【问题标题】:Using structure in reading a file, calculating, and writing into another在读取文件、计算和写入另一个文件时使用结构
【发布时间】:2016-12-25 15:37:18
【问题描述】:

我有一个名为“TEST.txt”的输入数据文件。它包含十名学生的三个不同考试的身份证号码、姓名和成绩。我正在尝试编写一个程序来读取这些输入数据,计算每个学生的考试平均值,然后将平均值> = 45.5的学生的id号、姓名、平均值再次写入名为“RESULT.TXT”的输出文件中" 使用结构。 我想我可以用我定义的结构读取我的输入数据。我想知道如何查找考试(一、二、三)的平均值,设置写入平均值的条件,以及将 ID、名称和平均值写入 RESULTS.TXT。 这是我到目前为止的代码。

#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;
}

【问题讨论】:

  • 请参阅Why is “while ( !feof (file) )” always wrong? 编写该循环的方式是while(fscanf(...) == 5) { printf("%s\n", test[i].name); i++; }
  • 我去看看,但是为什么条件==5?!
  • 请阅读man page for fscanf,然后再采取进一步措施。
  • 最好(虽然并不总是使用)结构的定义和该结构的 typedef 分开。
  • 发布的问题缺少某些关键信息。 IE。一些示例输入,一些预期输出

标签: c arrays structure file-writing file-processing


【解决方案1】:

以下代码:

  1. 是执行所需功能的一种可能方式:
  2. 干净编译
  3. 正确使用 fscanf()
  4. 不使用不受欢迎的功能,如feof()
  5. 有适当的评论
  6. 执行适当的错误检查
  7. 不包含不必要的头文件
  8. 将处理输入文件中任意数量的学生,包括 0 个学生

现在是代码

#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

【讨论】:

  • 谢谢你它工作得很好但我不得不写return 0;虽然:)
  • @utdlegend,因为它“完美运行”,请选择此答案。如果您必须声明:return 0; 那么我可以询问您使用的编译器及其版本号吗?我知道(至少)因为 C99 标准不需要该声明。
【解决方案2】:

我对您编写的代码进行了一些更改, 1.我用循环而不是结构数组,常量定义了要扫描的学生数量。

  1. 我为 RESULT.txt 创建了一个 fOut 指针,我以追加模式打开它。

  2. 我创建了一个条件,如果平均值 > 45.5,学生的详细信息将打印在 RESULT.txt 中。

    附:我用测试文件中的 1 个输入检查了程序。用多行输入测试它,应该可以正常工作。

    #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;
    }
    

【讨论】:

  • 此答案尝试访问无法打开的文件。所以这个答案是错误的。此答案无法检查对fscanf() 的调用结果,因此即使调用失败也会继续。此答案在计算变量 mean 时执行隐式转换,并且由于是整数除法而截断结果。函数:fprintf() 是“昂贵的”并且被调用了不必要的次数。代码缩进不一致。
  • 这个答案包括头文件:string.hmath.h。没有使用这些头文件的内容,因此不应包含在内。
  • 格式说明符 %s 使代码容易受到未定义行为的影响(如果名称长度超过 29 个字符)\
  • 这个答案取决于输入文件中恰好有 10 个学生的标准。这是不必要的约束。
  • 这一行:sum = test.exam1 + test.exam2 + test.exam 3; 无法编译
猜你喜欢
  • 2012-10-22
  • 2013-03-01
  • 1970-01-01
  • 2016-09-04
  • 2021-01-23
  • 1970-01-01
  • 1970-01-01
  • 2015-04-02
  • 1970-01-01
相关资源
最近更新 更多