Каковы особенности определения строки в C?

10

Я должен ответить на домашнее задание для одного из моих занятий. В частности, я должен сказать, считаются ли определенные массивы в C строками или нет. Основываясь на этой статье ( https://www.geeksforgeeks.org/strings-in-c-2/ ), я знаю, что строки - это массив символов с нулевым терминатором в конце.

Мое основное зависание является частью вопроса, который задает вопрос о массиве, который выглядит следующим образом:

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

Это, очевидно, массив символов с нулевым завершающим символом в конце. Однако считается ли он строкой, поскольку в середине также есть нулевой завершающий символ? Как это повлияет на строку?

РЕДАКТИРОВАТЬ: На основе комментариев, я представил фактическую формулировку вопроса:

«Какие из следующих массивов можно считать« строками »в целях использования их в качестве аргументов функций strcpy (), strncpy (), strcmp (), strncmp () и аналогичных строковых (указать все применимые)?»

РЕДАКТИРОВАТЬ: я написал своему профессору по электронной почте об этом, так как вопрос казался неоднозначным (как отметили несколько человек). Если кому-то любопытно, он сказал мне: «Да, это строка. Ключ в том, что есть нулевой символ. Но, конечно, это повлияет на любые строковые операции; строка заканчивается нулевым символом».

quango
источник
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]это указатель.

DevSolar
источник
Итак, правильно ли использовать 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», но, вероятно, этого достаточно для вашего вопроса инструкторов, что неоднозначно.

Deduplicator
источник
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");

Вы видите \0что-то ожидаемое, потому что для вывода специальных символов, таких как обратная косая черта или кавычки, вы должны использовать \вместе с ними.

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

Так что, возможно, продолжение этого вопроса, что здесь происходит?

rasengan__
источник
1
'\\0'не нулевой символ . Это многосимвольная константа. Он имеет значение, определенное реализацией, определенно вне диапазона char. c1[]не является строкой, так как в ней отсутствует нулевой символ . «Вы выводите эту строку», вероятно, приводит к неопределенному поведению .
chux - Восстановить Монику
Я не совсем понял вас, хотя я искал много-символьные константы. Если c1 [] не является строкой, потому что в конце она не имеет нулевого символа, то почему размер в исходном случае равен 7, как указано в OP?
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 - Восстановить Монику