Как использовать fgets, если вы не знаете, сколько символов нужно прочитать? - PullRequest
8 голосов
/ 21 мая 2010

Мне нужно прочитать файл и отправить текст из него в строку, чтобы я мог его проанализировать.Тем не менее, программа не будет точно знать, как долго файл находится, так что бы я сделал, если бы я хотел использовать fgets(), или есть лучшая альтернатива?

Примечание:

char *fgets(char *str, size_t num, FILE *stream);

Ответы [ 4 ]

9 голосов
/ 21 мая 2010

Не забывайте, что fgets() читает строку за раз при условии наличия достаточного пространства.

Люди редко пишут строки длиннее ... 80, 256, выбирают число ... символов. POSIX предлагает длину строки 4096. Поэтому я обычно использую:

char buffer[4096];

while (fgets(buffer, sizeof(buffer), fp)) 
{
    ...process line...
}

Если вы обеспокоены тем, что кто-то может предоставить более 4 КБ данных в одной строке (и файл, сгенерированный машиной, такой как HTML или JSON, может содержать это), то вам нужно решить, что делать дальше. Вы можете выполнить любое из следующих действий (и, вероятно, есть некоторые другие варианты, о которых я не упомянул):

  1. Обрабатывать слишком длинные строки в битах, не предполагая, что между ними была новая строка.
  2. Выделите память для более длинной строки (скажем, 8K для начала), скопируйте начальные 4K в выделенный буфер и считайте больше данных во вторую половину буфера, итерируя, пока не найдете конец строки.
  3. Используйте функцию POSIX 2008 getline(), которая доступна в Linux. Это делает выделение памяти для вас.
3 голосов
/ 21 мая 2010

Если вы не в системе POSIX и у вас нет getline, взгляните на публичный домен Чака Фальконера ggets / fggets функции , которые динамически увеличивают буфер до потреблять всю строку. (Эта ссылка сейчас недоступна, но archive.org имеет копию .)

3 голосов
/ 21 мая 2010

Вы можете использовать fgets итеративно, но более простой альтернативой является (stdio.h's) getline . Это в POSIX, но это не стандартная C.

Поскольку вы используете C ++, можете ли вы использовать функции std :: string, такие как getline ?

в iostream
0 голосов
/ 21 мая 2010

Выделите буфер (тот, на который указывает str) и передайте размер буфера для num.Фактически занимаемое пространство будет только длиной текста, прочитанного fgets.

Что-то вроде:

char str[1000];
fgets(str, 1000, &file);

Если следующая строка содержит только 10 символов перед новой строкой, тоstr будет содержать эти 10 символов, символ новой строки и нулевой терминатор.

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

...