2017-01-13 4 views
0

Существует текстовый файл 1.txt, как показано ниже, который содержит определенные имена, я хочу добавить их в связанный список, однако код не сканирует только одно имя, но всю строку, как я могу сделать fscanf так, чтобы она просматривала только одно имя?Получение ввода из текстового файла в C

Пример 1.txt:

ana,bob,max,dolores 

Мой код:

FILE *fp = fopen("1.txt", "rt"); 
while (!feof(fp)) { 
    char name_in[100]; 
    fscanf(fp, "%s,", name_in); 
    printf("%s", name_in); 
    addnewnode(head, name_in); 
} 
fclose(fp); 
+0

что-то вроде [это] (http://stackoverflow.com/questions/12911299/read-csv-file-in-c)? – Zorgatone

+0

Возможный дубликат [В C, как я должен читать текстовый файл и печатать все строки] (http://stackoverflow.com/questions/3463426/in-c-how-should-i-read-a-text-file -and-print-all-strings) –

ответ

2

Проблема заключается в том, что с форматом "%s", то scanf не остановит сканирование, пока он не попал в конец ввода или пробел. Это означает, что вы не можете использовать только scanf, чтобы разобрать ваш ввод.

Вместо этого я предлагаю вам прочитать всю вашу строку в буфер, например, используя fgets. После этого вы можете использовать strtok в цикле до tokenize линии.


Не используя scanf также уклоняется большая проблема с вашей строкой формата: именно, что он будет искать замыкающую запятую на входе. Если в конце строки нет запятой (как в вашем примере), то scanf будет просто заблокирован. Он будет блокироваться до тех пор, пока не будет запятая, но если вы не дадите ему запятую, тогда она может блокироваться навсегда. Либо это, либо вы не получите последнюю запись, потому что scanf не удастся. Проверка того, что возвращает scanf, имеет решающее значение.

Кроме того, я настоятельно рекомендую вам прочитать Why is “while (!feof (file))” always wrong?.

+0

, но я поставил запятую (,) до того, как% s ничего не подсчитывает? – TheGreatA

+0

@ArashArbabi, который означает только строку, за которой следует запятая, но строка может содержать запятую, поэтому она игнорируется – Zorgatone

+0

@ArashArbabi Нет, формат ''% s '' является жадным * и будет читать до тех пор, пока он не попадет в пробел или конец ввода. * Затем * он попытается сопоставить запятую. –

0

What's in a name?

Имя обычно мыслится как содержащие буквы, может быть, пробелы и некоторые другие символы. Код должен быть указан, что char составляют имя, какие действительные разделители и обрабатывают другие неожиданно char.

"%s" отличается только пробелом и небелым пространством. Он обрабатывает , так же, как буквы.

"%width[A-Za-z' ]" определит scanset Принимая буквы, ' и пробел. Он будет читать/сохранять до width символов перед добавлением нулевого символа .

Всегда полезно проверить возвращаемое значение функции ввода до с использованием населенных объектов.

FILE *fp = fopen("1.txt", "rt"); 
if (fp == NULL) Handle_Error(); 

// end-of-file signal is not raised until after a read attempt. 
// while (!feof(fp)) { 

char name_in[100]; 
char delimiter[2]; 
int count; 
while ((count = fscanf(fp, "%99[A-Za-z' ]%1[,\n]", name_in, delimiter)) == 2) { 
    printf("<%s>%s", name_in, delimiter); 
    addnewnode(head, name_in); 
    if (delimiter[0] == '\n') { 
    ; // Maybe do something special at end-of-line 
    } 
} 
fclose(fp); 

// Loop stopped unexpectedly 
if (count != EOF || !feof(fp)) { 
    puts("Oops"); 
} 

Более надежный код будет читать линию как с fgets(), а затем обработать строку. Может использовать подобный код, как описано выше, но с sscanf()


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

"%width[-A-Za-z' .]"