C语言实现链表用户名搜索与结果打印功能异常修复
问题定位
你的链表存储结构定义、头插法添加用户的逻辑没有问题,数据可以正常存入内存。搜索始终返回未找到是4个明确的代码错误导致的:
- 字符串比较方式错误:C语言中直接用
==对比两个char数组,比较的是数组的首内存地址,不是字符串实际存储的内容,这个判断条件永远不会成立 - 函数参数类型不匹配:
searchUser的第二个参数定义为单个char类型,但调用时传入的是字符数组首地址,类型不匹配会导致函数内部读取到的搜索关键词完全错乱 - 输出逻辑错误:遍历链表的循环结束后,无论是否找到匹配用户都会固定打印“未找到匹配”的提示
- 缓冲区溢出风险:定义的搜索输入缓冲区
searchValue仅20字节,而username字段长度为50字节,输入超过20字符的用户名时会发生内存溢出 - 编译错误:代码中调用了未实现的
listUser、deleteUser函数,直接编译会报错,需要补全逻辑或暂时注释对应分支。
修复方案
按以下步骤修改即可解决问题:
- 在头文件引入部分添加
#include <string.h>,用于调用标准字符串比较函数 - 将
main函数中searchValue的数组长度修改为50,和username字段长度保持一致,避免溢出 - 修改
searchUser的函数签名,第二个参数改为字符指针类型char *searchValue,用于接收传入的搜索关键词 - 替换字符串比较逻辑:用
strcmp(待比较字符串1, 待比较字符串2)做内容比较,函数返回0时代表两个字符串完全匹配 - 增加匹配标记位:遍历链表前初始化标记为0,找到匹配用户时将标记设为1,遍历结束后仅当标记为0时打印“未找到匹配”提示
- 规范
scanf写法:读取字符串时数组名本身就是首地址,不需要额外加&取地址符,避免未定义行为。
修复后核心代码示例
#include <stdio.h> #include <stdlib.h> #include <string.h> // 新增字符串处理头文件 #define MAX 100 #define TRUE 1 #define FALSE 0 struct fitnessTracking { char activity[50], unit[50]; int calories; float total, weight, height, bmi; }; struct recordDate { int dd, mm, yyyy; int duration; }; struct user { char username[50]; struct fitnessTracking tracker; struct recordDate record; }; struct Number { struct Number *ptrnext; struct user member; }; struct Number *newptr, *currentptr; // 提前声明函数,避免隐式声明报错 void addUser(struct Number** head_ref); void searchUser(struct Number* head, char *searchValue); void listUser(struct Number* head); void deleteUser(); int main(void) { int selection; int choice=TRUE; char searchValue[50]; // 缓冲区长度改为和username一致的50字节 struct Number* head = NULL; while(choice==TRUE) { printf("\n\n1 - Enter new user"); printf("\n2 - Search by username"); printf("\n3 - Display user list"); printf("\n4 - Delete user from list"); printf("\n5 - Exit\n"); printf("\nEnter choice: "); scanf("%d",&selection); switch(selection) { case 1: addUser(&head); break; case 2: printf("\nSearch username: "); scanf(" %[^\n]%*c", searchValue); // 去掉多余的&取地址符 searchUser(head, searchValue); break; case 3: listUser(head); break; case 4: deleteUser(); break; case 5: choice=FALSE; break; default: printf("\nEnter available choice from above"); } } return 0; } void addUser(struct Number** head_ref){ newptr=(struct Number *)malloc(sizeof(struct Number)); printf("\nEnter name: "); scanf(" %[^\n]%*c", newptr->member.username); // 去掉多余的&取地址符 printf("\nEnter weight: "); scanf("%f", &newptr->member.tracker.weight); printf("\nEnter height: "); scanf("%f", &newptr->member.tracker.height); printf("\nEnter activity: "); scanf(" %[^\n]%*c", newptr->member.tracker.activity); // 去掉多余的&取地址符 printf("\nEnter activity duration (in minutes): "); scanf("%d", &newptr->member.record.duration); printf("\nEnter total: "); scanf("%f", &newptr->member.tracker.total); printf("\nEnter unit: "); scanf(" %[^\n]%*c", newptr->member.tracker.unit); // 去掉多余的&取地址符 printf("\nEnter calories: "); scanf("%d", &newptr->member.tracker.calories); printf("\nEnter activity date (dd/mm/yyyy): "); scanf("%d/%d/%d", &newptr->member.record.dd, &newptr->member.record.mm, &newptr->member.record.yyyy); float bmi = 0; float weight = newptr->member.tracker.weight; float height = newptr->member.tracker.height; bmi = (weight) / (height*height); newptr->member.tracker.bmi = bmi; newptr->ptrnext = (*head_ref); (*head_ref) = newptr; } void searchUser(struct Number* head, char *searchValue){ // 参数改为字符指针类型 char a[20]="Name",b[20]="Weight(kg)", c[20]="Height(m)", d[20]="BMI", e[20]="Activity"; char f[20]="Duration(minutes)", g[20]="Total", h[20]="Unit", i[20]="Calories(kal)", j[20]="Date"; struct Number* temp=head; int found = 0; // 匹配标记位 printf("%-15s %-10s %-10s %-10s %-15s %-20s %-15s %-15s %-15s %-15s\n", a,b,c,d,e,f,g,h,i,j); while(temp != NULL){ // 用strcmp比较字符串实际内容,返回0代表完全匹配 if(strcmp(temp->member.username, searchValue) == 0){ printf("%-15s %-10.2f %-10.2f %-10.2f %-15s %-20d %-15.2f %-15s %-15d %d/%d/%-15d\n\n", temp->member.username, temp->member.tracker.weight, temp->member.tracker.height, temp->member.tracker.bmi, temp->member.tracker.activity, temp->member.record.duration, temp->member.tracker.total, temp->member.tracker.unit, temp->member.tracker.calories, temp->member.record.dd, temp->member.record.mm, temp->member.record.yyyy); found = 1; } temp=temp->ptrnext; } // 仅当没有匹配结果时打印提示 if(!found){ printf("Sorry, no match found\n"); } } // 未实现的函数暂时留空,避免编译报错 void listUser(struct Number* head){ // 参考searchUser的遍历逻辑实现全量打印即可 } void deleteUser(){ // 参考搜索逻辑找到目标节点后,调整前后节点指针、释放内存即可 }
注:当前
addUser使用头插法添加节点,最新录入的用户会显示在链表最前端,该逻辑本身没有问题,不需要调整。
内容的提问来源于stack exchange,提问作者user16045271
相关产品推荐
相关产品推荐

