1

This program should get in input a number and calculate the average value between a student's marks. This program works only with the former student, but not with the following ones. I think there's a mistake with that fscanf. Can anybody help?

int main ()
{
    FILE *cfPtr;
    int matricola_in, matricola, nEsami, codEsame, voto;
    char nome[20], cognome[20];
    int i, j, trovato = 0;
    float somma = 0.0;

    printf("Inserisci una matricola:\n");
    scanf("%d", &matricola_in);

    if( (cfPtr = fopen("studenti.txt", "r")) == NULL )
        printf("Errore");

    while( !feof(cfPtr) || trovato != 1 ){
        fscanf(cfPtr, "%d%s%s%d\n", &matricola, nome, cognome, &nEsami);
        if( matricola_in == matricola ){
            trovato = 1;
            for( i = 0; i < nEsami; i++ ){
                fscanf(cfPtr, "%d%d\n", &codEsame, &voto);
                somma += voto;
            }
            printf("Media: %.1f\n", somma/nEsami);
        }
    }

    fclose(cfPtr);

    return 0;
}

Edit: the data looks like:

matricola nome cognome n.esami`<eol>`
(for n.esami-rows)codice esame voto`<eol>`
...
Weather Vane
  • 33,872
  • 7
  • 36
  • 56
Teorema
  • 83
  • 6
  • Add a hexdump of the first few lines of `studenti.txt` -- try `hexdump -C studenti.txt | head`. That may show you the answer immediately, but in any case will be helpful to other people answering. – Dave M. Dec 27 '17 at 20:09
  • 1
    What does the data look like? Perhaps you have a student with more or fewer than 2 name components? You also aren't setting the sum (`somma`) back to zero. And you never want to control a loop with `feof`, instead check the return value from `fscanf`, and when it processed fewer fields than requested, then `feof` will tell you if the reason is reaching the end of file. – Ben Voigt Dec 27 '17 at 20:10
  • Edit: the data looks like: (matricola) (nome) (cognome) (n.esami) n.esami-rows: (codice esame) (voto) ... – Teorema Dec 27 '17 at 20:12
  • the data does not have parenthesis. I wrote them for you to let you understand that is a "campo" to fill – Teorema Dec 27 '17 at 20:17
  • Please edit the question with the additional information. – Weather Vane Dec 27 '17 at 20:20
  • 3
    [why `while (!feof(cfPtr))` is wrong](https://stackoverflow.com/questions/5431941/while-feof-file-is-always-wrong) – Barmar Dec 27 '17 at 20:23
  • Is that really the correct data? There are no numbers. – Barmar Dec 27 '17 at 20:24
  • 2
    Always check that the value returned by `fscanf` is correct! Besides that you need to show us an example of studenti.txt where it fails – Support Ukraine Dec 27 '17 at 20:33
  • `codice esame voto` Hmm... is that two or three values? – Support Ukraine Dec 27 '17 at 20:34

1 Answers1

1

Not clear but it seems the file contains a mix of line that have either four or two items.
Consider reading each line. Parse the line into up to four strings using sscanf. As needed use sscanf to capture the integers from the line. If there are two items, process them if trovato flag indicates a match has been found. If there are four items, see if there is a match and set trovato.

int main ()
{
    FILE *cfPtr;
    int matricola_in, matricola, nEsami, codEsame, voto;
    char nome[20], cognome[20];
    char temp[4][20];
    char line[200];
    int result;
    int i, j, trovato = 0;
    float somma = 0.0;

    printf("Inserisci una matricola:\n");
    scanf("%d", &matricola_in);

    if( (cfPtr = fopen("studenti.txt", "r")) == NULL ) {
        printf("Errore");
        return 0;
    }

    while( fgets ( line, sizeof line, cfPtr)){//read a line until end of file
        result = sscanf ( line, "%19s%19s%19s%19s", temp[0], temp[1], temp[2], temp[3]);//scan up to four strings
        if ( result == 2) {//the line has two items
            if ( trovato) {// match was found
                sscanf ( temp[0], "%d", &codEsame);
                sscanf ( temp[1], "%d", &voto);
                somma += voto;
            }
        }
        if ( result == 4) {//the line has four items
            if ( trovato) {
                break;//there was a match so break
            }
            sscanf ( temp[0], "%d", &matricola);
            sscanf ( temp[3], "%d", &nEsami);
            if( matricola_in == matricola ){//see if there is a match
                trovato = 1;//set the flag
            }
        }
    }
    printf("Media: %.1f\n", somma/nEsami);//print results

    fclose(cfPtr);

    return 0;
}
user3121023
  • 8,181
  • 5
  • 18
  • 16