添加联系人的do/while循环触发Segmentation Fault问题求助
解决你的
addContact函数段错误问题 嘿,我仔细看了你的addContact函数代码,触发段错误主要是几个容易忽略的细节问题,我帮你逐一拆解并给出修复方案:
1. 未初始化的FILE *fptr直接导致崩溃
你声明了FILE *fptr但从来没有打开文件就直接调用fprintf,这会让程序访问非法内存地址,直接触发段错误。
修复方法:
在使用fptr前,用fopen打开目标文件,同时要检查文件是否成功打开,避免后续操作出错:
fptr = fopen("contacts.txt", "a+"); // 以追加+读取模式打开,可根据需求调整模式 if (fptr == NULL) { perror("Failed to open file"); free(newPtr); // 避免内存泄漏 return; }
记得在文件操作完成后用fclose(fptr);关闭文件。
2. 未初始化的prevPtr引发野指针访问
当链表为空时(*sPtr是NULL),crntPtr初始化为NULL,第二个while循环(while (crntPtr != NULL && ...))根本不会执行,此时prevPtr是未初始化的野指针。后续判断if (prevPtr == NULL)时,野指针的值是随机的,大概率不会等于NULL,程序会进入else分支访问prevPtr->next,直接触发段错误。
修复方法:
显式将prevPtr初始化为NULL:
contactPtr prevPtr = NULL;
3. fflush(stdin)是未定义行为
标准C中,fflush只对输出流有效,对输入流stdin调用fflush是未定义行为,不同编译器可能有不同表现,甚至导致异常。
修复方法:
用自定义函数清空输入缓冲区:
void clearInputBuffer() { int c; while ((c = getchar()) != '\n' && c != EOF); }
然后把所有fflush(stdin);替换成clearInputBuffer();。
4. 不安全的gets函数存在溢出风险
gets函数不会检查输入长度,很容易导致缓冲区溢出,这也是潜在的崩溃隐患(输入过长时会触发)。
修复方法:
用fgets替代gets,同时处理掉fgets读取的换行符:
// 读取姓名 printf("Enter contact name: "); clearInputBuffer(); fgets(newPtr->name, sizeof(newPtr->name), stdin); newPtr->name[strcspn(newPtr->name, "\n")] = '\0'; // 读取电话号码同理 printf("Enter contact number: "); clearInputBuffer(); fgets(newPtr->phoneNum, sizeof(newPtr->phoneNum), stdin); newPtr->phoneNum[strcspn(newPtr->phoneNum, "\n")] = '\0';
修复后的完整函数示例
#include <stdio.h> #include <stdlib.h> #include <string.h> typedef struct Contact { char name[50]; char phoneNum[20]; struct Contact *next; } Contact; typedef Contact* contactPtr; void clearInputBuffer() { int c; while ((c = getchar()) != '\n' && c != EOF); } void addContact(contactPtr *sPtr) { FILE *fptr; contactPtr checkPtr = *sPtr; contactPtr crntPtr = checkPtr; contactPtr prevPtr = NULL; // 显式初始化prevPtr contactPtr newPtr; int check = 0; // 检查malloc是否成功 newPtr = (Contact *)malloc(sizeof(Contact)); if (newPtr == NULL) { perror("Failed to allocate memory"); return; } printf("Enter contact name: "); clearInputBuffer(); fgets(newPtr->name, sizeof(newPtr->name), stdin); newPtr->name[strcspn(newPtr->name, "\n")] = '\0'; do { checkPtr = crntPtr; check = 0; printf("Enter contact number: "); clearInputBuffer(); fgets(newPtr->phoneNum, sizeof(newPtr->phoneNum), stdin); newPtr->phoneNum[strcspn(newPtr->phoneNum, "\n")] = '\0'; for (; checkPtr != NULL; checkPtr = checkPtr->next) { if (strcmp(checkPtr->phoneNum, newPtr->phoneNum) == 0) { printf("Phone No is already available\n"); check = 1; break; } } } while (check); // 打开文件并检查 fptr = fopen("contacts.txt", "a+"); if (fptr == NULL) { perror("Failed to open file"); free(newPtr); return; } fprintf(fptr, "\n%s\n", newPtr->name); fprintf(fptr, "%s\n", newPtr->phoneNum); fclose(fptr); // 找到正确的插入位置 crntPtr = *sPtr; while (crntPtr != NULL && strcmp(newPtr->name, crntPtr->name) > 0) { prevPtr = crntPtr; crntPtr = crntPtr->next; } if (prevPtr == NULL) { newPtr->next = *sPtr; *sPtr = newPtr; } else { prevPtr->next = newPtr; newPtr->next = crntPtr; } }
内容的提问来源于stack exchange,提问作者chro1104
相关产品推荐
相关产品推荐

