C语言二进制文件项目调试出现breakpoint指令执行错误求助
解决C语言二进制文件写入员工信息时的调试断点错误
问题分析与修复步骤
以下是代码中导致断点错误的核心问题及对应修复方案:
1. 文件打开失败未处理
rb+模式要求目标文件已存在,若文件不存在fopen会返回NULL,后续对空指针的读写操作直接触发崩溃。需增加文件不存在时的创建逻辑:
FILE* f = fopen(numef, "rb+"); if (f == NULL) { // 文件不存在则创建并以读写模式打开 f = fopen(numef, "wb+"); if (f == NULL) { printf("无法打开或创建文件\n"); return 1; } }
2. 字符串输入的地址错误
scanf("%s", &numef);中numef是数组名,本身就是指向首元素的指针,无需取地址,修正为:
scanf("%s", numef);
3. 不安全函数与输入缓冲区残留问题
gets函数存在缓冲区溢出风险,改用fgets;同时scanf读取整数后残留的换行符会干扰后续输入,需提前清除:
// 替换原gets(a.nume)的逻辑 printf("Introduceti numele angajatului: "); while (getchar() != '\n'); // 清除缓冲区剩余的换行符 fgets(a.nume, sizeof(a.nume), stdin); a.nume[strcspn(a.nume, "\n")] = '\0'; // 移除fgets读取的换行符
4. double类型的格式符错误
salariu是double类型,scanf需用%lf格式符,而非%d,否则会破坏内存结构:
printf("Salariu: "); scanf("%lf", &a.salariu);
5. feof(stdin)的错误用法
feof不能直接作为循环终止条件,应通过scanf的返回值判断是否成功读取数据:
printf("Introduceti ID angajat: "); while (scanf("%d", &id) == 1) { // 原循环内部逻辑 printf("Introduceti alt ID sau CTRL-Z+ENTER pt a iesi din fisier: "); }
6. ftell返回值类型不匹配
ftell返回long型,用int存储可能导致溢出,修改articole函数的变量类型:
int articole(FILE* f, int lgart) { long pozp; long nrart; pozp = ftell(f); fseek(f, 0, SEEK_END); // 用SEEK_END代替2,提升可读性 nrart = ftell(f) / lgart; fseek(f, pozp, SEEK_SET); // 用SEEK_SET代替0 return (int)nrart; }
修正后的完整代码
#define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <string.h> typedef struct { int id; int EsteSetat; char nume[100]; int varsta; double salariu; char telefon[30]; } Angajat; int articole(FILE* f, int lgart) { long pozp; long nrart; pozp = ftell(f); fseek(f, 0, SEEK_END); nrart = ftell(f) / lgart; fseek(f, pozp, SEEK_SET); return (int)nrart; } void scriere(FILE* f) { int id; Angajat a; printf("Introduceti ID angajat: "); while (scanf("%d", &id) == 1) { int nr_art = articole(f, sizeof(Angajat)); if (id >= nr_art) { Angajat empty_a = {0}; // 初始化空结构体,避免随机值 empty_a.EsteSetat = 0; fseek(f, 0, SEEK_END); for (int i = nr_art; i <= id; i++) { fwrite(&empty_a, sizeof(Angajat), 1, f); } } fseek(f, (long)id * sizeof(Angajat), SEEK_SET); fread(&a, sizeof(Angajat), 1, f); if (a.EsteSetat == 1) { printf("Angajatul deja exista\n"); } else if (a.EsteSetat == 0) { a.EsteSetat = 1; a.id = id; printf("Introduceti numele angajatului: "); while (getchar() != '\n'); fgets(a.nume, sizeof(a.nume), stdin); a.nume[strcspn(a.nume, "\n")] = '\0'; printf("Varsta: "); scanf("%d", &a.varsta); printf("Salariu: "); scanf("%lf", &a.salariu); printf("Telefon: "); scanf("%s", a.telefon); fseek(f, (long)id * sizeof(Angajat), SEEK_SET); fwrite(&a, sizeof(Angajat), 1, f); } printf("Introduceti alt ID sau CTRL-Z+ENTER pt a iesi din fisier: "); } } int main() { char numef[20]; printf("Introduceti numele fisierului: "); scanf("%s", numef); FILE* f = fopen(numef, "rb+"); if (f == NULL) { f = fopen(numef, "wb+"); if (f == NULL) { printf("Eroare la deschiderea fisierului\n"); return 1; } } scriere(f); fclose(f); return 0; }
内容的提问来源于stack exchange,提问作者Vasile Tarcuta
相关产品推荐
相关产品推荐

