Короткий ответ
Вы не можете определить строку с неизвестного размера. Но при необходимости вы можете сделать строку больше и больше. Для всех строковых и I/O-функций необходимо получить уже выделенную строку для работы, поэтому вам нужно немного поиграть с распределением и быть осторожным, чтобы не превышать выделенную емкость.
Однако, если у вас есть постоянная верхняя граница длины строки, просто выделите строку этой длины, и вы будете в безопасности. Изменение размера является более сложным, поэтому избегайте его, если он вам не нужен.
Что строка в C
Строки является частью массива символов, останавливала \0
. Строковые функции перестают считывать массив, когда они сталкиваются с первым символом \0
. Помните, что strlen
возвращает количество символов перед первым \0
, поэтому, даже если массив заканчивается сразу после первого \0
, длина строки строго меньше, чем основная длина массива. В частности, в этом случае длина массива равна strlen + 1
. Это важно при назначении строки; всегда выделяйте пространство для завершающего \0
!
E.g.
char w[7] = "Hello";
такое же, как
char w[7] = {'H', 'e', 'l', 'l', 'o', '\0', '\0'};
При использовании в качестве строки, первый \0
является конец строки и все, что после того, как она игнорируется (не читается строковых функций). Даже если вы перепишете последний элемент массива символов примера печатным символом (например, w[6] = '!';
, в результате получив {'H', 'e', 'l', 'l', 'o', '\0', '!'}
), puts(w);
напечатает Hello
(не Hello!
или что-нибудь подобное).
При воспроизведении со строками как с массивами символов обязательно указывайте на своем конце \0
, как иначе потенциально нераспределенную память после считывания массивом строковыми функциями, что приводит к segfault.
Почему строка неизвестного размера не может быть определена
Как я уже писал, строка является частью массива полукокса. Каждый массив должен иметь фиксированный размер. Вы можете использовать только часть его (эффективно уменьшая его), но он должен быть выделен, и распределитель (malloc
, calloc
) должен знать, сколько памяти требуется.
Если вы используете массив размером больше, чем выделено, программа, скорее всего, сбой будет segfault в лучшем случае. Если вам очень не повезло, программа не будет разбиваться и будет просто использовать часть памяти сразу после массива, создавая странные результаты.
С C99 вы можете опустить спецификацию длины массива, если она может быть inferred from initializer: char w[] = "Hello";
- тот же результат, что и char w[6] = "Hello";
. Однако это не поможет вам, потому что вы указываете инициализатор во время компиляции, и вам нужно динамически изменять длину строки во время выполнения.
Как имитировать произвольную длину строки
Для обработки строк неограниченной длины, вы можете создать массив фиксированной длины и каждый раз, когда его длина слишком мала, выделить новый массив в два раза длиннее и скопировать оригинальное содержимое к новому. (И free - старый). Вы можете использовать realloc
для выполнения этой работы для вас, с дополнительным преимуществом более высокой скорости, когда массив не нужно перемещать и его можно просто сделать на месте.
Можете ли вы быть более конкретным? Вы можете увеличивать 'char *' до тех пор, пока не будет '== '\ 0'' –
Что вы подразумеваете под« пустым »символом' char * '? – merlin2011
Самый простой способ - передать указатель на эту строку. Затем он может быть перераспределен, если строка должна расти. Что касается ввода, вы, вероятно, можете установить максимальный размер, используя что-то вроде fgets. Если вы memset до 0 до fgets и строка слишком длинная, последний символ после fgets не будет null. – cup