Próbuję utworzyć tablicę ciągów znaków w C. Jeśli użyję tego kodu:
char (*a[2])[14];
a[0]="blah";
a[1]="hmm";
gcc daje mi „ostrzeżenie: przypisanie z niezgodnego typu wskaźnika”. Jaki jest właściwy sposób to zrobić?
edytuj: Jestem ciekawy, dlaczego powinno to dać kompilatorowi ostrzeżenie, ponieważ jeśli to zrobię printf(a[1]);
, to poprawnie wypisuje „hmm”.
char (*a[2])[14]
jest to tablica dwóch wskaźników do tablicy 14 znaków.char (*a[2])[14]
- zacznij oda
, przesuń w prawo: „tablica dwóch”, przesuń w lewo: „wskaźnik do”, nawias zakończony, więc przeczytaj w prawo: „tablica czternastu”, przeczytaj w lewo: „char” ... Złóż to i mamy „a to tablica dwóch wskaźników do tablic czternastu znaków”char *str
zamiastchar* str
. Pochodząc z Delphi / Pascal, byłem bardzo przyzwyczajony do tej drugiej drogi, dopóki nie natknąłem się na bardziej złożone typy. Ten pierwszy sposób nadal wydaje mi się brzydki, ale sprawia, że notacja typu jest bardziej spójna (IMO).Odpowiedzi:
Jeśli nie chcesz zmieniać ciągów, możesz po prostu to zrobić
Kiedy zrobisz to w ten sposób, przydzielisz tablicę dwóch wskaźników
const char
. Wskaźniki te zostaną następnie ustawione na adresy ciągów statycznych"blah"
i"hmm"
.Jeśli chcesz mieć możliwość zmiany rzeczywistej zawartości łańcucha, musisz zrobić coś takiego
Spowoduje to przydzielenie dwóch kolejnych tablic po 14
char
sekund, po których zawartość ciągów statycznych zostanie do nich skopiowana.źródło
Istnieje kilka sposobów utworzenia tablicy ciągów w C. Jeśli wszystkie ciągi będą mieć tę samą długość (lub przynajmniej taką samą maksymalną długość), wystarczy zadeklarować tablicę 2-d char i przypisać w razie potrzeby:
Możesz także dodać listę inicjatorów:
Zakłada się, że rozmiar i liczba łańcuchów w inicjalizatorze pasują do wymiarów tablicy. W tym przypadku zawartość każdego literału łańcuchowego (który sam jest tablicą znaków zakończoną zerem) jest kopiowana do pamięci przydzielonej do łańcuchów. Problemem w tym podejściu jest możliwość fragmentacji wewnętrznej; jeśli masz 99 łańcuchów, które mają 5 znaków lub mniej, ale 1 łańcuch o długości 20 znaków, 99 łańcuchów będzie zawierać co najmniej 15 nieużywanych znaków; to strata miejsca.
Zamiast używać dwuwymiarowej tablicy znaków, możesz przechowywać tablicę jednowymiarowych wskaźników do znaku:
Zauważ, że w tym przypadku pamięć została przydzielona tylko do przechowywania wskaźników do ciągów; pamięć dla samych łańcuchów musi być przydzielona gdzie indziej (jako tablice statyczne lub za pomocą
malloc()
lubcalloc()
). Możesz użyć listy inicjalizacyjnej jak we wcześniejszym przykładzie:Zamiast kopiować zawartość stałych ciągów, po prostu przechowujesz do nich wskaźniki. Zauważ, że stałe łańcuchowe mogą nie być zapisywalne; możesz ponownie przypisać wskaźnik, w ten sposób:
Ale możesz nie być w stanie zmienić zawartości łańcucha; to znaczy,
może nie być dozwolone.
Możesz użyć
malloc()
do dynamicznego przydzielania bufora dla każdego łańcucha i kopiowania do tego bufora:BTW,
Deklaruje jako 2-elementową tablicę wskaźników do 14-elementowych tablic char.
źródło
malloc
połączenia.T [N]
jest konwertowane na wyrażenie typuT *
, a wartością wyrażenia jest adres pierwszego elementu. Więc jeśli napiszeszstr = "foo"
, będziesz próbował przypisać adres pierwszej postaci"foo"
do tablicystr
, co nie działa. Zobacz tę odpowiedź, aby uzyskać więcej informacji.char *strs[NUMBER_OF_STRINGS] = {0};
Pomaga to zapobiec przyszłym problemom poprzez inicjowaniestrs
doNULL
. Wiele osób czyta ten post, gdy Google wyszukuje tablicę ciągów znaków w C.Ack! Stałe ciągi:
Jeżeli dobrze pamiętam.
Aha, i chcesz użyć strcpy do przypisania, a nie operatora =. strcpy_s jest bezpieczniejszy, ale nie jest ani w C89, ani w standardach C99.
Aktualizacja: Thomas mówi, że
strlcpy
jest to najlepsza droga.źródło
Oto niektóre z twoich opcji:
Zaletą
a2
jest to, że możesz wykonać następujące czynności z literałami łańcuchowymiA dla
a3
ciebie możesz wykonać następujące czynności:Bo
a1
będziesz musiał użyćstrcpy()
(jeszcze lepiejstrncpy()
), nawet przy przypisywaniu literałów łańcuchowych. Powodem jest toa2
, żea3
są to tablice wskaźników i możesz sprawić, aby ich elementy (tj. Wskaźniki) wskazywały na dowolną pamięć, podczas gdya1
jest tablicą „tablicy znaków”, a zatem każdy element jest tablicą, która „posiada” własną pamięć ( co oznacza, że ulega zniszczeniu, gdy wykracza poza zakres) - możesz kopiować tylko rzeczy do swojej pamięci.To także prowadzi do niekorzystnej strony używania
a2
ia3
- ponieważ wskazują one na przechowywanie statyczne (w którym przechowywane są literały łańcuchowe), którego zawartości nie można zmienić w niezawodny sposób (tj. Niezdefiniowane zachowanie), jeśli chcemy przypisać literały nie łańcuchowe do elementya2
luba3
- najpierw będziesz musiał dynamicznie przydzielić wystarczającą ilość pamięci, a następnie ich elementy wskażą tę pamięć, a następnie skopiuj do niej znaki - a następnie musisz pamiętać, aby cofnąć przydział pamięci po zakończeniu.Bah - już tęsknię za C ++;)
ps Daj mi znać, jeśli potrzebujesz przykładów.
źródło
Lub możesz zadeklarować typ struktury, który zawiera arry znaków (1 łańcuch), tworzą tablicę struktur, a tym samym tablicę wieloelementową
Jedną z zalet tego nad jakąkolwiek inną metodą jest to, że pozwala ci skanować bezpośrednio do łańcucha bez konieczności użycia
strcpy
;źródło
W ANSI C:
źródło
char* foo, bar;
jaki jest typbar
?Jeśli ciągi są statyczne, najlepiej jest:
Chociaż nie jest to część podstawowego ANSI C, istnieje prawdopodobieństwo, że twoje środowisko obsługuje składnię. Ciągi te są niezmienne (tylko do odczytu), dlatego w wielu środowiskach zużywają mniej obciążenia niż dynamiczne budowanie tablicy ciągów.
Na przykład w małych projektach mikrokontrolerów ta składnia wykorzystuje pamięć programu zamiast (zwykle) cenniejszej pamięci RAM. AVR-C to przykładowe środowisko obsługujące tę składnię, ale podobnie jak większość innych.
źródło
Jeśli nie chcesz śledzić liczby ciągów w tablicy i chcesz iterować nad nimi, po prostu dodaj na końcu ciąg NULL:
źródło
Literały łańcuchowe to
const char *
s.A twoje użycie nawiasu jest dziwne. Prawdopodobnie masz na myśli
który deklaruje tablicę dwóch wskaźników do stałych znaków i inicjuje je, aby wskazywały na dwie stałe w łańcuchu znaków.
źródło
Twój kod tworzy tablicę wskaźników funkcji. Próbować
lub
zamiast.
Zobacz wikibooks do tablic i wskaźników
źródło
cześć, możesz spróbować tego poniżej:
dobry przykład użycia, tablica ciągów w c, jeśli chcesz
źródło
Tutaj spróbuj tego !!!
źródło
Brakowało mi w jakiś sposób bardziej dynamicznej tablicy ciągów, gdzie liczba ciągów może się zmieniać w zależności od wyboru w czasie wykonywania, ale w przeciwnym razie ciągi powinny zostać naprawione.
Skończyłem kodować fragment kodu w ten sposób:
char** ev
podnosi wskaźnik do ciągów tablic i zlicza liczbę używanych ciągów_countof
funkcji. (Podobne dosizeof(arr) / sizeof(arr[0])
).I jest dodatkowa konwersja Ansi na Unicode przy użyciu
A2T
makra, ale może to być opcjonalne w twoim przypadku.źródło
Dobrym sposobem jest zdefiniowanie łańcucha siebie.
To naprawdę takie proste.
źródło
;
, a jak to tworzy tablicę ciągów ?