Одна возможность состоит в том, чтобы динамически выделить буфер и затем увеличить его (например, с помощью realloc) по мере необходимости. Это, вероятно, потребует написания функции-обертки для fgets, которая будет проверять, прочитала ли она всю строку (символ новой строки сохраняется в буфере). Это также должно обрабатывать условия EOF.
Это, вероятно, само собой разумеется, но использование C для чтения и анализа текстовых файлов с данными переменной ширины - довольно большая работа. Это может не иметь смысла для вашей ситуации или даже быть возможным, но если вы можете использовать что-то вроде Ruby, Python, Perl, Awk и т. Д., Вы, вероятно, сможете выполнить задачу за короткое время. Вы можете выполнить несколько строк кода с помощью этих инструментов, которые могут занимать сто строк кода C. Они идеально подходят для чтения и анализа текстового файла с разделителями. Например, следующий фрагмент ruby читает текстовый файл построчно и разбивает его на вертикальные полосы:
File.open("myfile.txt") { |file|
while ( line = file.gets )
puts "line: #{line}"
a = line.split( /\|/ )
puts "array: #{a}"
end
}
Просто для удовольствия, вот возможная реализация с несколькими TBD для обработки (проверка ошибок). Основной проблемой (кроме тонких ошибок, которые я не видел) было бы решение проблемы освобождения буфера, если вы не полностью читаете в EOF.
int myReadLine // return non-zero if line returned, 0 on eof (see tbd below)
(
FILE *fp, // (I) open file handle for reading
char **buf, // (IO) buffer allocated by this function. It is freed by
// this function when EOF is hit. TBD: Should write a myFreeLine
// (for encapsulation purposes) to free this buffer for cases where
// you quit calling
int *len // (IO) current length of buffer pointed to by buf
)
{
char *ret;
char *pos;
int curlen;
int remaining;
if ( *len == 0 )
{
assert( *buf == NULL );
// pick a number out of the air. Could be app-specific. In debug
// it may be nice to start very small to force reallocs to exercise all
// code paths.
*len = 2;
// tbd: need error checking
*buf = (char*)malloc( *len * sizeof( char ));
}
pos = *buf;
remaining = *len;
while ( 1 )
{
ret = fgets( pos, remaining, fp );
if ( ret == NULL )
{
// tbd: should check if error occurred here. For now assuming eof
free( *buf );
*buf = NULL;
*len = 0;
return 0;
}
// check to see if we got the entire line.
curlen = strlen( *buf );
if ( (*buf)[curlen - 1] == '\n' ) // tbd: check for \r?
{
// apparently we got the whole line
// remove the end of line (at least that's what I would want)
(*buf)[curlen - 1] = '\0';
return 1;
}
else
{
// failed to get entire line
assert( curlen + 1 == *len );
// grow the buffer (tbd: realloc is a pain ... need error checking)
*len *= 2; // doubling is often a good plan
*buf = (char*)realloc( *buf, *len );
// set the "amount left" variables correctly for next iteration
remaining = *len - curlen;
pos = *buf + curlen;
}
} // while forever
// don't expect to get here
assert( 0 );
}
А вот пример звонка:
void readfile(char *filepath)
{
int len = 0;
char *buf = NULL;
FILE *fp=fopen(filepath,"rt");
while ( myReadLine( fp, &buf, &len ))
printf( "'%s'\n", buf );
fclose(fp);
}