2017-04-02 95 views
-1

一个文件以我分配我得到两个函数写保存结构在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"); 
} 
} 
+0

你的main()必须调用/调用你已经实现了两个功能,给它们传递适当的参数,你的main也应该检查你的函数返回的返回码并采取适当的动作 – TonyB

+1

传递一个'FILE'指针并在函数内打开文件没有多大意义。你的老师有其他的想法 – user4581301

+0

@ user4581301功能名称是专门给出的。 – angelaziegler13

回答

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"); 
    /* ... */ 
    } 
} 
1

张贴的代码有一些问题。

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

这里是一个可能实现所期望的功能。

#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