将结构保存到C

时间:2017-04-02 04:20:41

标签: c

在我的任务中,我被赋予两个函数来编写

int openFileFromConsole(FILE *fp)

它使用空文件指针作为函数的输入,使用引用调用。并更新指针以指向适当的HDD地址。重要提示:稍后,它会通过控制台要求用户提供名称,并询问文件打开类型:" w"," r"," a"并更新文件指针。如果成功则返回1,如果失败则返回0。

void saveStudentGradeInfoTofile(FILE *fp)

此函数获取学生信息并将其首先保存到学生数据类型(结构但使用typedef伪装),然后将其保存到文件中。学生信息由注册表通过控制台提供。这会将文件指针作为输入引用,并使用fprint更新文件。

该程序应该根据用户输入通过控制台打开文件,然后收集信息并将它们存储到结构中并将其保存到该文件。我已经编写了两个函数(我认为正确吗?)。但我是很难实现它们到main(),因为第一个是一个int类型的函数。任何帮助将不胜感激。

typedef struct student {
    char name[50];
    char id [20];
    int score;
}student;

int openFileFromConsole(FILE *fp);
void saveStudentGradeInfoTofile(FILE *fp);

int main()
{
   return 0;
}


int openFileFromConsole(FILE *fp){
    char filePath[100],fileOpenType[10];
    printf("Enter Path name: ");
    scanf("%s", filePath);
    printf("Enter file open type w, r or a: ");
    scanf("%s", fileOpenType);

     fp = fopen(filePath,fileOpenType);
     if(fp != NULL) {
        printf("File has been opened");
     return 1;

     }
     else printf("File not found");
     return 0;
}
void saveStudentGradeInfoTofile(FILE *fp){

     int numOfStudent ;
     student s[100];
     printf ("Get the number of students :");
     scanf("%d",&numOfStudent);

     for(int i = 0; i < numOfStudent; i++) {


         printf("\nEnter ID number:");

         scanf(" %s",s[i].id);

         printf("Enter name: ");
         scanf("%s,",s[i].name); 

         printf("Enter score: ");
         scanf("%d",&s[i].score);

         fprintf(fp,"id : %s, Name: %s,  score =%d\n",s[i].id,s[i].name,s[i].score);

         printf("\n");
}
}

2 个答案:

答案 0 :(得分:1)

