Input data from file, calculating average by a function

I want to thank you guys firstly for your previous comments and feedback. Really appreciate it. I am learning C with school at the moment, but I plan to be "fluent" in C at the end of august of this year.

For school I have to write the following program:

1. Open up a file. The file is a *.txt one. It consists of 32 numbers. The first number corresponds to the number of tests distributed under the students. The second number is saying how many have returned the test. The other 30 numbers could be seperated into a 5 by 6 table. There were 6 question with each 5 possible answers. the numbers represent how many students have chosen the answer. The file is posted at the end of this post.

1. Now I have to open this file and making a display like this:
number of passed tests: 20
Number of returned tests: 19
Response is 95%.
A      B      C      D    E    grade     passed
question 1   2      2      2      2    2     2.4         yes
question 2   2      2      2      2    2     2.4         yes
question 3   2      2      2      2    2     2.4         yes
question 4   2      2      2      2    2     2.4         yes
question 5   2      2      2      2    2     2.4         yes
question 6   2      2      2      2    2     2.4         yes


Also note that the "comment" has three options; fail if grade<3.0 , warning if grade<3.5 and pass if higher than 3.5. The code I Have written is like this :

#include <stdio.h>
#define RIJ 6
#define KOLOM 5

int invoer[RIJ][KOLOM] , rij, kolom;
float ingeleverd ;

float functie(int* i ) ;
int main(void)
{

float uitgereikt=0  , percentage ;

FILE *inputbestand;
printf("Dit programma verwerkt de data uit verschillende enquetes.\n");
printf("\n");
printf("Voer de locatie van het bestand in.\n");

if (inputbestand == NULL)
{ printf("Bestand niet gevonden.");
return 0;
}

fscanf(inputbestand, "%f", &uitgereikt);
fscanf(inputbestand, "%f", &ingeleverd);
percentage = (ingeleverd/uitgereikt) *100 ;
//------- overige data inlezen in een array van 5 bij 6.

for (rij=0; rij<RIJ; rij++)
{
for (kolom=0; kolom<KOLOM ; kolom++)
{
fscanf(inputbestand, "%d", &invoer[rij][kolom]);
}
}
fclose(inputbestand);

printf("Aantal uitgereikte evaluaties: %0.f\n" , uitgereikt);
printf("Aantal ingeleverde evaluaties: %0.f\n" , ingeleverd);
printf("Response is: %.1f %% \n\n" , percentage);
printf("   \t  A\t B \t C \t D \t E \t cijfer \t opmerking\n\n");

for (rij=0; rij<RIJ; rij++)
{
printf("vraag %d   " ,rij+1);

for (kolom=0; kolom<KOLOM ; kolom++)
{
printf("%d       ", invoer[rij][kolom]);

if (kolom==KOLOM-1) {
printf("%c \n", functie(invoer[rij]));
}

}
}
}
float functie(int* i )
{
int a ;
float gem, totaal;

for (a=0; a<5 ; a++)
{totaal= totaal+ ( i[a] * (a+1)  ) ;}

gem =  totaal/ingeleverd ;

if      (gem<3.0)      {printf("%.1f \t \t Voldoet niet\n", gem);}
else if (gem<3.5)      {printf("%.1f \t \t opmerking\n", gem);}
else if (gem>3.5)      {printf("%.1f \t \t Voldoet\n", gem);}
//  return  gem ;
}


It is working completely. I have one minor bug though. the results are not aligned properly. What do you guys think ? Except the bad indenting... I am also very sorry it is in Dutch. But I think you guys will understand alright..

the inputfile is like this:

    20
19
1
2
4
5
7
0
1
8
7
3
8
5
4
2
0
2
2
4
11
0
2
3
3
5
6
0
0
4
12
3


I would think about breaking this up into more functions that do specific things. For example, I would break out the reading of the header information (the number of tests passed and the number returned) into one function, and the reading of the actual test data into another function:

void readHeader (FILE* inputbestand, float* uitgereikt, float* ingeleverd)
{
fscanf(inputbestand, "%f", uitgereikt);
fscanf(inputbestand, "%f", ingeleverd);
}


