Vilken typ av funktion kan jag använda för att veta hur många element som finns i en array char?
sizeof () ger antalet tillgängliga ”mellanslag” så att det inte fungerar för mig.
Kommentarer
Svar
Du vill ha strlen
.
char foo [100] = "bar"; Serial.println (strlen (foo)); // --> prints 3
Kommentarer
- Om svaret fungerade för dig, klicka på " acceptera " -knappen (det ser ut som en bock). På det sättet kommer andra att veta att lösningen fungerade.
- Jag var tvungen att vänta några minuter för att göra det
- Observera att detta bara fungerar om data i din innehåller en ascii-sträng och är ordentligt nollavslutad. Om du dessutom har en lång sträng i
char[]
, och du skriver över den med en kortare sträng utan att lägga till null-termination, får du storleken på den äldre strängen. - Helt rätt. Mitt svar var för frågan som presenterades. De saker du nämner bör tas i beaktande för null-avslutade C-strängar.
Svar
Jag känner dig har ditt svar från @NickGammon, men jag vill bara lägga till lite mer fördjupad information om hur allt detta fungerar.
sizeof()
är inte ett funktion i ordets normala bemärkelse. Det är en operatör som ger dig antalet byte minne tilldelat vad du än skickar till det. Om du skickar det till en matris returnerar det antalet byte som matrisen har tillgängligt för den. Om du skickar den en pekare till en matris returnerar den storleken på den pekaren, inte storleken på matrisen. Om du skickar den till en heltalvariabel returnerar den antalet byte som används av den heltalvariabeln (2 på en 8-bitars system som AVR, 4 på ett 32-bitars system som Due).
Så några exempel:
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()
. Hur exakt skiljer sig det från sizeof()
? Enkelt uttryckt, räknar antalet tecken i en teckenmatris tills den når tecknet \0
vilket är den” NULL ”avslutande karaktären i en C-sträng. Låt oss ta exemplen innan, men använd strlen istället:
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 märker att det alltid returnerar antalet tecken i strängen upp till, men inte inkluderar, det efterföljande \0
-tecknet.
I sin enklaste form kan funktionen strlen()
se ut så här:
int strlen(const char *data) { int c = 0; const char *p = data; while (*p) { c++; p++; } return c; }
I grund och botten börjar det vid första tecknet i strängen (*p = data
), undersöker om det är ”sa \0
eller inte (while (*p)
), ökar antalet tecken (c++
) och går vidare till nästa tecken i strängen (p++
).
Om du vill itera igenom din sträng i ditt program kan du ringa strlen()
först för att få antalet tecken i strängen och använd det värdet i en slinga. Det är lite slösaktigt, eftersom strlen()
först itererar genom strängen, så att du slutar itera igenom den två gånger. Det är mycket effektivare att lära sig hur man bäst går igenom varje tecken i strängen tills du hittar den avslutande karaktären, till exempel hur strlen()
-funktionen använder pekaren för att gå igenom minnet. Du kan också se hur viktigt det är att du ser till att \0
-tecknet finns i slutet av strängen, annars fungerar hur strlen()
vet när man ska sluta? De kan inte veta hur lång strängen är (sizeof()
returnerar storleken på pekaren den passeras, inte storleken på arrayen), så de måste ha någon form av manuell markör, och konventionen i C är att använda \0
.
Observera att Arduino ”s print()
fungerar faktiskt gör det mycket ineffektivt. Om du gör något som:
char message[] = "Hello"; Serial.println(message);
Det kommer faktiskt att göra en hel del arbete, det behöver inte verkligen . steg för steg det:
- samtal println (meddelande)
- vilka samtal skriv (meddelande)
- som får stränglängden med strlen (meddelande)
- och samtalsskrivning (meddelande, längd)
- som sedan slingrar från 0 till längd-1 och skickar varje tecken i meddelandet för att skriva () i tur och ordning.
- slutligen skriver ut
\r\n
för den nya raden.
Så det slutar faktiskt kapslat runt fyra funktioner djupt och itererar hela strängen två gånger. klassiskt exempel på hur man slösar bort behandlingstid.Genom att itera igenom strängen en gång och leta efter \0
karaktär i write(message)
-funktionen (steg 2) skulle den fungera minst dubbelt så snabbt. Gamla bra Arduino …
Kommentarer
- Re ”I sin enklaste form kan strlen () -funktionen se ut så här”, i en kortare ( kanske enklare?) i form kan det se ut:
int strlen(const char *data) { const char *p = data; while (*p++); return p-data-1; }
- @ jwpat7 Jag sa " enklaste ", inte " kortaste och mest kompakta ". Den formen, även om den är mindre och effektivare, är mycket mycket svårare för OP (som uppenbarligen inte är inte en programmerare) att förstå.
- Enas 🙂 Också lättare att göra misstag i Och om
\0
är den senast tillgängliga byten i ett segment, kommer*p++
fel. Menint strlen(const char *data) { const char *p = data; while (*p) ++p; return p-data; }
undviker det problemet. - Egentligen
*p++
vann ' t fel även om\0
är den senast tillgängliga byten i ett segment;*p
-delen kommer åt den sista byten; ++ -delen ställer inp
till en ogiltig adress; men eftersom den ogiltiga adressen inte ' inte hänvisas, inträffar inget fel på en typisk maskin. - Det är ett kompileringsmakro … Det ' är inte ett makro , det ' är en operatör (som " + " och " – " är operatörer). De är lägre än makron vilket är saker som görs vid tidpunkten för processorn. Se sizeof operator . Även Operatörer i C ++
Svar
use sizeof char nnn[10]; for(int i=0; i< sizeof(nnn)/sizeof(char); i++){ }
Kommentarer
- Har du läst frågan ordentligt?
- OP sa
sizeof
" fungerar inte ' t för mig " och då föreslår du att du använder sizeof. - kan inte svara på frågan när du använder samma okända
char foo [100] = "bar";
– är det vad du menar? Du vill ha svaret: 3?