1

I have an input data file called "TEST.txt". it contains id numbers, names, grades of three different exams of ten students. I'm trying to make a program that reads these input data, calculates the mean value of exams for each student, and writes again id numbers,names, averages, of students whose averages are >=45.5 into output file called "RESULT.TXT" using structures. I think I am able to read my input data with the structure I defined. I want to know what can I do for finding the averages of exams (one,two, and three), setting the condition of writing average values, and writing ids,names, and averages into RESULTS.TXT. Here is my code until now.

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
 typedef struct student{
    char name[30];
    int id;
    int exam1;
    int exam2;
    int exam3;




}STUDENT;



int main(){
    int sum=0;
    int i=0;
    double mean[10];


    STUDENT test[10]; 
    FILE *fRead;


    fRead=fopen("TEST.txt","r+");
    if((fRead=fopen("TEST.txt","r"))==NULL){
        printf("File could not be opened\n");       
    }

    while(!feof(fRead)){


            fscanf(fRead,"%d%s%d%d%d",&(test[i].id),test[i].name,&(test[i].exam1),&(test[i].exam2),&(test[i].exam3));


            printf("\n%s\n",test[i].name);

            i++;    
    }

    return 0;
}
utdlegend
  • 43
  • 1
  • 3
  • 11
  • 1
    Please see [Why is “while ( !feof (file) )” always wrong?](http://stackoverflow.com/questions/5431941/why-is-while-feof-file-always-wrong) The way to write that loop is `while(fscanf(...) == 5) { printf("%s\n", test[i].name); i++; }` – Weather Vane Dec 25 '16 at 15:41
  • I will check it out, but why the condition==5?! – utdlegend Dec 25 '16 at 16:02
  • 1
    Read the [man page](https://msdn.microsoft.com/en-us/library/cb5kac8b.aspx) for `fscanf`, please, before you take one more step. – Weather Vane Dec 25 '16 at 16:09
  • it is best (though not always used) that the definition of a struct and a typedef for that struct be separated. – user3629249 Dec 25 '16 at 16:25
  • the posted question is missing certain critical info. I.E. some example input, some expected output – user3629249 Dec 25 '16 at 16:27
  • regarding these two line: `fRead=fopen("TEST.txt","r+"); if((fRead=fopen("TEST.txt","r"))==NULL){` this is trying to open the file twice, suggest remove the first line. Also, when a system function (in this case `fopen()` fails, the system sets `errno` with the reason for the failure. Error messages should be output to `stderr` not `stdout`. Suggest using: `perror( "fopen for read of TEST.txt failed"); exit( EXIT_FAILURE );` The call to `exit()` because the code cannot continue if opening the file failed. – user3629249 Dec 25 '16 at 16:31
  • why 10 instances of the `STUDENT` struct? per the question only one student needs to be processed at a time. – user3629249 Dec 25 '16 at 16:33
  • Why the `#include ` statement? Nothing in the posted code is using anything from that header file. Why the `#include ` statement?. Nothing in the posted code is using anything from the header file. – user3629249 Dec 25 '16 at 16:34

2 Answers2

0

I have made a few changes to the code you have written, 1. I have used loop instead of array of structure, the constant defines the number of students to scan.

  1. I have created an fOut pointer for RESULT.txt, which I opened in append mode.

  2. I created a condition, where if mean > 45.5, the details of the students will be printed in RESULT.txt.

    P.S. I checked the program with 1 input in test file. Test it with multiple line inputs, should work fine.

    #include <stdio.h>
    #include <stdlib.h>
    
    //constant for number of students, can be changed according to requirement
    #define numOfStudents 10
    
    typedef struct student{
    char name[30];
    int id;
    int exam1;
    int exam2;
    int exam3;
    }STUDENT;
    
    int main(){
        double sum=0;
        int i=0;
        double mean;
    
        STUDENT test; 
        FILE *fRead;
    
        //File pointer for output
        FILE * fOut;
    
        //File  for output in append mode
        fOut = fopen("RESULT.txt", "a+");       
    
    
        fRead=fopen("TEST.txt","r+");
    
        if(fRead == NULL)
        {
            printf("File could not be opened\n");       
        }
    
       //check if the file is successfully opened for appending
        if(fOut == NULL)
        {
            printf("File could not be opened for printing\n"); 
        }
    
    
        for(i; i < numOfStudents; i++)
        {  
             fscanf(fRead,"%d%s%d%d%d",&(test.id),test.name,&(test.exam1), &(test.exam2), &(test.exam3));
             //calculates mean
             sum = test.exam1 + test.exam2 + test.exam3;
             mean = sum / 3.0;
    
             //Condition for mean to be printed to output file
             if(mean > 45.5)               
             {
                fprintf(fOut, "%d %s %d %d %d", (test.id),test.name, (test.exam1),(test.exam2),(test.exam3 ));
                fprintf(fOut, "\n");
             }
    
             if(feof(fRead))
             {
                break;
             }
         }
         fclose(fRead);
         fclose(fOut);
         return 0;
    }
    
zeek-r
  • 1
  • 2
  • this answer tries to access files that failed to open. So this answer is wrong. This answer fails to check the result of the call to `fscanf()` so will continue even if the call fails. This answer performs an implicit conversion when calculating the variable `mean` and will truncate the result due to being an integer divide. the function: `fprintf()` is 'expensive' and is being called an unnecessarily number of times. the code indenting is not consistent. – user3629249 Dec 25 '16 at 17:09
  • this answer includes the header files: `string.h` and `math.h`. None of the contents of those header files are used, so should not be included. – user3629249 Dec 25 '16 at 17:13
  • the format specifier `%s` leaves the code vulnerable to undefined behavior (if the name is greater than 29 characters long)\ – user3629249 Dec 25 '16 at 17:15
  • this answer depends on a criteria that there is exactly 10 students in the input file. This is an unnecessary constraint. – user3629249 Dec 25 '16 at 17:16
  • this line: `sum = test.exam1 + test.exam2 + test.exam 3;` does not compile – user3629249 Dec 25 '16 at 17:26
  • @user3629249, thank you for commenting out all the mistakes, I am new to stack overflow and have less experience with code editor here, I copied and pasted from my local machine, so there may exist problems with indentation, and also intermediate for C programming, so don;t have much experience with all those vulnerabilities – zeek-r Dec 25 '16 at 17:30
0

the following code:

  1. is one possible way to perform the desired function:
  2. cleanly compiles
  3. uses fscanf() properly
  4. does not use undesireable functions like feof()
  5. is appropriately commented
  6. performs appropriate error checking
  7. does not include unnecessary header files
  8. will handle any number of students in the input file, including 0 students

and now the code

#include <stdio.h>   // fopen(), fscanf(), fclose()
#include <stdlib.h>  // exit(), EXIT_FAILURE

#define MAX_NAME_LEN (29)

struct student
{
    char name[MAX_NAME_LEN+1]; // +1 to allow for NUL terminator byte
    int id;
    int exam1;
    int exam2;
    int exam3;
};

int main( void )
{
    struct student test;

    FILE *fRead  = NULL;
    FILE *fWrite = NULL;

    if((fRead=fopen("TEST.txt","r"))==NULL)
    {
        perror("fopen for read of Test.txt failed");
        exit( EXIT_FAILURE );
    }

    // implied else, fopen successful

    if( (fWrite = fopen( "RESULT.TXT", "w" )) == NULL )
    {
        perror( "fopen for write of RESULT.TXT failed" );
        exit( EXIT_FAILURE );
    }

    // implied else, fopen successful

    while( 5 == fscanf(fRead,"%d %" MAX_NAME_LEN "s %d %d %d",
           &(test.id),
           test.name,
           &(test.exam1),
           &(test.exam2),
           &(test.exam3)) )
    {
        printf("\n%s\n",test.name);

        float sum  = (float)test.exam1 + test.exam2 + test.exam3;
        float mean = sum / 3.0f;

        if( 45.5f < mean )
        {
            fprintf( fWrite, "%d %s %d %d %d %2.2f\n",
              test.id,
              test.name,
              test.exam1,
              test.exam2,
              test.exam3,
              mean );
        } // end if
    } // end while

    fclose( fRead );
    fclose( fWrite );

    //return 0; == not needed when returning from 'main' and value is zero
} // end function: main
user3629249
  • 16,402
  • 1
  • 16
  • 17
  • Thank you it worked perfectly but I had to write return 0; though :) – utdlegend Dec 25 '16 at 17:24
  • @utdlegend, since it 'worked perfectly', please select this answer. If you had to have the statement: `return 0;` then might I inquire as to the compiler your using and its' version number? I know that (at least) since the C99 standard that that statement is not needed. – user3629249 Dec 25 '16 at 17:36