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

如何避免C语言链表中新添加用户在同一循环迭代中被增龄

问题描述

我正在实现一个存储User的链表,每个用户包含int age;字段。程序支持addUser、findUser、exit等操作。需求是:每次while循环迭代时,给所有已存在的用户年龄加5,但刚添加的新用户在第一次循环中要保持年龄为0。当前实现里新用户也会被increaseUsersAge函数影响,该怎么解决?

以下是我的代码:

#include <stdio.h>
#include <stdlib.h>

#define BUFFER 1024
#define ADD_USER 1
#define ADD_USER 1
#define COMPLAINTS_AM 2
#define COMPLAINTS_EDA 3
#define COMPLAINTS_ASAFSUF 4
#define FIND_USER 5
#define PRINT_ALL_USERS 6
#define EXIT 7
#define TRUE 1
#define FALSE 0

typedef enum Type
{
    Am = 0,
    Eda,
    Asafsuf
} Type;

typedef struct User
{
    int id;
    int counter;
    int age;
    char *name;
    Type type;
    struct User *next;
} User;

int main()
{
    int choice = 0;
    int isGoingOn = TRUE;

    User *head = NULL;

    while (isGoingOn)
    {
        printMenu();
        scanf("%d", &choice);

        increaseUsersAge(&head); // 这里有问题!
        RemoveUsersOverForty(&head);

        switch (choice)
        {
        case ADD_USER:
            addUser(&head);
            break;
        case COMPLAINTS_AM:
            printf("Ma Nishte?\n");
            addOneForAm(&head);
            break;
        case COMPLAINTS_EDA:
            printf("Lehamiteno berahav\n");
            addOneForEda(&head);
            break;
        case COMPLAINTS_ASAFSUF:
            printf("Mi Yaachileno Basar?\n");
            addOneForAsafsuf(&head);
            break;
        case FIND_USER:
            printUserById(&head);
            break;
        case PRINT_ALL_USERS:
            printAllUsers(head);
            break;
        case EXIT:
            isGoingOn = FALSE;
            break;
        default:
            printf("wrong choose please choose again.\n");
        }

        printf("\n");
    }

    freeMemory(&head);
    return EXIT_SUCCESS;
}

addUser函数:

void addUser(User **head)
{
    // create new user
    User *newUser = malloc(sizeof(User));

    // get id from user
    printf("please insert id:\n");
    scanf("%d", &newUser->id);
    if (checkValidId(head, newUser->id) == FALSE)
    {
        printf("error\n");
        freeMemory(head);
        exit(1);
    }

    // get name from user
    printf("please insert name:\n");
    newUser->name = malloc(BUFFER * sizeof(char));
    scanf(" %[^\n]s", newUser->name);

    // get type from user
    printf("please insert type (Am - 0, Eda - 1, Asafsuf - 2):\n");
    scanf("%d", &newUser->type);

    newUser->counter = 0;
    newUser->age = 0;
    newUser->next = NULL;

    if (*head == NULL)
    {
        *head = newUser;
        return;
    }

    // insert to end of linked list
    User *curr = *head;
    while (curr->next != NULL)
    {
        curr = curr->next;
    }
    curr->next = newUser;
}

increaseUsersAge函数:

void increaseUsersAge(User **head)
{
    User *curr = *head;
    while (curr)
    {
        curr->age += 5;
        curr = curr->next;
    }
}

解决方案

下面提供三种可行的解决思路,你可以根据业务逻辑选择最合适的一种:

方法1:给用户添加「新用户标记位」

在User结构体中新增一个标记,用来区分是否是刚添加的用户。添加用户时标记为「新用户」,执行年龄增长时跳过新用户,之后再重置标记,确保下次循环正常增长。

修改步骤:

  1. 更新User结构体,添加标记位:
typedef struct User
{
    int id;
    int counter;
    int age;
    char *name;
    Type type;
    int is_new; // 1表示刚添加的新用户,0表示已度过首次循环
    struct User *next;
} User;
  1. 修改addUser函数,初始化标记位:
