c - gets 和 fopen 不起作用,甚至更改为 gets_s 和 fopen_s

标签 c file

我的代码:

#include "stdafx.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#define NAME_LEN 30
#define LINE_LEN 80

struct record {
    char *firstname;
    char *lastname;
    long int idnumber;
    int ccode;
    long int phonenum;
    struct record *next;
};
typedef struct record STUDENT;

STUDENT *header;  /* pointer to the start of linked list */

char fname[NAME_LEN], lname[NAME_LEN];
char filename[LINE_LEN];
long int id, phone;
int course;

FILE *fptr;

STUDENT *makenode(long int stud_id, int c_code, long int phone, char *fname, char *lname);
void insert_node();
void delete_node();
void search_node();
void print_list();
void output_list();

int main()
{
    int choice;
    STUDENT *p, *q;
    q = NULL;
    printf(" Enter the input file name: ");
    gets_s(filename);
    fptr = fopen_s(filename, "r");
    if (fptr == NULL)
        printf("Error, can't open the input file %s \n", filename);
    else
    {

        while (!feof(fptr))
        {

            fscanf(fptr, " %s %s %ld %d %ld", fname, lname, &id, &course, &phone);
            /* printf("%s  %s  %ld %d %ld \n",fname, lname,id,course,phone);*/
            p = makenode(id, course, phone, fname, lname);
            p->next = q;
            q = p;

        }
        printf("Created the Linked List\n");
        header = q;
        fclose(fptr);

        do {
            printf("\n\n MENU \n\n");
            printf("1. Insert\n");
            printf("2. Delete\n");
            printf("3. Search\n");
            printf("4. List\n");
            printf("5. Save\n");
            printf("6. Quit\n");
            printf("\n");

            printf("Enter your choice: "); /*Prompt user*/
            scanf("%d", &choice);

            switch (choice)
            {
            case 1:
                insert_node();
                break;
            case 2:
                delete_node();
                break;
            case 3:
                search_node();
                break;
            case 4:
                print_list();
                break;
            case 5:
                output_list();
                break;
            }
        } while (choice != 6);
        return 0;
    }
}

/***************************************************************/
STUDENT *makenode(long int stud_id, int c_id, long int phone, char *fname, char *lname)
{
    STUDENT *ptr;

    ptr = (STUDENT *)malloc(sizeof(STUDENT));
    if (ptr != NULL)
    {
        ptr->next = NULL;
        ptr->firstname = (char *)malloc(strlen(fname) + 1);
        strcpy(ptr->firstname, fname);
        ptr->lastname = (char *)malloc(strlen(lname) + 1);
        strcpy(ptr->lastname, lname);
        ptr->idnumber = stud_id;
        ptr->ccode = c_id;
        ptr->phonenum = phone;
        return(ptr);
    }
    else
    {
        printf("Memory not allocated\n");
    }

}
/************************************************************/
void insert_node()
{

}
/************************************************************/
void delete_node()
{

}
/***********************************************************/
void search_node()
{

}
/**********************************************************/
void output_list()
{

}
/********************************************************/
void print_list()
{
    STUDENT *p1;
    p1 = header;
    while (p1 != NULL)
    {
        printf("%s %s %ld %d %ld\n", p1->firstname,
            p1->lastname, p1->idnumber, p1->ccode, p1->phonenum);
        p1 = p1->next;
    }
}
/********************************************************/

我按照错误中的说明进行操作。我将 getsfopen 更改为 gets_sfopen_s,但出现以下错误:

  • IntelliSense:函数调用中的参数太少
  • IntelliSense:“char *”类型的参数与 “FILE **”类型的参数
  • IntelliSense:“errno_t”类型的值不能分配给 “FILE *”类型的实体错误
  • 错误 C2660:“fopen_s”:函数不接受 2 个参数

最佳答案

gets_s()fopen_s() 采用与 getsfopen 不同的参数。 gets_s() 获取接收缓冲区的大小:

gets_s(filename, sizeof filename);

fopen_s()采用指向FILE*的指针:

if (fopen_s(&fptr, filename, "r"))
    printf("Error, can't open the input file %s\n", filename);

fopen_s 返回错误代码。您可以保存它,并在失败时使用 strerror() 获取相应的错误消息。

另请注意,您的 while(!feof(fptr)) 循环将无法在文件末尾正确停止,它可能会重复最后一组值。请参阅Why is “while ( !feof (file) )” always wrong?并以这种方式修复代码:

    while (fscanf(fptr, " %s %s %ld %d %ld", fname, lname, &id, &course, &phone) == 5)) {
        /* printf("%s  %s  %ld %d %ld\n",fname, lname,id,course,phone); */
        p = makenode(id, course, phone, fname, lname);
        p->next = q;
        q = p;
    }

链接列表的方式实际上会颠倒文件内容中节点的顺序,这可能不是您想要做的。

使用 scanf("%d", &choice); 获取用户选择是有风险的:如果用户键入非数字、非空格字符,程序将进入无限循环。至少检查 scanf 的返回值,或者从用户处获取整行,测试文件结尾,并使用 sscanf() 解析用户选择。

如果出现内存分配失败的情况,您只需测试三个潜在故障之一,然后打印一条消息。您应该返回 NULL 并在调用函数中测试它,或者使用 exit()abort() 中止程序。

关于c - gets 和 fopen 不起作用,甚至更改为 gets_s 和 fopen_s,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29692006/

相关文章:

c++ - 使 DEV++ 与 Turbo C++ 的代码/ header 兼容

c - 如何使用宽字符到多字节删除字符串字符之间的空格?

mongodb - 在 golang 中使用 griddfs 从 Mongodb 下载文件

java - GZIPOutputStream 不更新 Gzip 大小字节

c - 回文数,代码不起作用

C fscanf 以正确的格式读取

c - 发送指向函数的指针

c - 如何在 C 中使用 zlib 库对 websocket permessage-deflate 进行编码和解码?

java - 在 Spring Boot 中发送文件

python - 如何在Python中完成线程的功能之前使其保持事件状态?