0

I should read a file formatted in this way and store infos into a structure:

Johnny Rico A B A B C C C B B A
Ace Levy A A B A C A C A C A
Carmen Ibanez A B B B C C B B B B
Dizzy Flores B A A B C C C B B A
Zander Barcalow A B A B C C A B B A
Carl Jenkins A A A C B C A B B B

EDIT

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

#define N 100

typedef struct _cad
{
    char nome[36], cognome[36];
    char risultati[50];
} Cadetto;

/*
 * 
 */
int main(int argc, char** argv)
{
    FILE *fp = NULL;
    int j = 0, count = 0, i, k;
    char riga[255];
    Cadetto cadetti[100];
    char *ptk;

    if(argc != 2)
    {
        fprintf(stderr, "Error: no parameter has been passed!\n");
        exit(1);
    }


    if((fp = fopen(argv[1], "r")) == NULL)
    {
        fprintf(stderr, "Error opening file %s\n", argv[1]);
        exit(1);
    }

    while (fgets(riga, sizeof(riga), fp) != NULL)
    {
        j = 0;

        ptk = strtok(riga, " ");
        strcpy(cadetti[count].nome, ptk);

        ptk = strtok(NULL, " ");
        strcpy(cadetti[count].cognome, ptk);

        while (ptk != NULL)
        {
            ptk = strtok(NULL, " ");
            cadetti[count].risultati[j] = *ptk;
            j++;
        }

        count++;
    }

    fclose(fp);

    for (i = 0; i < count; i++)
    {
        printf("%s %s", cadetti[i].nome, cadetti[i].cognome);

        for (k = 0; k < j; k++)
        {
            printf(" %c", cadetti[i].risultati[k]);
        }

        printf("\n");
    }

    return (EXIT_SUCCESS);
}

This is the program but it doesn't work again

enter image description here

Mazzy
  • 13,354
  • 43
  • 126
  • 207
  • 1
    look at this: http://stackoverflow.com/questions/2854488/reading-a-string-with-spaces-with-sscanf – x4rf41 Aug 13 '13 at 11:47
  • `strcpy(cadetti[count].risultati[j], ptk);` --> `cadetti[count].risultati[j] = *ptk;` and also reset `j` by `fgets` loop. – BLUEPIXY Aug 13 '13 at 14:59
  • the program works but it doesn't print the chars correctly – Mazzy Aug 13 '13 at 15:17
  • I don't understand why I got that weird symbol – Mazzy Aug 13 '13 at 15:41
  • Debugging my code I got an error when I try to strtok the last char of the first line. Debugging my code through gdb I see that the last char of the first line is A\\r\n. So I got an error – Mazzy Aug 13 '13 at 15:53
  • 1
    You should really use a variable other than `j` to identify how many grades the students have. It should probably be recorded in the `Cadetti` structure since each student could have a different number of grades. – Jonathan Leffler Aug 13 '13 at 15:56
  • Yes. This could be a problem in case in the file there would not be the same grades but this is not the case. – Mazzy Aug 13 '13 at 16:00
  • 1
    You should also modify the `while (ptk != NULL) { ptk = strtok(NULL, " "); ...` code so that it tests for nullness before using `*ptk`, like this for example: `while ((ptk = strtok(NULL, " ")) != NULL) { ...`. This avoids dereferencing a null pointer. And for debugging, add copious print statements so you know what is happening and what has been read at each stage. – Jonathan Leffler Aug 13 '13 at 16:02

2 Answers2

1

This code works for me:

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

#define N 100

typedef struct _cad
{
    char nome[36], cognome[36];
    char risultati[50];
    int nrisultati;
} Cadetto;