// 在addUser函数中,初始化完其他字段后添加这行
newUser->is_new = 1;
  1. 修改increaseUsersAge函数,跳过新用户并重置标记:
void increaseUsersAge(User **head)
{
    User *curr = *head;
    // 第一步:给非新用户增长年龄
    while (curr)
    {
        if (!curr->is_new)
        {
            curr->age += 5;
        }
        curr = curr->next;
    }

    // 第二步:重置所有新用户的标记,确保下次循环正常增长
    curr = *head;
    while (curr)
    {
        if (curr->is_new)
        {
            curr->is_new = 0;
        }
        curr = curr->next;
    }
}

方法2:调整循环内操作的执行顺序

原逻辑是先增长年龄,再处理用户操作(包括添加新用户),导致新用户刚被添加就被增长年龄。把增长年龄的操作移到switch之后,这样流程变为:先处理用户操作(添加新用户),再执行年龄增长——新用户是本次循环添加的,要等到下一次循环才会被增长,自然首次保持0。

修改后的main函数核心部分:

while (isGoingOn)
{
    printMenu();
    scanf("%d", &choice);

    switch (choice)
    {
    case ADD_USER:
        addUser(&head);
        break;
    case COMPLAINTS_AM:
        printf("Ma Nishte?\n");
        addOneForAm(&head);
        break;
    case COMPLAINTS_EDA:
        printf("Lehamiteno berahav\n");
        addOneForEda(&head);
        break;
    case COMPLAINTS_ASAFSUF:
        printf("Mi Yaachileno Basar?\n");
        addOneForAsafsuf(&head);
        break;
    case FIND_USER:
        printUserById(&head);
        break;
    case PRINT_ALL_USERS:
        printAllUsers(head);
        break;
    case EXIT:
        isGoingOn = FALSE;
        break;
    default:
        printf("wrong choose please choose again.\n");
    }

    // 把增长年龄和移除操作移到switch之后,退出时不执行
    if (isGoingOn)
    {
        increaseUsersAge(&head);
        RemoveUsersOverForty(&head);
    }

    printf("\n");
}

注意:这种方法需要确认业务逻辑是否允许调整顺序,如果原需求必须先增长年龄再处理用户操作,这种方法不适用;如果顺序不影响核心业务,这是最简洁的解决方案。

方法3:记录用户创建时的循环次数

在main函数中维护一个循环计数器,每次循环递增。User结构体中新增字段存储用户被添加时的循环次数,增长年龄时只有当当前循环次数大于用户创建时的次数,才执行增长操作。

修改步骤:

  1. 在main中添加循环计数器:
int main()
{
    int choice = 0;
    int isGoingOn = TRUE;
    int loop_count = 0; // 新增循环计数器
    User *head = NULL;

    while (isGoingOn)
    {
        loop_count++; // 每次循环开始时递增
        printMenu();
        scanf("%d", &choice);

        increaseUsersAge(&head, loop_count); // 传入当前循环次数
        RemoveUsersOverForty(&head);

        // ... 其他代码保持不变
    }
}
  1. 更新User结构体,添加存储创建循环次数的字段:
typedef struct User
{
    int id;
    int counter;
    int age;
    char *name;
    Type type;
    int created_loop; // 用户被添加时的循环次数
    struct User *next;
} User;
  1. 修改addUser函数,接收并记录当前循环次数:
// 修改函数签名,添加循环次数参数
void addUser(User **head, int current_loop)
{
    // ... 其他代码不变
    newUser->created_loop = current_loop; // 记录创建时的循环次数
    // ... 其他代码不变
}

在main的ADD_USER分支中调用:

case ADD_USER:
    addUser(&head, loop_count);
    break;
  1. 修改increaseUsersAge函数,根据循环次数判断是否增长:
// 修改函数签名,接收当前循环次数
void increaseUsersAge(User **head, int current_loop)
{
    User *curr = *head;
    while (curr)
    {
        // 只有当前循环次数大于用户创建时的次数,才增长年龄
        if (current_loop > curr->created_loop)
        {
            curr->age += 5;
        }
        curr = curr->next;
    }
}

内容的提问来源于stack exchange,提问作者CStudent

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 22:05:53