Можно ли прочитать строку неизвестного размера на C, не помещая ее в заранее выделенный буфер фиксированной длины? - PullRequest
9 голосов
/ 03 марта 2010

Можно ли прочитать строку в C, не выделяя массив фиксированного размера заранее?

Каждый раз, когда я объявляю массив символов некоторого фиксированного размера, я чувствую, что делаю это неправильно. Я всегда догадываюсь о том, что, по моему мнению, будет максимальным для моего варианта использования, но это не всегда легко.

Кроме того, мне не нравится идея иметь меньшую строку, сидящую в большем контейнере. Это не правильно.

Я что-то упустил? Есть ли какой-то другой способ, которым я должен делать это?

Ответы [ 6 ]

7 голосов
/ 03 марта 2010

В тот момент, когда вы читаете данные, ваш буфер будет иметь фиксированный размер - это неизбежно.

Однако вы можете прочитать данные, используя fgets, и проверить, является ли последний символ '\ n' (или вы достигли конца файла), а если нет, realloc ваш буфер и читать дальше.

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

3 голосов
/ 03 марта 2010

Когда вы говорите «раньше времени», вы имеете в виду во время выполнения или во время компиляции? Во время компиляции вы делаете это:

char str[1000];

во время выполнения вы делаете это:

char *str = new char[size];

Единственный способ получить точно правильный размер - узнать, сколько символов вы собираетесь прочитать. Если вы читаете из файла, вы можете перейти к ближайшей новой строке (или какому-либо другому условию), а затем точно знать, насколько большим должен быть массив. то есть:

int numChars = computeNeededSpace(someFileHandle);
char *readBuffer = new char[numChars];
fread(someFileHandle, readBuffer, numChars);  //probly wrong parameter order

Нет другого способа сделать это. Поставьте себя на перспективу программ. Как узнать, сколько клавиш нажимает пользователь? Лучшее, что вы можете сделать, это ограничить пользователя или что-то еще.

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

РЕДАКТИРОВАТЬ: Большинство языков имеют классы string / inputbuffer, которые скрывают это от вас.

2 голосов
/ 03 марта 2010

Вы должны выделить фиксированный буфер. Если он станет маленьким, то realloc() увеличьте его и продолжите.

1 голос
/ 03 марта 2010

Нет способа определить длину строки, пока вы не прочитаете ее, поэтому чтение ее в буфер фиксированного размера - в значительной степени ваш единственный выбор.

Я полагаю, у вас есть альтернатива для чтения строки небольшими порциями, но в зависимости от вашего приложения, которое может не дать вам достаточно информации за раз для работы.

Возможно, самый простой способ справиться с этой дилеммой - определить максимальную длину для определенного ввода строки (#define - помогает константа для этого значения). Используйте буфер этого заранее определенного размера всякий раз, когда вы читаете строку, но обязательно используйте форму строковых команд strncpy(), чтобы вы могли указать максимальное количество символов для чтения. Некоторые часто используемые типы строк (например, имена файлов или пути) могут иметь максимальную длину, определяемую системой.

Нет ничего по сути «неправильного» в объявлении массива фиксированного размера, если вы используете его правильно (выполните надлежащую проверку границ и обработайте случай, когда ввод переполнит массив). Это может привести к выделению неиспользуемой памяти, но, к сожалению, язык Си не дает нам много работы, когда дело касается строк.

0 голосов
/ 03 марта 2010

Вы можете использовать общедоступную функцию Чака Фальконера ggets для управления и перераспределения буферов: http://cbfalconer.home.att.net/download/index.htm

Edit: Сайт Чака Фальконера больше не доступен. archive.org все еще имеет копию , а Я тоже размещаю копию .

0 голосов
/ 03 марта 2010

Существует концепция String Ropes , которая позволяет создавать деревья буферов фиксированного размера. Вы по-прежнему должны иметь фиксированный размер буферов, от которых на самом деле не обойтись, но это довольно аккуратный способ динамического создания строк.

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