Home > OS >  Can't print data from struct in C
Can't print data from struct in C

Time:01-03

My goal here is to print student data contain in struct

My question is why i unable to print out data from struct?

Here is my code:

typedef struct _STUDENT{
    char *fullname;
    int ID;
    float scores[6];
} STUDENT;
void input(STUDENT* student){
    fflush(stdin);
    printf("\nInput Student Fullname: ");
    scanf("%s", &student->fullname);
    printf("\nInput ID: ");
    scanf("%s",&student->ID);
    for(int i = 0; i < 6; i  ){
        printf("\nInput point for course %d: ", i 1);
        scanf("%f",&student[i].scores);
    }
    
}
void output(STUDENT* student){
    
    printf("\nStudent Fullname: %s", student->fullname);
    printf("\nStudent ID: %d", student->ID);
    for(int i = 0; i < 6; i  ){
        printf("\nStudent Score: %f", student[i].scores);   
    }
    
}

int main(){
    
    STUDENT* students;
    int size;
    printf("Enter number of student: ");
    scanf("%d",&size);
    
    students = (STUDENT*)calloc(size,sizeof(STUDENT));
    
    for(int i =0;i<size;i  ){

        input(students i);
    }

    
    for(int i =0;i<size;i  ){
        output(students i);
    }
    return 0;
}

here is the output:

Student Fullname:?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
Student ID: 50
Student Score: 0.000000
Student Score: 0.000000
Student Score: 0.000000
Student Score: 0.000000
Student Score: 0.000000
Student Score: 0.000000

under the output funtion i try to print out some data but none of it been print

CodePudding user response:

My question is why i unable to print out data from struct?

In part, the student data are just not what you expect, on account of numerous errors in your input() function. You could have discovered this for yourself by running the program under control of a debugger, and your compiler might have warned you about several of the errors, at least if you turned up the warning level. Always pay attention to compiler warnings.

Issues with your input() function include:

  • Do not fflush() the standard input. Flushing is about output, not input. If fflush(stdin) happens to produce an effect that you find desirable then that is not portable. If you want to ignore some input then read and discard it.

    As long as you are using scanf or fscanf for input, however, be aware that most field directives skip leading whitespace, including newlines. In that case, however, be aware also that these functions are difficult to use correctly. You may be better served by fgets() combined with sscanf(), though that's not a cure-all.

  • You do not check the return values of your scanf() calls. This is not in itself an error per se, but it means that the program will not recognize input errors or malformed input (relative to your sequence of scanf calls).

  • This ...

        scanf("%s", &student->fullname);
    

    ... attempts to read the name into the representation of a pointer. Undefined behavior results if the name (with terminating null) is longer than the representation of a pointer (probably either four or eight bytes). You probably meant to read the data into the location to which the pointer points:

        scanf("%s", student->fullname);
    

    ... but that is problematic too, because the pointer does not point to valid storage. You could solve the latter problem (with the corrected code) by declaring the fullname member as an array instead of a pointer, in which case you would want to take care to avoid overrunning the length of that array. Alternatively, you could read the name into a local temporary array, and then allocate a copy for the student to point to:

    char temp[1024];
    int result = scanf("23s", temp);
    if (result != 1) /* ... handle input failure ... */;
    student->fullname = malloc(strlen(temp)   1);
    strcpy(student->fullname, temp);
    

    If you have a POSIX-compatible strdup() function, then you could use that instead of the explicit malloc and strcpy.

  • Also, "fullname" suggests a string that may contain space characters, but %s scans a whitespace-delimited string. You may want a %[ directive instead, but do note that that is one of the few directives that does not ignore leading whitespace.

  • This ...

        scanf("%s",&student->ID);
    

    ... is wrong, because &student->ID is a pointer to int, whereas a %s requires a pointer to char. Additionally, that will attempt to store the result as a string, not as an int.

  • This ...

                scanf("%f",&student[i].scores);
    

    ... is wrong because you are passing a pointer to an array (of float), not a pointer to float. That in itself probably would not cause an error in practice, but for i != 0, it is also a pointer to the wrong location. student[i].scores is the scores array of the student at offset i, but you appear to want the ith element of the scores array of the student at offset 0:

                scanf("%f", &student->scores[i]);
    

    An error analogous to this also appears in your output() function.

    Additionally, if you were checking then you might find that some or all of these calls were failing to scan anything. With your current code, this would probably be the case when a three-part fullname was presented (for example, "Cento T. Programmer").

  • Related