У чому специфіка визначення рядка в C?


10

Я повинен відповісти на запитання домашнього завдання на одному з моїх занять. Зокрема, я повинен сказати, чи вважаються певні масиви на C рядками чи ні. На основі цієї статті ( https://www.geeksforgeeks.org/strings-in-c-2/ ) я знаю, що рядки - це масив символів із нульовим термінатором в кінці.

Моя головна повірка - це частина запитання про масив, який виглядає приблизно так:

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

Це, очевидно, масив символів з нульовим символом, що закінчується в кінці. Однак, чи все ж це вважається рядком, оскільки він також має нульовий завершальний характер посередині? Як це вплине на рядок?

EDIT: На підставі коментарів я надав фактичне формулювання питання:

"Який із перелічених нижче масивів можна вважати" рядками "для цілей використання їх як аргументів strcpy (), strncpy (), strcmp (), strncmp () та подібних рядкових функцій (вказати всі застосуванні)?"

РЕДАКТ: Я надіслав електронною поштою своєму професору, оскільки питання здавалося неоднозначним (як зазначали кілька людей). Якщо комусь цікаво, він сказав мені: "Так це рядок. Ключовим є те, що є нульовий символ. Але, звичайно, це призведе до будь-яких операцій рядка; рядок закінчується на нульовому символі".


4
Ви можете сказати, що це рядок "CS"із кількома байтами доданого сміття (у такому випадку остаточний символ NUL не має значення). Але це не рядок "в цілому". - Тим не менш, подача цього в strcpyінше не призведе до того, що ваш ПК вибухне, оскільки ці функції будуть "бачити" лише "CS"частину.
Хаген фон Ейтцен

2
c1 можна абсолютно використовувати як аргумент strcmp(). Чи може він використовуватися як аргумент мутації рядкових функцій, залежить від додаткових факторів, які не наводяться.
EOF

2
Вміст c1є змінним, тому я не бачу, чому він не стане дійсним аргументом призначення для strcpyподібного, якщо тільки він не був достатньо великим, щоб вмістити вихідний рядок. Це не зробить це не рядком, просто не підходящим для заданої мети.
Джон Боллінгер

1
Загалом, я згоден, що питання неоднозначно сформульовано. Вираз c1буде задовольняти основні вимоги до аргументів рядка для всіх (вузьких) рядкових функцій стандартної бібліотеки, включаючи всі ті, які спеціально названі, але поведінка може бути не такою, яку очікує або хоче абонент (навіть ігноруючи невизначені форми поведінки, які можуть бути викликані).
Джон Боллінгер

1
Зверніть увагу, що тип не повинен бути char. Буде робити будь-який тип символів .
chux

Відповіді:


8

c1здебільшого [1] еквівалент &c1[0], який містить одну струну,"CS" .

Там стоїть друга рядок "324", починаючи з &c1[3]- але до тих пір, поки ви маєте доступ c1до c1, рядок "CS"- це всі функції strcpy()та ін. побачив би.


[1]: c1це масив, &c1[0]вказівник.


Отже, чи правильно використовувати c1як цільовий рядок у strcpy()команді? Питання неоднозначне - в кращому випадку.
Ендрю Генле

1
Звичайно, ви можете використовувати c1як будь-який аргумент strcpy(). Це абсолютно звичайна струна в будь-якому сенсі. Звичайні рядки часто містять залишки сміття після своїх термінаторів. Той факт, що це сміття важко закодовано в програму, створює враження, що автор має намір використовувати c1неструмними способами, але це не було частиною питання.
Лі Даніел Крокер

" c1еквівалент &c1[0]" оманам. c1- це масив. &c1[0]- покажчик.
chux

2

Якщо ви хочете знати специфіку визначення рядка в C, перейдіть до джерела.

Від стандарту C90 :

7 Бібліотека

7.1 Вступ

7.1.1 Визначення термінів рядок являє собою безперервну послідовність символів , що перериваються і в тому числі першого нульового символу. Рядок "вказівник на" - це вказівник на його початковий (найнижчий адресальний) символ. "Довжина" рядка - це кількість символів, що передує нульовому символу, а його "значення" - це послідовність значень містяться символів в порядку.

(У пізніших стандартах не було відповідних змін.)

Таким чином, c1 містить два послідовних рядки "CS" і "324", але сам по собі не є рядком.

Якщо ми передамо масив функції, він занепадає до вказівника на його перший елемент, тим самим +c1вказує на рядок (перший), що досить добре для будь-якої функції, яка очікує, що вказівник на рядок. Це не вказує на рядок "CS \ 0324", але це, мабуть, досить добре для ваших інструкторських питань, що є неоднозначним.


4
Я б заперечував, що навіть за цим визначенням c1 явно є рядком "CS". Період. Той факт, що він може містити ненульові байти після термінатора, не має значення - багато рядків будуть такими протягом життя.
Лі Даніел Крокер

+c1вказує на рядок, тому що c1починається з рядка. Це ні в якому разі не має форми, ані форми c1.
Дедуплікатор

2
Це адреса розділу пам'яті, який містить деякі символи, закінчені нульовим байтом. Якщо було б printf () просто відмінним з% s, воно дало б ідеально хороше число, передане strlen (), працювало б, якби перейшло до strcpy () тощо. Здається мені.
Лі Даніел Крокер


Звичайно. Але масиви, безумовно, можуть бути рядками.
Лі Даніел Крокер

0

Додавши до відповіді @ DevSolar щось, що я виявив, погравшись із заданою струною, якби це було:

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

Якщо ви виведете цей рядок, ви отримаєте CS03240і розмір цієї рядка дорівнює 7. Наскільки я розумію, \\0використовується для позначення нульового символу ( тобто \0 ). Якщо ти зробиш:

printf("\0");

Ви нічого не бачите у журналі виводу, але якщо:

printf("\\0");

Ви бачите a \0, те, чого очікується, оскільки для виведення спеціальних символів, таких як зворотна косої риски або котирування, потрібно використовувати \разом з ними.

Те, що мене спантеличує, - це результат CS03240і його розмір 7. Загальновідомо, що розмір рядка - це кількість символів плюс один (для нульового символу). Крім того , розмір 7 навіть для рядка char c1[] = { 'C', 'S', '\0', '3', '2', '4', '\0' };.

То, можливо, слідкуйте за цим питанням, що тут відбувається?


1
'\\0'не є нульовим символом . Це константа багато символів. Він має значення, визначене реалізацією, безумовно, поза діапазоном char. c1[]не є рядком, оскільки він не має нульового символу . "Ви виводите цей рядок", ймовірно, призводить до невизначеної поведінки .
chux

Я не зрозумів тебе, хоча я шукав багатоконтурні константи. Якщо c1 [] не є рядком, оскільки він не має нульового символу в кінці, то чому розмір виходить як 7 у початковому випадку, як розміщено ОП?
rasengan__

char c1[] = { 'C', 'S', '\0', '3', '2', '4', '\0' };має розмір 7, оскільки він ініціалізується із 7 значеннями. Її розмір не має нічого спільного з рядками . char c1[] = { 1, 2, 3, 4, 5, 6, 7 };все-таки зробить його розміром 7.
chux - Відновіть Моніку

Як масив c1містить жало? Це окреме питання. Дивіться також
chux
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.