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. Iffflush(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
orfscanf
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 byfgets()
combined withsscanf()
, 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 ofscanf
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 explicitmalloc
andstrcpy
.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 toint
, whereas a%s
requires a pointer tochar
. Additionally, that will attempt to store the result as a string, not as anint
.This ...
scanf("%f",&student[i].scores);
... is wrong because you are passing a pointer to an array (of
float
), not a pointer tofloat
. That in itself probably would not cause an error in practice, but fori != 0
, it is also a pointer to the wrong location.student[i].scores
is thescores
array of the student at offseti
, but you appear to want thei
th 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").