Учитывая буферизацию, присущую всем функциям stdio, я бы испытал желание читать символ за символом потока с помощью getc (). Простой конечный автомат может определять границы слов и границы строк, если это необходимо. Преимущество - полное отсутствие буферов для переполнения, за исключением того, в каком буфере вы собираете текущее слово, если этого требует ваша дальнейшая обработка.
Возможно, вы захотите сделать быстрый тест, сравнивая время, необходимое для полного чтения большого файла, с помощью getc () и fgets () ...
Если внешнее ограничение требует, чтобы файл действительно читал строку за раз (например, если вам нужно обрабатывать строчный ввод из tty), тогда fgets (), вероятно, ваш друг, как указывают другие ответы, но даже тогда подход getc () может быть приемлемым, если входной поток работает в режиме буферизации строки, что является обычным для stdin, если stdin находится на tty.
Редактировать: Чтобы иметь контроль над буфером во входном потоке, вам может понадобиться вызвать setbuf () или setvbuf (), чтобы принудительно переключить его в буферный режим. Если входной поток заканчивается небуферизованным, то использование явного буфера некоторой формы всегда будет быстрее, чем getc () в необработанном потоке.
Лучшая производительность, вероятно, будет использовать буфер, связанный с вашим дисковым вводом / выводом, размером не менее двух дисковых блоков и, возможно, намного больше. Часто даже эту производительность можно превзойти, расположив входные данные в виде файла с отображением в памяти и полагаясь на подкачку ядра для чтения и заполнения буфера при обработке файла, как если бы это была одна гигантская строка.
Независимо от выбора, если производительность будет иметь значение, вам нужно будет сравнить несколько подходов и выбрать тот, который лучше всего работает на вашей платформе. И даже в этом случае простейшее выражение вашей проблемы все же может быть лучшим общим решением, если оно будет написано, отлажено и использовано.