Search code examples
cfiletext-filesfgetsscanf

Read textfile line by line and scan from buffert - C


I have made a program which handles and stores records of movies in a library. This is how my library looks like when I print it out to a file. So basicly my problem is to read this file and save those columns in my struct of variables and dynamically increase the size of the struct for every entry. Right now I have a while loop reading line by line into a buffert and I am then trying to scan the values from the buffert. I know the format of the spacings in between the columns if that helps.(No it's not tabs, would that help?) Else i thought about once it finds "two spaces" it could parse onto the next one... What I'm looking for is something like this:

("%s %d %d %d %s %d", name, &id, &qty, &price, genre, &year)

This is how the textfile looks like: "test.txt" (UPDATED version below)

-------------------------------------------------------------------------------
NAME                                          ID    QTY   PRICE GENRE      YEAR
-------------------------------------------------------------------------------
THE SHAWSHANK REDEMPTION                      1     25    99    Crime      1994
THE GODFATHER                                 2     65    199   Crime      1972
PULP FICTION                                  3     265   99    Drama      1994
THE LORD OF THE RINGS                         4     1024  199   Action     2003
THE DARK KNIGHT                               5     99    99    Action     2008

And this is how my code looks like:

void read_from_file(struct movies *movie)
{
    FILE *fp;
    char buffer[1024];
    int line_num = 0;
    int index = 0;

    fp = fopen("test.txt", "r");

    if ( fp == NULL )
    {
        printf("Error opening file!\n");
        exit(1);
    }

    fgets(buffer, 1024, fp); fgets(buffer, 1024, fp); fgets(buffer, 1024, fp); // Skip 3 first lines (header)

    while(fgets(buffer, 1024, fp) != NULL) // read one line to buffer at a time
    {  
        printf("%s", buffer); //DEBUG 

        // Trying here to read only the names which i know should be no longer than 40chars. first row goes well, then it's messed up
        sscanf(buffer, "%40[^\0]" , movie[index].name);

        index++;
    }

    fclose(fp);
    getch();
}

Update: I changed the format of the storage file to the following:

THE SHAWSHANK REDEMPTION,1,25,99,Crime,1994
THE GODFATHER,2,75,199,Crime,1972
PULP FICTION,3,512,99,Drama,2000
THE LORD OF THE RINGS,4,1024,199,Action,2003
THE DARK KNIGHT,5,99,99,Action,2008

Solution

  • The main problem is that there is no single char delimiter. So process the first 45 char;

    while(fgets(buffer, sizeof buffer, fp) != NULL) {
      printf("%s", buffer); //DEBUG
      if (strlen(buf < 80)) {
        handle_short_line_error();
      }
      size_t len;
      for (len = 45; len > 0; len--) {
        if (!isspace(buf[len-1])) {
          break;
        }
      }
      if (!IsAGoodLength(len)) {
        handle_format_error();
      }
      memcpy(movie[index].name, buf, len);
      movie[index].name[len] = '\0';
      if (5 != sscanf(&buffer[45], "%d%d%d%9s%d", &id, &qty, &price, genre, &year)) {
        handle_format_error();
      }
      // Use other fields scanned
      index++;
    }