KonstantaV
KonstantaV

Reputation: 23

How to read from the file and write it in the structure? I have a little trouble with my code

I have to write this code, I mean I should read from the file name of students and their mark, and then sort students by the grow of mark. Now I just want to output only mark. I want to display grades using structures. I don't know where the problem is.

text.file

Jon 3
Alina 5
Ron 1
#include <stdio.h>
#define _CRT_SECURE_NO_WARNINGS
#include <string.h>
#include <stdlib.h>
int main()
{
    const int N = 3;
    int i = 0;
    struct student {
        char surname[50];
        int mark;
    };
    struct student PI1[N];

    char str[50];
    const char s[1] = " ";
    char* token;
    FILE* ptr;
    token = strtok(str, s);
    
    ptr = fopen("test.txt", "r");

    if (NULL == ptr) {
        printf("file can't be opened \n");
    }

    while (fgets(str, 50, ptr) != NULL){
        
        token = strtok(str, s);
        strcpy(PI1[i].surname, token);
        token = strtok(NULL, s);
        PI1[i].mark = atoi(token);
        i++;
    }
    fclose(ptr);
    printf("The marks is:\n");
    printf("%d %d %d", PI1[0].mark, PI1[1].mark, PI1[2].mark);
    return 0;
}

Upvotes: 1

Views: 51

Answers (1)

Ted Lyngmo
Ted Lyngmo

Reputation: 117298

  • You need to prevent the program from reading from the file pointer if opening the file fails:
    ptr = fopen("test.txt", "r");
    if (NULL == ptr) {
        perror("test.txt");
        return 1;               // this could be one way
    }
    
  • The second argument to strok should be a null terminated string. const char s[1] = " "; only has room for one character. No null terminator (\0). Make it:
    const char s[] = " "; // or const char s[2] = " "; or const char *s = " ";
    
  • Don't iterate out of bounds. You need to check so that you don't try to put data in PI1[N] etc.
    while (i < N && fgets(str, sizeof str, ptr) != NULL) {
    //     ^^^^^^^^
    
  • Check that strok actually returns a pointer to a new token. If it doesn't, the line you've read doesn't fulfill the requirements.
    while (i < N && fgets(str, sizeof str, ptr) != NULL) {
        token = strtok(str, s);
        if(!token) break;               // token check
        strcpy(PI1[i].surname, token);
        token = strtok(NULL, s);
        if (token)                      // token check
            PI1[i].mark = atoi(token);
        else
            break;
        i++;
    }
    
  • You could also skip the strcpy by reading directly into your struct student since char str[50]; has the same length as surname. str should probably be larger though, but for now:
    while (i < N && fgets(PI1[i].surname, sizeof PI1[i].surname, ptr) != NULL) {
        token = strtok(PI1[i].surname, s);
        if(!token) break;
        token = strtok(NULL, s);
        if (token)
            PI1[i].mark = atoi(token);
        else
            break;
        i++;
    }
    
  • Only print as many marks as you successfully read
    printf("The marks are:\n");
    for(int idx = 0; idx < i; ++idx) {
        printf("%d ", PI1[idx].mark);
    }
    putchar('\n');
    

Upvotes: 2

Related Questions