Язык C - команды Fscanf и sprint в среде unix - PullRequest
3 голосов
/ 08 июня 2010

Я пытаюсь прочитать файл с 30 строками и 5 столбцами с разделителем «табуляция».Каждый раз я получаю только часть строк.В среде Windows это работает хорошо.Есть идеи, почему в Unix это не работает?

while (fscanf(FFMapFile, "%s\t%s\t%s\t%s\t%s\t", fnfMap[i].COS_ID, fnfMap[i].FF_First_Act, fnfMap[i].FF_Next_Act, nfMap[i].Free_FF_allowed, fnfMap[i].FF_Change_Charge) != EOF)
{ 
    sprintf(s,"%s\t%s\t%s\t%s\t%s\t", nfMap[i].COS_ID, fnfMap[i].FF_First_Act, fnfMap[i].FF_Next_Act, fnfMap[i].Free_FF_allowed, fnfMap[i].FF_Change_Charge);
    error_log(s,ERROR);
    i++; }

Ответы [ 3 ]

1 голос
/ 08 июня 2010

Символы \ t в вашей строке fscanf () не являются необходимыми - вкладки являются пробелами, так что вы также можете сказать «% s% s% s% s» - возможно, две реализации scanf обрабатывают их по-разному. Кроме того, вам следует проверить, возвращает ли fscanf значение, отличное от EOF, но не равное числу ожидаемых преобразований, что может указывать на ошибку преобразования какого-либо рода.

0 голосов
/ 08 июня 2010

Проверьте возвращаемое значение из fscanf() более тщательно; он вернет, например, 3, если он соответствует 3 полям. Возможно, вы захотите быть осторожнее с размерами различных строк, чтобы избежать переполнения буфера - однако, это, вероятно, тема для другого дня.

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

Эта упрощенная (но полная, работающая) версия вашего кода ведет себя более или менее разумно в MacOS X.

#include <stdio.h>

int main(void)
{
    char b1[20], b2[20], b3[20], b4[20], b5[20];
    while (fscanf(stdin,"%s\t%s\t%s\t%s\t%s\t", b1, b2, b3, b4, b5) == 5)
        printf("%s\t%s\t%s\t%s\t%s\n", b1, b2, b3, b4, b5);
    return 0;
}

Однако строка «k k k k k» (5 одинарных букв, разделенных пробелами) трактуется как эквивалентная 5 разделенным табуляциям. Следовательно, проблема заключается в том, что в разделе §7.19.6.2 стандарта C указано:

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

Вводимые пробельные символы (как указано в функции isspace) пропускаются, если только спецификация включает спецификатор [, c или n.

Также, что касается спецификатора '% s', он говорит:

Соответствует последовательности символов без пробелов.

Для принудительного сопоставления реальных вкладок вам придется работать немного сложнее. Было бы намного проще прибегнуть к «чтению строки в буфер (fgets()) и разделению ее вручную». Это также позволит вам ввести 5 слов в строку, и вы можете сгенерировать ошибку или предупреждение, если полей слишком мало или слишком много. С fscanf() вы не можете этого сделать. Если вы наберете 8 слов в строке, первые пять будут прочитаны в первый раз, затем три оставшихся слова в строке плюс первые два в следующей и т. Д.

0 голосов
/ 08 июня 2010

В случае успеха fscanf возвращает количество успешно прочитанных элементов.Это число может соответствовать ожидаемому числу или быть меньше в случае сбоя сопоставления.

Вы должны проверить возвращаемое значение fscanf s, чтобы увидеть, какая строка не была правильно проанализирована, и проверить ваши входные данные.

...