Какие строки являются допустимыми входными данными для строковых функций Си? - PullRequest
3 голосов
/ 11 ноября 2011

Требуются ли для таких функций, как strcat и strcmp, строки с нулевым символом в конце в качестве аргументов или любой массив символов приемлем?

Во всех документах предполагается, что он должен заканчиваться нулем, но одна из самых известных ссылок в Интернете (http://cplusplus.com) приводит в качестве примера strcmp:

/* strcmp example */
#include <stdio.h>
#include <string.h>

int main ()
{
  char szKey[] = "apple";
  char szInput[80];
  do {
     printf ("Guess my favourite fruit? ");
     gets (szInput);
  } while (strcmp (szKey,szInput) != 0);
  puts ("Correct answer!");
  return 0;
}

Ответы [ 7 ]

5 голосов
/ 11 ноября 2011

Да, для функций требуются строки с нулевым символом в конце. Однако в приведенном выше примере действительно используются строки с нулевым символом в конце. Например, строка

char szKey[] = "apple";

Описывает строку, к которой добавлен нулевой терминатор, хотя это не сразу видно в исходном коде. Любой строковый литерал в C автоматически завершается нулем, даже если вы явно не помещаете запрос в себя (хотя есть исключение, как мы увидим через минуту).

Более того, в строке

gets (szInput);

Функция gets автоматически добавляет нулевой терминатор в конец строки, которую она читает из консоли. Фактически, за немногими исключениями (такими как общеизвестно сложная функция strncat), все функции манипуляции со строками в <string.h> автоматически добавляют нулевой терминатор. В общем случае редко встречается строка с нулевым символом в конце, если вы сами явно не возитесь с байтами символа.

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

char hello[5] = {'h', 'e', 'l', 'l', 'o'}; /* Careful! */

Этот массив не будет заканчиваться нулем, потому что вы явно перечислили значения, которые вы хотели бы иметь. Это означает, что у вас есть массив символов, а не строка. Если вы попытались позвонить

printf("%s\n", hello);

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

Кроме того, если вы используете какие-либо необработанные процедуры манипулирования памятью, такие как memcpy или memmove, вам нужно быть осторожным, чтобы убедиться, что нулевой терминатор скопирован или задан явно, поскольку эти подпрограммы не имеют понятия нулевого -terminators.

Кроме того, один быстрый бит терминологии - NULL обычно относится к нулевому указателю , то есть к указателю, который явно помечен как указывающий на отсутствие объекта. Нуль в нулевом терминаторе относится к символу с числовым значением 0 и является символом (не указателем), используемым для указания того, что конец строки достигнут. Хотя имена совпадают (и имеют сходство), лучше не путать их.

Надеюсь, это поможет!

1 голос
/ 11 ноября 2011

Строки должны заканчиваться NUL, но я не вижу никаких проблем с завершением NUL в этом коде.

Я должен добавить, что это почти only проблема, которой нетестьВ частности, использование gets непростительно.

1 голос
/ 11 ноября 2011

gets() завершается нулем, а szKey[] = "apple"; заканчивается нулем."apple" является строковым литералом, который всегда заканчивается нулем.

strcmp требует, чтобы строка для копирования имела терминатор \0, в противном случае она могла бы выйти за пределы конца строки и вызвать нарушения доступа.

strcat также требует, чтобы аргументы \0 были завершены.

0 голосов
/ 11 ноября 2011

Что заставляет вас думать, что они / не / обнулились?Строковые литералы автоматически заканчиваются нулем, и (при условии, что в буфере достаточно места), get () также завершается нулем.

Эта точка там - то, что получает, завершается нулем, только если в буфере есть место- это причина, по которой вы должны использовать getsn () вместо gets ().

0 голосов
/ 11 ноября 2011

Они должны заканчиваться NULL, потому что длина неизвестна.Работа библиотечных функций заключается в том, что они начинаются с начала строки и повторяются по каждому символу, пока не встретится нулевой байт.Если это не так, функция продолжит работу в памяти, где она не должна быть.

0 голосов
/ 11 ноября 2011

Абсолютно они должны заканчиваться нулем.

Функции сравнения, такие как strcmp, должны иметь что-то, чтобы остановить сравнение, и это нулевой символ.

Существуют другие функции, такие как strncmp, которые принимают длинупараметр.В этом случае строки не должны заканчиваться нулем, поскольку вы указываете количество символов для сравнения.

0 голосов
/ 11 ноября 2011

По определению, строка всегда заканчивается NULL.

"apple" фактически обрабатывается компилятором как apple\0.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...