int main(int argc, char** argv)
{
    FILE *fp = NULL;
    int i, k;
    int count;
    char riga[255];
    Cadetto cadetti[N];
    char *ptk;

    if(argc != 2)
    {
        fprintf(stderr, "Error: no parameter has been passed!\n");
        exit(1);
    }

    if((fp = fopen(argv[1], "r")) == NULL)
    {
        fprintf(stderr, "Error opening file %s\n", argv[1]);
        exit(1);
    }

    for (count = 0; count < N && fgets(riga, sizeof(riga), fp) != NULL; count++)
    {
        int j = 0;
        printf("Input: %s", riga);

        ptk = strtok(riga, " ");
        strcpy(cadetti[count].nome, ptk);

        ptk = strtok(NULL, " ");
        strcpy(cadetti[count].cognome, ptk);
        printf("Name: %s %s\n", cadetti[count].nome, cadetti[count].cognome);

        while ((ptk = strtok(NULL, " ")) != NULL)
        {
            cadetti[count].risultati[j] = *ptk;
            printf("Grade %d: %c\n", j, *ptk);
            j++;
        }
        cadetti[count].nrisultati = j;
    }

    fclose(fp);

    for (i = 0; i < count; i++)
    {
        printf("%s %s", cadetti[i].nome, cadetti[i].cognome);

        for (k = 0; k < cadetti[i].nrisultati; k++)
        {
            printf(" %c", cadetti[i].risultati[k]);
        }

        printf("\n");
    }

    return (EXIT_SUCCESS);
}

The nrisultati member keeps track of the number of grades of each Cadetto separately, in case the data is inconsistent. The main reading loop is protected against overflowing the array. I've not protected the name reading code from accessing a null pointer with malformed data (a single word, for example). There could be problems if the names are overlong too.

The primary change is in the grade scanning loop; the result of strtok() is checked before it is used.

Sample output from given data:

Input: Johnny Rico A B A B C C C B B A
Name: Johnny Rico
Grade 0: A
Grade 1: B
Grade 2: A
Grade 3: B
Grade 4: C
Grade 5: C
Grade 6: C
Grade 7: B
Grade 8: B
Grade 9: A
Input: Ace Levy A A B A C A C A C A
Name: Ace Levy
Grade 0: A
Grade 1: A
Grade 2: B
Grade 3: A
Grade 4: C
Grade 5: A
Grade 6: C
Grade 7: A
Grade 8: C
Grade 9: A
Input: Carmen Ibanez A B B B C C B B B B
Name: Carmen Ibanez
Grade 0: A
Grade 1: B
Grade 2: B
Grade 3: B
Grade 4: C
Grade 5: C
Grade 6: B
Grade 7: B
Grade 8: B
Grade 9: B
Input: Dizzy Flores B A A B C C C B B A
Name: Dizzy Flores
Grade 0: B
Grade 1: A
Grade 2: A
Grade 3: B
Grade 4: C
Grade 5: C
Grade 6: C
Grade 7: B
Grade 8: B
Grade 9: A
Input: Zander Barcalow A B A B C C A B B A
Name: Zander Barcalow
Grade 0: A
Grade 1: B
Grade 2: A
Grade 3: B
Grade 4: C
Grade 5: C
Grade 6: A
Grade 7: B
Grade 8: B
Grade 9: A
Input: Carl Jenkins A A A C B C A B B B
Name: Carl Jenkins
Grade 0: A
Grade 1: A
Grade 2: A
Grade 3: C
Grade 4: B
Grade 5: C
Grade 6: A
Grade 7: B
Grade 8: B
Grade 9: B
Johnny Rico A B A B C C C B B A
Ace Levy A A B A C A C A C A
Carmen Ibanez A B B B C C B B B B
Dizzy Flores B A A B C C C B B A
Zander Barcalow A B A B C C A B B A
Carl Jenkins A A A C B C A B B B

With the debugging prints commented out:

Johnny Rico A B A B C C C B B A
Ace Levy A A B A C A C A C A
Carmen Ibanez A B B B C C B B B B
Dizzy Flores B A A B C C C B B A
Zander Barcalow A B A B C C A B B A
Carl Jenkins A A A C B C A B B B
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
0
sscanf(riga, "%s %s %s", cadetti[count].nome,
                                 cadetti[count].cognome,
                                 result);

==>

char * tmp = strtok( riga, " ");
memcpy(cadetti[count].nome,tmp,strlen(tmp)+1);

tmp= strtok (NULL " ");
memcpy(cadetti[count].cognome,tmp,strlen(tmp)+1); 

tmp= strtok(NULL,'\0');
memcpy(result,tmp,strlen(tmp)+1);
Lidong Guo
  • 2,817
  • 2
  • 19
  • 31