Liczba elementów w tablicy char

Jakiego rodzaju funkcji mogę użyć, aby dowiedzieć się, ile elementów znajduje się w tablicy?

sizeof () podaje liczbę dostępnych „spacji”, więc nie działa dla mnie.

Komentarze

  • Czy możesz podać przykład? np. char foo [100] = "bar"; – czy to masz na myśli? Chcesz odpowiedzi: 3?
  • tak, że ' s prawo

Odpowiedź

Chcesz strlen.

 char foo [100] = "bar"; Serial.println (strlen (foo)); // --> prints 3  

Komentarze

  • Jeśli odpowiedź zadziałała dla Ciebie, kliknij przycisk " zaakceptuj " (wygląda jak zaznaczenie). Dzięki temu inne osoby będą wiedzieć, że rozwiązanie zadziałało.
  • Musiałem czekać kilka minut, aby to zrobić.
  • Pamiętaj, że będzie to działać tylko , jeśli dane w Twoim zawiera ciąg ascii i jest poprawnie zakończony znakiem null. Ponadto, jeśli masz długi ciąg w char[] i zastąpisz go krótszym ciągiem bez dodawania zakończenia zerowego, otrzymasz rozmiar starszego ciągu.
  • Całkiem dobrze. Moja odpowiedź była na przedstawione pytanie. To, o czym wspomniałeś, należy wziąć pod uwagę w przypadku ciągów znaków C zakończonych znakiem null.

Odpowiedź

Znam cię mam swoją odpowiedź od @NickGammon, ale chciałbym tylko dodać nieco więcej szczegółowych informacji o tym, jak to wszystko działa.

sizeof() nie jest funkcja w normalnym znaczeniu tego słowa. Jest to operator, który podaje liczbę bajtów pamięci przydzielonych do tego, co do niej przekażesz. Jeśli przekażesz mu tablicę, zwróci liczbę bajtów, które tablica ma do dyspozycji. Jeśli przekażesz mu wskaźnik do tablicy, to zwróci rozmiar tego wskaźnika, a nie rozmiar tablicy. Jeśli przekażesz mu zmienną całkowitą, zwraca liczbę bajtów używanych przez tę zmienną całkowitą (2 na 8-bitowej system taki jak AVR, 4 w systemie 32-bitowym, takim jak Due).

Oto kilka przykładów:

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 

Teraz strlen(). Czym dokładnie różni się to od sizeof()? Mówiąc najprościej, zlicza liczbę znaków w tablicy znaków, aż osiągnie znak \0, który jest znakiem kończącym„ NULL ”w łańcuchu C. Weźmy przykłady wcześniej, ale zamiast tego użyj strlen:

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. 

Zauważasz, że zawsze zwraca liczbę znaków w ciągu do, ale nie wliczając, końcowy znak \0.

W najprostszej postaci funkcja strlen() może wyglądać następująco:

int strlen(const char *data) { int c = 0; const char *p = data; while (*p) { c++; p++; } return c; } 

Zasadniczo zaczyna się od pierwszego znaku w ciągu (*p = data), sprawdza, czy „jest \0 lub nie (while (*p)), zwiększa liczbę znaków (c++) i przechodzi do następnego znaku w ciągu (p++).

Jeśli chcesz iterować po swoim ciągu w programie, możesz wywołać strlen() najpierw, aby uzyskać liczbę znaków w ciągu, a następnie użyj tej wartości w pętli. To trochę marnotrawstwo, ponieważ strlen() najpierw iteruje przez ciąg, więc w końcu powtarzasz go dwukrotnie. O wiele bardziej efektywne jest nauczenie się, jak najlepiej przechodzić przez każdy znak w ciągu, aż znajdziesz znak kończący, na przykład jak funkcja strlen() używa wskaźnika poruszać się po pamięci. Możesz również zobaczyć, jak ważne jest, aby upewnić się, że znak \0 istnieje na końcu ciągu, w przeciwnym razie jak będzie działać, jak strlen() wiem, kiedy przestać? Nie mogą wiedzieć, jak długi jest ciąg (sizeof() zwróci rozmiar przekazywanego wskaźnika, a nie rozmiar tablicy), więc muszą mieć jakiś rodzaj znacznik ręczny, a konwencją w C jest użycie \0.

Zwróć uwagę, że Arduino „s print() faktycznie działa zrobić to bardzo nieefektywnie. Jeśli zrobisz coś takiego:

char message[] = "Hello"; Serial.println(message); 

W rzeczywistości wykona sporo pracy, której nie naprawdę musi. krok po kroku to:

  1. wywołuje println (wiadomość)
  2. która wywołuje write (wiadomość)
  3. która pobiera długość ciągu ze strlen (wiadomość)
  4. i wywołuje write (message, length)
  5. , który następnie zapętla od 0 do length-1, wysyłając po kolei każdy znak wiadomości do funkcji write ().
  6. w końcu wypisuje \r\n dla nowej linii.

Więc w rzeczywistości kończy się zagnieżdżeniem wokół 4 funkcji i dwukrotnie iteruje cały ciąg. klasyczny przykład marnowania czasu przetwarzania.Po wykonaniu iteracji po ciągu w poszukiwaniu znaku \0 w funkcji write(message) (krok 2) działałoby co najmniej dwa razy szybciej. Stare, dobre Arduino …

Komentarze

  • Re „W najprostszej formie funkcja strlen () może wyglądać tak”, w krótszym ( może prostsza?) forma mogłaby wyglądać następująco: int strlen(const char *data) { const char *p = data; while (*p++); return p-data-1; }
  • @ jwpat7 Powiedziałem " najprostszy ", a nie " najkrótsza i najbardziej kompaktowa ". Ta forma, choć mniejsza i wydajniejsza, jest znacznie trudniejsza do zrozumienia dla OP (który oczywiście nie jest programistą).
  • Zgoda 🙂 Również łatwiej jest popełniać błędy w . A jeśli \0 jest ostatnim dostępnym bajtem w segmencie, *p++ zakończy się błędem. Ale int strlen(const char *data) { const char *p = data; while (*p) ++p; return p-data; } pozwala uniknąć tego problemu.
  • Właściwie *p++ wygrał ' t błąd, nawet jeśli \0 jest ostatnim dostępnym bajtem w segmencie; część *p uzyska dostęp do ostatniego bajtu; część ++ ustawi p na nieprawidłowy adres; ale ponieważ ten nieprawidłowy adres nie ' nie jest przywoływany, na typowej maszynie nie występuje błąd.
  • Jest to makro kompilowane w czasie … To ' nie jest makrem , ' jest operatorem (na przykład " + " i " – " są operatorami). Są niższego poziomu niż makra, które są wykonywane w czasie preprocesora. Patrz operator rozmiaru . Ponadto Operatory w C ++

Odpowiedź

 use sizeof char nnn[10]; for(int i=0; i< sizeof(nnn)/sizeof(char); i++){ } 

Komentarze

  • Czy dobrze przeczytałeś pytanie?
  • Operator powiedział: sizeof " nie ' nie działa dla mnie " i to sugerujesz użycie sizeof.
  • nie mogę odpowiedzieć na pytanie, używając tego samego nieznanego

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *