You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C语言实现链表用户名搜索与结果打印功能异常修复

问题定位

你的链表存储结构定义、头插法添加用户的逻辑没有问题,数据可以正常存入内存。搜索始终返回未找到是4个明确的代码错误导致的:

  • 字符串比较方式错误:C语言中直接用==对比两个char数组,比较的是数组的首内存地址,不是字符串实际存储的内容,这个判断条件永远不会成立
  • 函数参数类型不匹配:searchUser的第二个参数定义为单个char类型,但调用时传入的是字符数组首地址,类型不匹配会导致函数内部读取到的搜索关键词完全错乱
  • 输出逻辑错误:遍历链表的循环结束后,无论是否找到匹配用户都会固定打印“未找到匹配”的提示
  • 缓冲区溢出风险:定义的搜索输入缓冲区searchValue仅20字节,而username字段长度为50字节,输入超过20字符的用户名时会发生内存溢出
  • 编译错误:代码中调用了未实现的listUser、deleteUser函数,直接编译会报错,需要补全逻辑或暂时注释对应分支。
修复方案

按以下步骤修改即可解决问题:

  1. 在头文件引入部分添加#include <string.h>,用于调用标准字符串比较函数
  2. 将main函数中searchValue的数组长度修改为50,和username字段长度保持一致,避免溢出
  3. 修改searchUser的函数签名,第二个参数改为字符指针类型char *searchValue,用于接收传入的搜索关键词
  4. 替换字符串比较逻辑:用strcmp(待比较字符串1, 待比较字符串2)做内容比较,函数返回0时代表两个字符串完全匹配
  5. 增加匹配标记位:遍历链表前初始化标记为0,找到匹配用户时将标记设为1,遍历结束后仅当标记为0时打印“未找到匹配”提示
  6. 规范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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 07:51:19