I'm trying to write a program as an exercise that takes some values from a file sorts them into two variables named studentsPassed
and studentsFailed
, then prints the number of students that have passed and the number of students that have failed aswell as the module code and the number of students.
Here is the .txt file:
101 20
65 72 23 59 80 75 55 88 92 77 44 57 73 31 48 59 71 48 66 59
101
is the module code, and 20
is the number of students in the class. The 20 numbers in the row below are the marks each one of those 20 students scored (e.g. Student 1 scored 65, Student 2 scored 72, etc.)
Here is my code:
#include <stdio.h>
FILE *fp;
int main(){
//Open the file and assign its address/disk location to file pointer
fp = fopen("marks.txt", "r");
//Variables
int moduleCode, numStudents;
const int size = 20;
int studentMark;
int studentsPassed;
int studentsFailed;
//Scan in the first line for the module code and the number of students
fscanf(fp, "%d %d", &moduleCode, &numStudents);
//Scan in the student marks and loop through them
for (int i = 0; i < size; i )
if (fscanf(fp, "%d", &studentMark) < 40){
int studentsFailed = studentsFailed 1;
}
else if (fscanf(fp, "%d", &studentMark) >= 40){
int studentsPassed = studentsPassed 1;
}
else{
printf("Error: Number of marks exceeds cap!");
return 0;
}
//Print the results
printf("%d %d\n", moduleCode, numStudents);
printf("Number of students passed: %d\n", studentsPassed);
printf("Number of students failed: %d\n", studentsFailed);
return 0;
}
What the program should do is read the module code and the number of students and print them on the first line (which is successfully does), then the program should loop through each of the 20 numbers and sort them into different variables based on if they are higher or lower than 40, this is the part that I am struggling on, as the program executes, but it will print out a random large number for studentsPassed
, and "1" for studentsFailed
every time I run it.
What am I doing wrong? I feel like I am missing something to do with looping through each of the numbers but I'm not sure how to correct it.
Note: This is what I initially tried (which also didn't work) before reading another answer on this website to get what my current code is.
//Scan in the student marks and loop through them
fscanf(fp, "%d", &studentMark);
for (int i = 0; i < size; i )
if (studentMark < 40){
int studentsFailed = studentsFailed 1;
}
else if (studentMark >= 40){
int studentsPassed = studentsPassed 1;
}
CodePudding user response:
Your second version is almost correct, except that the call to fscanf()
needs to be inside the loop.
Also, you shouldn't re-declare studentsFailed
and studentsPassed
in the if
blocks. Just assign to the variables that were declared earlier.
for (int i = 0; i < size; i )
fscanf(fp, "%d", &studentMark);
if (studentMark < 40){
studentsFailed ;
}
else{
studentsPassed ;
}
}
You also shouldn't use else if
when the second condition is the opposite of the first one. Just use else
.
CodePudding user response:
The value that *scanf
returns is the number of conversion specifiers that were successfully matched. It is unrelated to the values that it reads from the input stream.
You should get out of the habit of relying on the input stream to provide the number of expected data points; it is fragile and usually not necessary. Instead, just read all of the data until you reach the end of the input stream. In your case, you can do something like:
#include <stdio.h>
int
main(int argc, char **argv)
{
int moduleCode, numStudents, studentsPassed = 0, studentsFailed = 0;
int actualNumStudents = 0;
int score;
FILE *fp = argc > 1 ? fopen(argv[1], "r") : stdin;
if( fp == NULL ){
perror(argv[1]);
return 1;
}
if( fscanf(fp, "%d%d", &moduleCode, &numStudents) != 2 ){
fprintf(stderr, "invalid input\n");
return 1;
}
while( fscanf(fp, "%d", &score) == 1 ){
actualNumStudents = 1;
*( score < 40 ? &studentsFailed : &studentsPassed ) = 1;
}
if( ! feof(fp) ){
fprintf(stderr, "invalid input or read error\n");
return 1;
}
if( actualNumStudents != numStudents ){
fprintf(stderr, "Warning: the declared number of students does "
"not match the actual number of students\n");
}
printf("%d %d\n", moduleCode, actualNumStudents);
printf("Number of students passed: %d\n", studentsPassed);
printf("Number of students failed: %d\n", studentsFailed);
}