发布的代码有一些问题。

  1. 它不遵循公理:每行只有一个语句,并且(最多)每个语句一个变量声明。结果是代码更难理解,调试,维护。 / LI>
  2. 对系统函数的调用需要检查其返回值,以确保操作成功。
  3. 要修改位于调用函数中的指针指向的位置,必须将指针作为指针传递给指针&#39;。
  4. 在调用任何scanf()系列函数时,使用&#39;%s&#39;输入转换说明符,总是包含一个比输入缓冲区长度小1的MAX CHARACTERS修饰符,因此用户不能超出输入缓冲区。这种溢出会导致未定义的行为,并可能导致seg故障事件。
  5. 使用&#39;%s&#39;输入转换说明符,在说明符之前插入一个空格以使用任何前导的空格&#39;,就像任何换行序列一样。
  6. 退出程序时始终清理。不要将清理工作留给操作系统。
  7. 使用永远不会少于0的数值时,最好使用size_t而不是int
  8. 发布的代码永远不会从学生成绩信息文件中读取,因此永远不应使用r
  9. 打开
  10. &#39;模式&#39;在对fopen()的调用中始终是一个字符串,即使它只是一个字符串,因此需要写成"w"而不仅仅是w
  11. 代码中包含大量的魔法&#39;数字。 &#39;魔术&#39;数字是没有依据的数字。这些数字使得理解,调试等比必要的困难得多。建议使用enum语句或#define语句来提供这些“魔法”#39;编号有意义的名称,然后在整个代码中使用那些有意义的名称。
  12. 为了便于阅读和理解,始终缩进代码。在每个开口支架后缩进&#39; {&#39;。在每次闭幕后都会无意义地使用&#39;}。建议每个缩进级别使用4个空格,因为即使使用可变宽度字体也可以看到。
  13. 结合一个结构&#39;这是一个糟糕的编程习惯。使用&#39; typedef&#39;定义。分别编码。
  14. 在发布代码时,包含所需的头文件语句,因此我们不必猜测您的代码实际使用了什么。
  15. 为了便于阅读和理解,通过一个空白行分隔代码块(for,if,else,do ... while,switch,case,default)。通过2或3个空行分隔功能(保持一致)。
  16. 虽然现代编译器将处理名称的重复,但现代编译器将结构名称保留在与typedef名称不同的命名空间中,这是一种糟糕的编程习惯,很容易导致混淆。建议保持名称的独特性(尽管在这个答案中没有遵循。
  17. 以下是所需功能的可能实现:

    #include <stdio.h>  // fopen(), fclose(), perror(), FILE
    #include <stdlib.h> // exit(), EXIT_FAILURE
    
    enum {
        MAX_NAME_LEN     =50,
        MAX_ID_LEN       =20,
        MAX_PATH_LEN     =100,
        MAX_TYPE_LEN     =10,
        MAX_NUM_STUDENTS =100
    };
    
    struct student
    {
        char name[ MAX_NAME_LEN ];
        char id [ MAX_ID_LEN ];
        int score;
    };
    
    typedef struct student student;
    
    int openFileFromConsole(FILE **fp);
    void saveStudentGradeInfoTofile(FILE *fp);
    
    int main( void )
    {
        FILE * fp = NULL;
    
        int openStatus = openFileFromConsole(&fp);
    
        if( 0 == openStatus )
        {
            saveStudentGradeInfoTofile( fp );
        }
    
        fclose( fp );
       return 0;
    } // end function: main
    
    
    int openFileFromConsole(FILE **fp)
    {
        char filePath[ MAX_PATH_LEN ];
        char fileOpenType;
    
        printf("Enter Path name: ");
        if( 1 != scanf("%100s", filePath) )
        {
            perror( "scanf for file path failed" );
            exit( EXIT_FAILURE );
        }
    
        // implied else, scanf successful
    
        printf("Enter file open type w, r or a: ");
        if( 1 != scanf(" %c", &fileOpenType) )
        {
            perror( "scanf for file open type failed" );
            exit( EXIT_FAILURE );
        }
    
        // implied else, scanf successful
    
        char buffer[ MAX_TYPE_LEN ];
        buffer[0] = '\"';
        buffer[1] = fileOpenType;
        buffer[2] = '\"';
        buffer[3] = '\0';
        *fp = fopen(filePath, buffer);
        if( *fp )
        {
            return 1;
        }
    
        else
        {
             perror( "fopen failed" );
             return 0;
        }
    } // end function: openFileFromConsole
    
    
    void saveStudentGradeInfoTofile(FILE *fp)
    {
         size_t numOfStudent;
         student s[ MAX_NUM_STUDENTS ];
    
         printf ("Get the number of students :");
         if( 1 != scanf("%lu",&numOfStudent) )
         {
             perror( "scanf for number of students failed:" );
             fclose( fp );
             exit( EXIT_FAILURE );
         }
    
         // implied else, scanf successful
    
         for( size_t i = 0; i < numOfStudent; i++)
         {
             printf("\nEnter ID number:");
             if( 1 != scanf(" %19s",s[i].id) )
             {
                 perror( "scanf for student ID failed" );
                 fclose( fp );
                 exit( EXIT_FAILURE );
             }
    
             // implied else, scanf successful
    
             printf("Enter name: ");
             if( 1 != scanf(" %49s,",s[i].name) )
             {
                 perror( "scanf for student ID failed" );
                 fclose( fp );
                 exit( EXIT_FAILURE );
             }
    
             // implied else, scanf successful
    
             printf("Enter score: ");
             if( 1 != scanf("%d",&s[i].score) )
             {
                 perror( "scanf for student Score failed" );
                 fclose( fp );
                 exit( EXIT_FAILURE );
             }
    
             // implied else, scanf successful
    
             fprintf(fp,"id : %s, Name: %s,  score =%d\n",
                    s[i].id,
                    s[i].name,
                    s[i].score);
    
             printf("\n");
        } // end while
    } // end function: saveStudentGradeInfoToFile
    

答案 1 :(得分:0)

以防您希望将文件路径作为参数传递给程序

int main(int c /* argument counter */, char *v[] /*argument list */)
{
   FILE *fp;
   if(c >= 2) {
   char *path = v[1]; /* this is the second argument (the first one, v[0], is the program's name): ./foo myfile.txt */
   fp = fopen(path, "your mode goes here");
   /* ... */
   }
}