This brings up a question I have for you - why is ingeleverd a global variable? In fact, why do you have any global variables? They all look like they belong inside the main() function to me.

In any event, reading the table of data would then look something like this:

void readTable (FILE* inputbestand, int invoer[RIJ][KOLOM])
{
//------- overige data inlezen in een array van 5 bij 6.
int rij, kolom;
for (rij = 0; rij < RIJ; rij++)
{
for (kolom = 0; kolom < KOLOM; kolom++)
{
fscanf(inputbestand, "%d", &invoer[rij][kolom]);
}
}
}


For what it's worth, I like to put spaces around operators (like comparison operators - <, >, etc.), as I find it much easier to read. That's just a style decision and might not suit you, but that's what I prefer.

I would also move the output into various functions. The introductory text could go into a function like this:

#define RESULT_OK 1    // <- These can go at the top of the file
#define RESULT_ERROR 0 // <- with the others
int printIntro (FILE** inputbestand, char bestandpad[100])
{
int result = RESULT_OK;
printf("Dit programma verwerkt de data uit verschillende enquetes.\n");
printf("\n");
printf("Voer de locatie van het bestand in.\n");

if (*inputbestand == NULL)
{
printf("Bestand niet gevonden.");
result = RESULT_ERROR;
}
else
{
result = RESULT_OK;
}

return result;
}


Although, perhaps a better function name would be getFileName() (or would it be getBestandpad()? I don't know Dutch for "get").

Since you were originally returning 0 from main() when the file could not be read, you need to return any errors from the above function and use that in main() to decide what to return. Which reminds me - you aren't returning a value on success in your main() function. So let's look at that next. After breaking out the various functions, it will look something like this:

int main (void)
{
FILE* inputbestand;
int invoer[RIJ][KOLOM];

if (result == RESULT_OK)
{
float uitgereikt;
float ingeleverd;
fclose(inputbestand);

printStatistics(uitgereikt, ingeleverd);
printResults(invoer, ingeleverd);
}

return result;
}


The function printStatistics() should print out the information about how many tests were passed and how many were returned:

void printStatistics (const float uitgereikt, const float ingeleverd)
{
printf("Aantal uitgereikte evaluaties: %0.f\n" , uitgereikt);
printf("Aantal ingeleverde evaluaties: %0.f\n" , ingeleverd);

float percentage = (ingeleverd/uitgereikt) *100 ;
printf("Response is: %.1f %% \n\n" , percentage);
}


Likewise, printResults() should print out the resulting table:

void printResults(int invoer[RIJ][KOLOM], const float ingeleverd)
{
printf("   \t  A\t B \t C \t D \t E \t cijfer \t opmerking\n\n");
int rij, kolom;
for (rij=0; rij<RIJ; rij++)
{
printf("vraag %d   " ,rij+1);

for (kolom=0; kolom<KOLOM ; kolom++)
{
printf("%d       ", invoer[rij][kolom]);
if (kolom==KOLOM-1)
{
printf("%c \n", functie(invoer[rij], ingeleverd));
}
}
}
}


It's not clear to me what the functie() function is doing. It looks like it's supposed to calculate an average, but it doesn't look to me like it's actually doing that. Also, it returns a float, but it's being used as a character in the printf() statement where it's called. That's almost certainly incorrect. And you've listed 3.0 and 3.5 as the breakpoints between fail, warning, and pass, but in the example, all the grades are 2.4, but marked as "pass". So I'd double-check to make sure you understand the requirement there.

In addition to the above, you should know that there are various ways that reading from the file could fail. You could have truncated data, or there might be the wrong kind of data in the file. I'm not sure if your teacher wants you to worry about that yet, or not. If you want to, you can check the return value of fscanf() and make sure that it read the argument you expected.

• Nice first answer, thanks for chiming in! – Phrancis May 25 '15 at 21:54
• Thanks a lot !. The example output I have written is not correct. But that was just to show how it was supposed to be. – sarcode May 26 '15 at 21:53