2015-01-12 4 views
0

Я работаю над базовой библиотекой музыкальных файлов в C, которая позволяет вам открывать файл через командную строку и добавлять информацию, такую ​​как художник, название песни и год публикации. Как только он выходит, он затем записывает эту информацию обратно в тот же файл.Проанализируйте файл с несколькими общими разделителями C

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

Например, входной файл будет выглядеть примерно так:

Title: Heirloom, Artist: Basenji, Year Published: 2014 
Title: With Me, Artist: Cashmere Cat, Year Published: 2014 

проекта я работаю над специфицирует (против общей практики), что мы храним одну строку информации в struct Song которая выглядит следующим образом :

struct Song { 
    char title[250]; 
    char artist[250]; 
    int year_published; 
}; 

Каждый Song хранится в массиве типа struct Song, называется music_lib[].

Я знаю, как отделить каждую строку в один конкретный struct Song, выполнив:

while(fscanf(input_file, "%s %s %ld", *temp_title, *temp_artist, *temp_year) != EOF) 
    copy_song_to_music_library(temp_title, temp_artist, temp_year); 

То, что я не знаю, как сделать, как правильно разобрать текстовый файл, так что, когда у меня есть известный формат :

Title: Heirloom, Artist: Basenji, Year Published: 2014

для моего переменного заголовка, я получаю «Фамильный черту» (и название: раздели уходит), для моего переменного художника, я получаю «Басенджи~d» (с художником: раздел), и для моих летняя переменная я получаю 2014 год (с годом publis hed: убрано).

Есть ли простой способ сделать это?

+1

Вы пробовали '' Название:% s, Исполнитель:% s, Year Опубликовано:% ld "'? – tumdum

+0

@Tomasz Kłak '" Название:% s, ... 'не будет работать для заголовка с пространством типа' "With Me". – chux

ответ

4

Вы должны изменить

while(fscanf(input_file, "%s %s %ld", *temp_title, *temp_artist, *temp_year) != EOF) 

в

while(fscanf(input_file, "Title: %s, Artist: %s, Year Published: %ld", *temp_title, *temp_artist, *temp_year) != EOF) 

Кроме того, вы должны проверить возвращаемое значение fscanf() для обеспечения правильного чтения.

Из man page из fscanf()

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

Некоторые связанные ссылка:

Подпись этого (и семьи) функция

int fscanf(FILE *stream, const char *format, ...); 

Где, const char *format описывается как

Формат строки состоит из последовательности директив, которые описывают e как обрабатывать последовательность входных символов.

и ожидаемый формат format является [курсив мой]

директива является один из следующих:

• Последовательность пробельных символов (пробел, табуляция, перевод строки, и т. д., см. isspace (3)). Эта директива соответствует любому количеству пробелов, в том числе ни одного, на входе.

• Обычный символ (т. Е. Другой, кроме пробела или «%»). Этот символ должен точно соответствовать следующему символу ввода.

• Спецификация перехода, которая начинается с символа «%» (процента). Последовательность символов из ввода преобразуется в соответствии с этой спецификацией, и результат помещается в соответствующий аргумент указателя. Если следующий элемент ввода не соответствует спецификации преобразования, преобразование завершается неудачно - это совпадение.

Примечание:

Однако, чтобы сделать его более обобщенно, я рекомендую использовать fgets() принимать входные данные, а затем с помощью strtok() чтобы разметить вход и использовать.

+0

@Gopi На этот раз, в следующий раз, когда вы это сделаете. :-) –

+0

Спасибо за это. Я также проверю fgets() :) – Alex

+0

@Alex Вы очень желанны. :-) –

Смежные вопросы