P
P
PaGrom2012-02-27 16:51:12
C++ / C#
PaGrom, 2012-02-27 16:51:12

Line-by-line reading from a file and line processing in C

It is required to develop a program in pure C that would read text from a file, divide it into words and enter them and the number of their repetitions in a singly linked list. The program seems to have sketched, but I can not overcome the problem. The program works correctly only if there is only one line in the file.
If the file has only one line "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.", the program outputs this:

Word: Star Count: 1
Word: Wars Count: 2
Word: is Count: 2
Word: an Count: 2
Word: American Count: 2
Word: epic Count: 2
Word: space Qty: 2
Word: opera Qty: 2
Word: film Qty: 2
Word: series Qty: 2
Word: created Qty: 2
Word: by Qty: 2
Word: George Qty Number : 2
Word: Lucas Number: 2


If you make two lines, then you get something like this:
Word: Wars Count: 2
Word: is Count: 2
Word: Count: 1
Word: erican Count: 1
Word: can Count: 1
Word: space Count: 2
Word: Count Number : 1
Word: Number: 1
Word: series Number: 2
Word: s Number: 1
Word: ed Number: 1
Word: orge Number: 1
Word: e Number: 1
Word: Quantity: 1
Word: an Quantity: 1
Word: American Quantity: 1
Word: epic Quantity: 1
Word: opera Quantity: 1
Word: film Quantity: 1
Word: created Qty: 1
Word: by Qty: 1
Word: George Qty: 1
Word: Lucas Qty: 1


The program starts behaving completely abnormally. I don't understand what is wrong. Here is the listing:
#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;
}

Answer the question

In order to leave comments, you need to log in

1 answer(s)
R
retran, 2012-02-27
@PaGrom

Are you sure that strtok always creates a new string without overwriting the old one when you store a pointer to a token in your list?
Replace with
list->item = ptr;

list->item = (char *)malloc(strlen(ptr) + 1);
strcpy(ptr, list->item);

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question