Milyen funkcióval tudom megtudni, hogy hány elem van egy tömb karakterben?
A sizeof () megadja a rendelkezésre álló “szóközök” számát, így nekem nem fog működni.
Megjegyzések
Válasz
A következőre kíváncsi: strlen
.
char foo [100] = "bar"; Serial.println (strlen (foo)); // --> prints 3
Megjegyzések
- Ha a válasz neked bevált, kérlek kattints a " accept " gombra (úgy tűnik, mint egy pipa). Így mások tudják, hogy a megoldás működött.
- Ehhez pár percet kellett várnom.
- Vegye figyelembe, hogy ez csak akkor működik, ha a egy ascii karakterláncot tartalmaz, és megfelelően null-végű. Továbbá, ha van egy hosszú karakterlánc a
char[]
-ben, és rövidebb karakterlánccsal írja felül, anélkül, hogy hozzáadná a null-megszüntetést, akkor megkapja a régebbi karakterlánc méretét. - Teljesen helyes. Válaszom a bemutatott kérdésre volt. Az általad említett dolgokat figyelembe kell venni a nullaszerű C karakterláncoknál.
Válasz
Ismerlek válaszoljon a @NickGammon címre, de én csak egy kicsit részletesebb információt szeretnék hozzáadni mindezek működéséről.
sizeof()
nem függvény a szó normális értelmében. Ez egy operátor, amely megadja a kiosztott memória bájtjainak számát. Ha átad egy tömböt, akkor visszaadja a tömb számára elérhető bájtok számát. Ha átad egy mutatót egy tömbnek, akkor az a mutató méretét adja vissza, nem a tömb méretét. Ha egy egész változót ad át, akkor az egész változó által használt bájtok számát adja vissza (2-t egy 8-bitesen) rendszer, például AVR, 4 egy 32 bites rendszeren, például a Due).
Tehát néhány példa:
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
Most strlen()
. Ez pontosan miben különbözik a sizeof()
-től? Egyszerűen fogalmazva: addig számolja a karaktertömbök karaktereinek számát, amíg el nem éri a \0
karaktert, amely egy C karakterlánc” NULL “befejező karaktere. Vegyük a példákat korábban, de használjuk inkább a strlen szót:
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.
Észreveszi, hogy mindig a karakterláncok számát adja vissza legfeljebb, de nem tartalmazza, a záró \0
karakter.
Egyszerűbb formájában a strlen()
függvény így nézhet ki:
int strlen(const char *data) { int c = 0; const char *p = data; while (*p) { c++; p++; } return c; }
Alapvetően a karakterlánc első karakterétől kezdődik (*p = data
), megvizsgálja, hogy “sa \0
vagy sem (while (*p)
), növeli a karakterek számát (c++
), és továbblép a következő karakterre a karakterláncban (p++
).
Ha a programban a karakterláncon keresztül szeretne iterálni, hívhatja a strlen()
először megkapja a karakterláncok számát, majd használja ezt az értéket egy hurokban. Ez kissé pazarló, mivel a strlen()
először a sztringen keresztül iterál, így végül kétszer is végigmegy rajta. Sokkal hatékonyabb megtanulni, hogy miként lehet a karakterláncban minden egyes karaktert végiglépni, amíg meg nem találja a befejező karaktert, például azt, hogy a strlen()
függvény hogyan használja a mutatót a memóriában való mozgáshoz. Láthatja azt is, mennyire fontos, hogy megbizonyosodjon arról, hogy a \0
karakter létezik-e a karakterlánc végén, különben hogyan fognak működni, például a strlen()
tudja, mikor kell megállni? Nem tudhatják, hogy a karakterlánc mennyi ideig tart (sizeof()
visszaadja az átadott mutató méretét, nem pedig a tömb méretét), ezért valamilyen kézi jelölő, és a C-ben a \0
használata.
Ne feledje, hogy az Arduino “s print()
funkciói valójában csináld nagyon hatástalanul. Ha ilyesmit csinál:
char message[] = "Hello"; Serial.println(message);
Valójában nagyon sok munkát fog elvégezni, amire “nincs valójában szüksége.” lépésről lépésre:
- hívja a println (üzenet)
- amely felhívja az írást (üzenet)
- amely a string hosszúságot kapja meg strlen (üzenet)
- és felhívja az írást (üzenet, hossz)
- amely ezt követően 0-tól 1-ig terjed, és az üzenet minden karakterét felváltva () írja.
- végül kinyomtatja a
\r\n
-t az új sorhoz.
Tehát valójában 4 függvény mélyén beágyazva végződik, és kétszer iterálja az egész karakterláncot. klasszikus példa arra, hogyan pazaroljuk a feldolgozási időt.A karakterláncon keresztüli iterációval, ha egyszer megkeresi a \0
karaktert a write(message)
függvényben (2. lépés), akkor legalább kétszer olyan gyorsan működik. A jó öreg Arduino …
Megjegyzések
- Re “A strlen () függvény a legegyszerűbb formájában így nézhet ki”, röviden ( talán egyszerűbb?) forma a következőképpen nézhet ki:
int strlen(const char *data) { const char *p = data; while (*p++); return p-data-1; }
- @ jwpat7 Mondtam, hogy " legegyszerűbb ", nem " legrövidebb és legkompaktabb ". Ezt a formát, bár kisebb és hatékonyabb, sokkal nehezebb megérteni az OP-nak (aki nyilván nem programozó).
- Egyetértett 🙂 Könnyebben hibázhat És ha a
\0
az utolsó hozzáférhető bájt a szegmensben, akkor a*p++
hibát okoz. Deint strlen(const char *data) { const char *p = data; while (*p) ++p; return p-data; }
elkerüli ezt a problémát. - Valójában
*p++
nyert ' t hiba akkor is, ha a\0
az utolsó hozzáférhető bájt a szegmensben; az*p
rész hozzáfér az utolsó bájthoz; a ++ rész érvénytelen címre állítja ap
-et; de mivel ez az érvénytelen cím nem hivatkozik ' t, egy tipikus gépen nem történik hiba. - Ez egy fordítási idejű makró … Ez ' nem makró , hanem ' s operátor (például " + " és " – " operátorok). Alacsonyabb szintűek, mint a makrók, amelyek a processzor előtti időben történnek. Lásd: operátor mérete . Szintén operátorok a C ++ rendszerben
Válasz
use sizeof char nnn[10]; for(int i=0; i< sizeof(nnn)/sizeof(char); i++){ }
Megjegyzések
- Helyesen olvastad a kérdést?
- Az OP szerint
sizeof
" nem ' nem működik nekem " és akkor javasoljuk a sizeof használatát. - nem válaszolhat a kérdésre, ha ugyanazt az ismeretlenet használja
char foo [100] = "bar";
– erre gondolsz? A választ akarod kapni: 3?