Hvilken slags funktion kan jeg bruge til at vide, hvor mange elementer der er i en array-char?
sizeof () giver antallet af “mellemrum” til rådighed, så det ikke virker for mig.
Kommentarer
Svar
Du vil have strlen
.
char foo [100] = "bar"; Serial.println (strlen (foo)); // --> prints 3
Kommentarer
- Hvis svaret fungerede for dig, klik på " accept " -knappen (det ser ud som et kryds). På den måde vil andre mennesker vide, at løsningen fungerede.
- Jeg måtte vente et par minutter på at gøre det
- Bemærk at dette kun fungerer hvis dataene i din indeholder en ascii-streng og er korrekt null-termineret. Desuden, hvis du har en lang streng i
char[]
, og du overskriver den med en kortere streng uden at tilføje null-terminering, får du størrelsen på den ældre streng. - Helt rigtigt. Mit svar var på spørgsmålet som præsenteret. De ting, du nævner, skal tages i betragtning for null-afsluttede C-strenge.
Svar
Jeg kender dig har dit svar fra @NickGammon, men jeg vil bare gerne tilføje lidt mere detaljerede oplysninger om, hvordan alt dette fungerer.
sizeof()
er ikke en funktion i ordets normale forstand. Det er en operatør, der giver dig antallet af hukommelsesbyte, der er allokeret til det, du sender til det. Hvis du sender det til et array, returnerer det antallet af bytes, som arrayet har til rådighed for det. Hvis du sender den en markør til en matrix, returnerer den størrelsen på den pågældende markør, ikke størrelsen på arrayet. Hvis du sender den til et heltalsvariabel, returnerer det antallet af byte, der er brugt af denne heltalsvariabel (2 på en 8-bit system som AVR, 4 på et 32-bit system som Due).
Så nogle eksempler:
char array[50] = "hello"; // sizeof(array) = 50. char *array_p = array; // sizeof(array_p) = 2 or 4 depending on architecture. char single = "a"; // sizeof(single) = 1. char string[] = "hello"; // sizeof(string) = 6 (5 letters plus \0) - it allocates the memory at compile time to fit the string
Nu strlen()
. Hvordan adskiller det sig nøjagtigt fra sizeof()
? Enkelt sagt, tæller antallet af tegn i et tegnarray, indtil det når tegnet \0
, som er den” NULL “afslutningskarakter af en C-streng. Lad os tage eksemplerne før, men brug strlen i stedet:
char array[50] = "hello"; // strlen(array) = 5. char *array_p = array; // strlen(array_p) = 5. char single = "a"; // strlen(single) = ERROR! strlen() doesn"t operate on single characters. char string[] = "hello"; // strlen(string) = 5.
Du bemærker, at det altid returnerer antallet af tegn i strengen op til, men inkluderer ikke, den efterfølgende \0
karakter.
I sin enkleste form kan funktionen strlen()
se sådan ud:
int strlen(const char *data) { int c = 0; const char *p = data; while (*p) { c++; p++; } return c; }
Grundlæggende starter det ved det første tegn i strengen (*p = data
), undersøger om det er “sa \0
eller ej (while (*p)
), øger antallet af tegn (c++
) og går videre til det næste tegn i strengen (p++
).
Hvis du vil gentage gennem din streng i dit program, kan du ringe til strlen()
først for at få antallet af tegn i strengen, brug derefter denne værdi i en løkke. Det er en smule spild, da strlen()
først gentages gennem strengen, så du ender med at gentage gennem den to gange. Det er langt mere effektivt at lære, hvordan man bedst kan gå gennem hvert tegn i strengen, indtil du finder det afsluttende tegn, såsom hvordan strlen()
-funktionen bruger markøren for at bevæge sig gennem hukommelsen. Du kan også se, hvor vigtigt det er, at du sørger for, at \0
-tegnet findes i slutningen af strengen, ellers hvordan fungerer funktioner som strlen()
ved hvornår du skal stoppe? De kan ikke vide, hvor lang strengen er (sizeof()
vil returnere størrelsen på den markør, den sendes, ikke størrelsen på arrayet), så de skal have en slags manuel markør, og konventionen i C er at bruge \0
.
Bemærk, at Arduino “s print()
faktisk fungerer gør det meget ineffektivt. Hvis du gør noget som:
char message[] = "Hello"; Serial.println(message);
Det vil faktisk gøre en hel del arbejde, det behøver det ikke virkelig . trin for trin det:
- kalder println (besked)
- hvilke opkald skriv (besked)
- som får strenglængden med strlen (besked)
- og kalder skrivning (besked, længde)
- som derefter sløjfer fra 0 til længde-1 og sender hvert tegn i meddelelsen til at skrive () igen.
- til sidst udskriver
\r\n
til den nye linje.
Så det slutter faktisk indlejret omkring 4 funktioner dybt og gentager hele strengen to gange. klassisk eksempel på, hvordan man spilder behandlingstid.Ved at gentage gennem strengen en gang på udkig efter \0
-tegnet i write(message)
-funktionen (trin 2) fungerer den mindst dobbelt så hurtigt. Gode gamle Arduino …
Kommentarer
- Re “I sin enkleste form kan strlen () -funktionen se sådan ud”, i en kortere ( måske enklere?) form kunne det se ud:
int strlen(const char *data) { const char *p = data; while (*p++); return p-data-1; }
- @ jwpat7 Jeg sagde " enkleste ", ikke " korteste og mest kompakte ". Denne form, selvom den er mindre og mere effektiv, er meget meget sværere for OP (som selvfølgelig ikke er ikke en programmør) at forstå.
- Enig 🙂 Også lettere at begå fejl i Og hvis
\0
er den sidst tilgængelige byte i et segment, er*p++
fejl. Menint strlen(const char *data) { const char *p = data; while (*p) ++p; return p-data; }
undgår det problem. - Faktisk,
*p++
vandt ' t fejl, selvom\0
er den sidst tilgængelige byte i et segment;*p
-delen får adgang til den sidste byte; ++ – delen indstillerp
til en ugyldig adresse; men da den ugyldige adresse ikke ' ikke bliver henvist til, forekommer der ikke en fejl på en typisk maskine. - Det er en makro til kompileringstid … Det ' er ikke en makro , det ' er en operatør (som " + " og " – " er operatører). De er lavere end makroer, hvilket er ting, der gøres på præ-processor tid. Se operatorstørrelse . Også Operatører i C ++
Svar
use sizeof char nnn[10]; for(int i=0; i< sizeof(nnn)/sizeof(char); i++){ }
Kommentarer
- Læste du ordentligt spørgsmålet?
- OP sagde
sizeof
" fungerer ikke ' for mig " og så foreslår du at bruge sizeof. - kan; ikke besvare spørgsmålet, når du bruger det samme ukendte
char foo [100] = "bar";
– er det hvad du mener? Du vil have svaret: 3?