Задать вопрос

Построковое чтение из файла и обработка строк на C

Требуется разработать программу на чистом С, которая читала бы текст из файла, разделяла его на слова и заносила их и количество их повторений в односвязный список. Программку вроде как набросал, но вот не могу побороть проблему. Программа работает корректно, только если в файле всего одна строка.
Если в файле всего одна строка «Star Wars is an American epic space opera film series created by George Lucas. Sixteen years after the release of the trilogy's final film, the first in a new prequel trilogy of films was released.», то программа выдает это:
Слово: Star Кол-во: 1
Слово: Wars Кол-во: 2
Слово: is Кол-во: 2
Слово: an Кол-во: 2
Слово: American Кол-во: 2
Слово: epic Кол-во: 2
Слово: space Кол-во: 2
Слово: opera Кол-во: 2
Слово: film Кол-во: 2
Слово: series Кол-во: 2
Слово: created Кол-во: 2
Слово: by Кол-во: 2
Слово: George Кол-во: 2
Слово: Lucas Кол-во: 2


Если же сделать две строки, то получается нечто подобное:
Слово: Wars Кол-во: 2
Слово: is Кол-во: 2
Слово: Кол-во: 1
Слово: erican Кол-во: 1
Слово: can Кол-во: 1
Слово: space Кол-во: 2
Слово: Кол-во: 1
Слово: Кол-во: 1
Слово: series Кол-во: 2
Слово: s Кол-во: 1
Слово: ed Кол-во: 1
Слово: orge Кол-во: 1
Слово: e Кол-во: 1
Слово: Кол-во: 1
Слово: an Кол-во: 1
Слово: American Кол-во: 1
Слово: epic Кол-во: 1
Слово: opera Кол-во: 1
Слово: film Кол-во: 1
Слово: created Кол-во: 1
Слово: by Кол-во: 1
Слово: George Кол-во: 1
Слово: Lucas Кол-во: 1


Программа начинает себя вести совершенно ненормально. Не пойму в чем ошибка. Вот листинг:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
 
typedef struct list_item 
{ 
    char *item;
    int count;
    struct list_item *next;
} ITEM_LIST;

int check(ITEM_LIST *l, char *c)
{
    while (l != NULL)
    {
		if (strcmp(c,l->item) == 0)
		{
			l->count++;
			return 0;
		}
		else l=l->next;
    }
    return 1;
}

void show(ITEM_LIST *l)
{
	if (l == NULL)
		return;
	printf("Слово: %s\t Кол-во: %d\n", l->item, l->count);
	show(l->next);
}

int main (void)
{
    char buf[4096];
    char *ptr;
    FILE *f = fopen("file1","r");
    if (f == NULL)
    {
    	printf("Error. I can't find file.");
    	return 0;
    }
    
    ITEM_LIST *list;
    ITEM_LIST *beg = NULL;
    ITEM_LIST *end = NULL;
        
    while(!feof(f))
    {
    	if (fgets(buf,sizeof(buf),f))
    	{
	    	printf("%s",buf);
	    	for(ptr = strtok(buf," ,.:;!?\n\t"); ptr != NULL; ptr = strtok(NULL," ,.:;!?\n\t"))
		    {
				list=(ITEM_LIST *)malloc(sizeof(ITEM_LIST));
				if (check(beg, ptr))
				{
					list->item = ptr;
					list->count = 1;
					if (beg == NULL && end == NULL) 
						beg = list;
					else
						end->next = list;
					end = list;
					end->next = NULL;
				}
				else
					free(list);
		    }
		}
    }
    
    fclose(f);
    show(beg);
    return 0;
}
  • Вопрос задан
  • 8661 просмотр
Подписаться 3 Оценить Комментировать
Решения вопроса 1
retran
@retran
А вы уверены что strtok всегда создает новую строку не затирая старую, когда сохраняете указатель на токен в свой список?

Замените
list->item = ptr;

на
list->item = (char *)malloc(strlen(ptr) + 1);
strcpy(ptr, list->item);
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

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