首页 文章

为什么跳过fgets()?

提问于
浏览
0
typedef struct {
int serial_no;
char s_name[100];
char s_street[50];
char s_town[20];
int s_speaker_no;
int max_no_teachers;
int no_applied_teachers;
} type_seminar;


void add_seminar() {
int seminar_number, temp_int;
char *temp_string;
temp_string = (char*) malloc(100 * sizeof(char));

FILE *f_sem;
FILE *f_school;
f_sem = fopen("seminars.bin", "a");
f_school = fopen("school_list.txt", "r");

fgets(temp_string, 10, f_school);
seminar_number = (atoi(temp_string) + 1);

type_seminar *temp_s = (type_seminar*) malloc(sizeof(type_seminar));
temp_s->serial_no = seminar_number;
temp_s->no_applied_teachers = 0;
temp_s->s_speaker_no = 0;

printf("Enter the seminar title: \n");
fgets(temp_string, sizeof temp_string, stdin);
strcpy(temp_s->s_name, temp_string);

printf("Enter the seminar address(street and house number): \n");
fgets(temp_string, sizeof temp_string, stdin);
strcpy(temp_s->s_street, temp_string);

printf("Enter the town (where the seminar will be held) : \n");
fgets(temp_string, sizeof temp_string, stdin);
strcpy(temp_s->s_town, temp_string);

printf("Enter the maximum number of the seminar participants : \n");
fgets(temp_string, sizeof temp_string, stdin);
temp_int = (atoi(temp_string));
temp_s->max_no_teachers = temp_int;

free(temp_s);
free(temp_string);
fclose(f_school);
fclose(f_sem);
}

每次运行该函数时,都会跳过用户输入研讨会 Headers 的第一个fgets() . 我假设从txt文件读取的previus fgets()会在缓冲区中留下一些东西?我不知道怎么解决这个问题...而且,我是C的新手和一般的编程,所以如果它是obvius ...抱歉:/ /

1 回答

  • 3

    感谢使用 fgets 以避免缓冲区溢出,但你并不完全在那里:

    char *temp_string;
    :
    temp_string = (char*) malloc(100 * sizeof(char));
    :
    fgets(temp_string, sizeof temp_string, stdin);
    

    temp_string 的大小是一个字符指针的大小,而不是你最有可能读取四个(或者如果你有64位指针可能是八个)字符最大的缓冲区的大小,那么其余的都留在输入流中 .

    您应该使用缓冲区的大小(100,尽管它作为定义的常量而不是硬编码值会更好) .

    或者,看看this getLine routine,它可以处理很多边缘情况 .


    而且,顺便说一句,你不需要乘以 sizeof(char) ,因为根据定义,它始终保证为 1 - 执行乘法只会堵塞你的源代码 .

    您也不应该从 malloc 转换返回值,因为它可以隐藏某些微妙的错误 . C非常能够将 the void *`返回值隐式转换为任何其他指针类型 .

    您需要注意的另一件事是:即使您使用 fgets 来保护 temp_string 缓冲区不被溢出,也没有为您的 strcpy 功能提供类似的保护 .

    这意味着它将允许您输入一个80个字符的城镇名称,然后它将吹掉它不应该触及的内存,因为你进入了20个字符的结构字段 .

相关问题