Проблема читая строку с помощью fscanf ()

Я смог решить свой вопрос здесь. Оказывается, что nodemailer уже возвращает обещание, поэтому возвращение обещания обещало (разумно) не действовать так, как я думал обещание. Удалив ошибочный / возвращенный код «нового Promise», я смог получить соответствующий ответ обратно в файл контроллера, вернув встроенную функцию Promise для nodeMailer.

6
задан unwind 14 May 2009 в 07:36
поделиться

5 ответов

Мне кажется, вы пытаетесь использовать операторы регулярных выражений в своей строке fscanf. Строка [^ \ n \ r] ничего не значит для fscanf, поэтому ваш код работает не так, как ожидалось.

Кроме того, fscanf () не возвращает EOF, если товар не совпадает. Скорее, он возвращает целое число, которое указывает количество совпадений, которое в вашем случае, вероятно, равно нулю. EOF возвращается только в конце потока или в случае ошибки. Итак, что происходит в вашем случае, так это то, что первый вызов fscanf () читает полностью до конца файла в поисках соответствующей строки, затем возвращает 0, чтобы вы знали, что совпадений не найдено. Затем второй вызов возвращает EOF, поскольку был прочитан весь файл.

Наконец, обратите внимание, что оператор формата% s scanf захватывает только следующий пробельный символ, поэтому вам не нужно исключать \ n или \ r ни в одном case.

Для получения дополнительной информации см. документацию fscanf: http://www.cplusplus.com/reference/clibrary/cstdio/fscanf/

0
ответ дан 8 December 2019 в 04:55
поделиться

Практически всегда плохая идея использовать функцию fscanf () , поскольку она может оставить указатель на файл в неизвестном месте в случае сбоя.

Я предпочитаю использовать fgets () для ввода каждой строки, а затем sscanf () для этого. Затем вы можете продолжить изучение прочитанной строки по своему усмотрению. Что-то вроде:

#define LINESZ 1024
char buff[LINESZ];
FILE *fin = fopen ("infile.txt", "r");
if (fin != NULL) {
    while (fgets (buff, LINESZ, fin)) {
        /* Process buff here. */
    }
    fclose (fin);
}

fgets () похоже на то, что вы пытаетесь сделать, читая строку, пока не встретите символ новой строки.

19
ответ дан 8 December 2019 в 04:55
поделиться

Если вы попробуете while (fscanf (f, "% 27 [^ \ n \ r]", cLine) == 1) , возможно, вам повезет больше. Три изменения по сравнению с вашим оригиналом:

  • ограничение длины того, что читается - я использовал здесь 27 в качестве примера, и, к сожалению, семейство scanf () требует поля width буквально в строке формата и не может использовать механизм * , который printf () может для передачи значения в
  • избавиться от s ] в строке формата - % [ - это спецификатор формата для «всех символов, совпадающих или не соответствующих набору», и набор заканчивается ] сам по себе
  • сравните возвращаемое значение с ожидаемым количеством конверсий (и для простоты управления
1
ответ дан 8 December 2019 в 04:55
поделиться

У вашего цикла есть несколько проблем. Вы писали:

while( fscanf( f, "%[^\n\r]s", cLine ) != EOF ) 
    /* do something */;

Некоторые моменты, которые следует учитывать:

  1. fscanf () возвращает количество сохраненных элементов. Он может возвращать EOF, если он читает после конца файла или если дескриптор файла содержит ошибку. Вы должны отличать действительный возврат нуля, когда в буфере cLine нет нового содержимого, от успешного чтения.

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

  3. Написанный вами шаблон, вероятно, не выполняет то, что вы планировали. Он сопоставляет любое количество символов, которые не являются CR или LF, а затем ожидает найти литерал s .

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

  5. Если вы специально не попросили открыть f в двоичном режиме, перевод окончания строки будет происходить в библиотеке, и вы, как правило, никогда не увидите символы CR, как правило, не в текстовых файлах.

Возможно, вам понадобится цикл, более похожий на следующий:

while(fgets(cLine, N_CLINE, f)) {
    /* do something */ ;
}

где N_CLINE - количество байтов, доступных в буфер, запускающий cLine .

Функция fgets () является наиболее предпочтительным способом чтения строки из файла. Его второй параметр - это размер буфера, и он считывает из файла в буфер на 1 байт меньше этого размера. Он всегда завершает буфер символом nul , чтобы его можно было безопасно передать другим строковым функциям C.

Он останавливается на первом из конца файла, новой строке или buffer_size-1 байтов прочитано.

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

Он возвращает NULL, если байты не были скопированы из-за конца файла или ошибки, и указатель на буфер в противном случае. Вы можете использовать feof () и / или ferror () , чтобы различать эти случаи.

0
ответ дан 8 December 2019 в 04:55
поделиться

Использование fscanf для чтения / токенизации файла всегда приводит к хрупкому коду или боли и страданиям. Чтение строки, разметка или сканирование этой строки безопасны и эффективны. Ему нужно больше строк кода - а это значит, что нужно больше времени, чтобы ДУМАТЬ о том, что вы хотите сделать (и вам нужно обрабатывать конечный размер входного буфера), - но после этого жизнь просто воняет меньше.

Не сражайтесь с fscanf. Просто не используйте это. Всегда.

1
ответ дан 8 December 2019 в 04:55
поделиться
Другие вопросы по тегам:

Похожие вопросы: