Jakie są szczegóły definicji ciągu w C?

10

Mam odpowiedzieć na pytanie o pracę domową dla jednej z moich klas. W szczególności mam powiedzieć, czy niektóre tablice w C są uważane za łańcuchy, czy nie. Na podstawie tego artykułu ( https://www.geeksforgeeks.org/strings-in-c-2/ ) wiem, że ciągi znaków to tablica znaków z zakończeniem zerowym na końcu.

Moje główne zawieszenie jest częścią pytania, które dotyczy tablicy, która wygląda następująco:

char c1[] = { 'C', 'S', '\0', '3', '2', '4', '\0' };

Jest to oczywiście tablica znaków ze znakiem kończącym na zero na końcu. Czy jednak nadal jest uważany za ciąg, ponieważ ma również znak kończący na zero w środku? Jak to wpłynie na ciąg?

EDYCJA: Na podstawie komentarzy podałem rzeczywiste brzmienie pytania:

„Które z poniższych tablic można uznać za„ ciągi ”w celu wykorzystania ich jako argumentów funkcji strcpy (), strncpy (), strcmp (), strncmp () i podobnych funkcji ciągu (wskazać wszystkie obowiązujące)?”

EDYCJA: Wysłałem e-mail do mojego profesora na ten temat, ponieważ pytanie wydawało się dwuznacznie sformułowane (jak zauważyło kilka osób). Jeśli ktoś jest ciekawy, powiedział mi: „Tak, to ciąg znaków. Kluczem jest to, że istnieje znak zerowy. Ale oczywiście będzie to miało wpływ na wszelkie operacje na łańcuchach; łańcuch kończy się na znaku zerowym”.

quango
źródło
4
Można powiedzieć, że jest to ciąg "CS"z dołączonymi kilkoma bajtami śmieci (w takim przypadku końcowy znak NUL nie ma znaczenia). Ale to nie jest ciąg „jako całość”. - Niemniej jednak karmienie tego strcpyitp. Nie spowoduje wybuchu komputera, ponieważ funkcje te będą „widzieć” tylko "CS"część.
Hagen von Eitzen
2
c1 może być absolutnie użyte jako argument strcmp(). To, czy można go użyć jako argumentu do mutowania funkcji łańcuchowych, zależy od dodatkowych czynników, których nie podano.
EOF
2
Zawartość c1jest zmienna, więc nie rozumiem, dlaczego nie byłby prawidłowym argumentem docelowym strcpylub podobnym, chyba że nie był wystarczająco duży, aby pomieścić łańcuch źródłowy. To nie oznaczałoby, że nie byłby to sznurek, tylko nieodpowiedni do określonego celu.
John Bollinger
1
Ogólnie rzecz biorąc, zgadzam się, że pytanie jest dwuznacznie sformułowane. Wyrażenie c1spełniałoby podstawowe wymagania dotyczące argumentów łańcuchowych dla wszystkich funkcji łańcuchowych biblioteki standardowej (wąskich), w tym wszystkich tych specjalnie nazwanych, ale zachowanie może nie być tym, czego osoba wywołująca oczekuje lub chce (nawet ignorując niezdefiniowane zachowania, które można wywołać).
John Bollinger
1
Pamiętaj, że typ nie musi być char. Wystarczy dowolny typ postaci .
chux - Przywróć Monikę

Odpowiedzi:

8

c1jest zasadniczo [1] równoważna &c1[0], która posiada jeden łańcuch, "CS".

Jest to drugi ciąg czai się tam "324", zaczynając &c1[3]- ale tak długo, jak masz dostęp c1jako c1, łańcuch "CS"ma wszystkie funkcje strcpy()et al. zobaczyłby.


[1]: c1jest tablicą, &c1[0]jest wskaźnikiem.

DevSolar
źródło
Czy zatem należy używać c1ciągu docelowego w strcpy()poleceniu? Pytanie jest niejednoznaczne - w najlepszym razie.
Andrew Henle
1
Oczywiście możesz użyć c1jako argumentu do strcpy(). Jest to całkowicie zwyczajna struna pod każdym względem. Zwykłe ciągi znaków często zawierają resztki śmieci po ich terminatorach. Fakt, że te śmieci są zakodowane na stałe w programie, sprawia wrażenie, że autor zamierza użyć ich c1w sposób nieciągowy, ale nie było to częścią pytania.
Lee Daniel Crocker
c1jest równoważne z &c1[0]” wprowadzającymi w błąd. c1jest tablicą. &c1[0]jest wskaźnikiem.
chux - Przywróć Monikę
2

Jeśli chcesz poznać specyfikę definicji łańcucha w C, przejdź do źródła.

Od standardu C90 :

7 Biblioteka

7.1 Wprowadzenie

7.1.1 Definicje terminów ciąg jest ciągła sekwencja znaków zakończone włącznie pierwszego znaku null. „Wskaźnik do” łańcucha to wskaźnik do jego początkowego (najniższego adresowanego) znaku. „Długość” ciągu to liczba znaków poprzedzających znak zerowy, a jego „wartość” to kolejność wartości zawartych znaków, w kolejności.

(Nie wprowadzono żadnych istotnych zmian w późniejszych standardach).

Tak więc c1zawiera dwa kolejne ciągi „CS” i „324”, ale sam nie jest ciągiem.

Jeśli przekażemy tablicę do funkcji, rozkłada się ona na wskaźnik do jej pierwszego elementu, a tym samym +c1wskazuje na ciąg znaków (pierwszy), który jest wystarczający dla każdej funkcji oczekującej wskaźnika na ciąg. Nie wskazuje na ciąg „CS \ 0324”, ale prawdopodobnie wystarcza to na pytanie instruktora, co jest dwuznaczne.

Deduplikator
źródło
4
Argumentowałbym, że nawet przy tej definicji c1 jest wyraźnie ciągiem „CS”. Kropka. Fakt, że może on zawierać niezerowe bajty po terminatorze, jest nieistotny - wiele łańcuchów będzie podobnych w ciągu swojego życia.
Lee Daniel Crocker
+c1wskazuje na ciąg, ponieważ c1zaczyna się od ciągu. Nie ma to jednak żadnego kształtu, kształtu ani formy c1.
Deduplicator
2
Jest to adres sekcji pamięci, która zawiera niektóre znaki zakończone bajtem zerowym. Gdyby printf () dobrze działał z% s, dałby idealnie dobrą liczbę przekazywaną do strlen (), działałby, gdyby był przekazany do strcpy () itp. Brzmi dla mnie jak ciąg znaków.
Lee Daniel Crocker
Oczywiście. Ale tablice z pewnością mogą być łańcuchami.
Lee Daniel Crocker
0

Dodając do odpowiedzi @ DevSolar, coś odkryłem po zabawie danym ciągiem, jeśli miałoby to być:

char c1[] = { 'C', 'S', '\\0', '3', '2', '4', '\\0' };

Jeśli wypiszesz ten ciąg, otrzymasz, CS03240a jego rozmiar wynosi 7. O ile mi wiadomo, \\0jest używany do oznaczenia znaku zerowego ( tj \0 .). Jeśli zrobisz:

printf("\0");

Nic nie widać w dzienniku wyjściowym, ale jeśli:

printf("\\0");

Widzisz \0coś, co jest oczekiwane, ponieważ aby wypisać znaki specjalne, takie jak ukośniki odwrotne lub cudzysłowy, musisz użyć \wraz z nimi.

Coś, co mnie zastanawia, to wynik CS03240i jego rozmiar 7. Powszechnie rozumie się, że rozmiar łańcucha to liczba znaków plus jeden (dla znaku zerowego). Również rozmiar jest 7 nawet do łańcucha, char c1[] = { 'C', 'S', '\0', '3', '2', '4', '\0' };.

Więc może kontynuacja tego pytania, co się tutaj dzieje?

rasengan__
źródło
1
'\\0'nie jest znakiem zerowym . Jest to stała wieloznakowa. Ma określoną wartość implementacyjną z pewnością poza zakresem char. c1[]nie jest łańcuchem, ponieważ nie ma znaku zerowego . „wyprowadzasz ten ciąg” prawdopodobnie spowoduje niezdefiniowane zachowanie .
chux - Przywróć Monikę
Nie zrozumiałem cię dokładnie, ale szukałem stałych wielu postaci. Jeśli c1 [] nie jest łańcuchem, ponieważ nie ma na końcu znaku zerowego, to dlaczego rozmiar wychodzi jako 7 w pierwszym przypadku, jak podano w PO?
rasengan__
char c1[] = { 'C', 'S', '\0', '3', '2', '4', '\0' };ma rozmiar 7, ponieważ jest inicjowany 7 wartościami. To wielkość nie ma nic wspólnego ze strun . char c1[] = { 1, 2, 3, 4, 5, 6, 7 };nadal miałby rozmiar 7.
Chux - Przywróć Monikę
Co do tablicy c1zawiera żądło? To osobny problem. Zobacz także
chux - Przywróć Monikę