How to read parts

147 Views Asked by At

I have a problem with this program: I was able to make another draft program but it only reads the first three lines and stops. Unfortunately, the input file is not symmetrical so I should use while loops for some parts only to avoid repeating parts of the program. With strcpy I could copy the work done up to a certain point and then continue from that point on. I was trying but visual studio tells me to move the memory to the heap but I don't know how to do it ... Practically I should only extrapolate certain data from the input file and order them in an output file according to a precise line. I also know there's a problemi with char buf[200], rec[200] because I have to allocate much more memory...

1

There are 1 best solutions below

3
bruno On

the first time in

while ( !feof(fd) ) {
  fscanf(fd, "session %d (COPY MODE):\n\n", &session);

you call feof before any read so feof cannot work proprely, an easy change is to do

while (fscanf(fd, "session %d (COPY MODE):\n\n", &session) == 1) {

Out of that the mode can be something else that COPY MODE and the two \n after are not mandatory, you also do not check your next fscanf success and globaly the algorithm you use is wrong

A possible way to do the job also checking the validity of the input file is :

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{
  FILE * fp = fopen("summary.txt", "r");
  
  if (fp == NULL) {
    perror("cannot open summary.txt");
    exit(1);
  }
  
  int session;
  char mode[64];
  const char * separator = "_____________________________________________";
  
  while (fscanf(fp, " session %d (%[^)]):", &session, mode) == 2) {
    if (strcmp(mode, "COPY MODE") && strcmp(mode,"ONLINE FREE MODE")) 
    {
       fprintf(stderr, "invalid file, invalid mode '%s'\n", mode);
       exit(1);
    }

    char line[64];
    char given[64];
    char recognized[64];
    int registration, registration_set = 0;
    int sequences, sequences_set = 0;
    
    for(;;) {
      /* read next line, bypass possible newline(s) before */
      if (fscanf(fp, " %63[^\n]", line) != 1) { 
        if (!feof(fp)) {
          perror("reading file");
          exit(1);
        }
        *line = 0;
      }
      else if (sscanf(line, "number of sequences: %d", &sequences) == 1) {
        sequences_set = 1;
        continue;
      }
      else if ((*given == 0) && 
               (sscanf(line, "characters given: %63s", given) == 1)) {
        if (!registration_set) {
          fprintf(stderr, 
                  "registration is missing before 'characters given: %s'\n",
                  given);
          exit(1);
        }
        if (!sequences_set) {
          fprintf(stderr, 
                  "sequences is missing before 'characters given: %s'\n",
                  given);
          exit(1);
        }
        continue;
      }
      else if ((*recognized == 0) &&
               (sscanf(line, "characters recognized: %63s", recognized) == 1)) {
        if (!*given) {
          fprintf(stderr, 
                  "given is missing before 'characters recognized: %s'\n",
                  recognized);
          exit(1);
        }
        continue;
      }
      
      if (registration_set) {
        if (!*given) {
          fputs("invalid file, given is missing\n", stderr);
          exit(1);
        }
        printf("%d %d %d %s %s\n", session, registration, sequences, given, recognized);
        
        if (!*line || !strcmp(line, separator))
          break;
      }
      
      if (sscanf(line, "registration %d:", &registration) != 1) {
        fprintf(stderr,
                "invalid file, 'registration <n>:' expected rather than '%s'\n",
                line);
        exit(1);
      }
      else {
        registration_set = 1;
        *given = *recognized = 0;
      }
    }
  }
  
  fclose(fp);
  return 0;
}

Note the space at the beginning of the format of the fscanf, that allows to bypass character considered to be space including the newline

Compilation and execution :

pi@raspberrypi:/tmp $ gcc -Wall c.c
pi@raspberrypi:/tmp $ cat summary.txt 
session 1 (COPY MODE):
number of sequences: 15
 
registration 1:
characters given: CALOR
 
registration 2:
characters given: CARINO
 
registration 3:
characters given: SUSHI
 

_____________________________________________
session 2 (COPY MODE):
registration 1:
number of sequences: 15
 
characters given: SUSHI
characters recognized: SUSHI
 
_____________________________________________
session 3 (ONLINE FREE MODE):
number of sequences: 15
 
registration 1:
 
characters given: PERA
characters recognized: PFRA
 
registration 2:
 
characters given: SALON
characters recognized: SALON
 
registration 3:
 
characters given: PERRO  
characters recognized: PERRO
 
_____________________________________________
session 4 (ONLINE FREE MODE):
 
registration 1:
number of sequences: 7
 
characters given: TORTUGA
characters recognized: TORTUGA
 
registration 2:
number of sequences: 4
 
characters given: ANAEROBIO
characters recognized: ANAERPBIO
 
registration 3:
number of sequences: 4
 
characters given: PAPELES
characters recognized: PAPELEX
pi@raspberrypi:/tmp $ ./a.out
1 1 15 CALOR 
1 2 15 CARINO 
1 3 15 SUSHI 
2 1 15 SUSHI SUSHI
3 1 15 PERA PFRA
3 2 15 SALON SALON
3 3 15 PERRO PERRO
4 1 7 TORTUGA TORTUGA
4 2 4 ANAEROBIO ANAERPBIO
4 3 4 PAPELES PAPELEX
pi@raspberrypi:/tmp $