如何避免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结构体中新增一个标记,用来区分是否是刚添加的用户。添加用户时标记为「新用户」,执行年龄增长时跳过新用户,之后再重置标记,确保下次循环正常增长。
修改步骤:
- 更新
User结构体,添加标记位:
typedef struct User { int id; int counter; int age; char *name; Type type; int is_new; // 1表示刚添加的新用户,0表示已度过首次循环 struct User *next; } User;
- 修改
addUser函数,初始化标记位:
// 在addUser函数中,初始化完其他字段后添加这行 newUser->is_new = 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结构体中新增字段存储用户被添加时的循环次数,增长年龄时只有当当前循环次数大于用户创建时的次数,才执行增长操作。
修改步骤:
- 在
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); // ... 其他代码保持不变 } }
- 更新
User结构体,添加存储创建循环次数的字段:
typedef struct User { int id; int counter; int age; char *name; Type type; int created_loop; // 用户被添加时的循环次数 struct User *next; } User;
- 修改
addUser函数,接收并记录当前循环次数:
// 修改函数签名,添加循环次数参数 void addUser(User **head, int current_loop) { // ... 其他代码不变 newUser->created_loop = current_loop; // 记录创建时的循环次数 // ... 其他代码不变 }
在main的ADD_USER分支中调用:
case ADD_USER: addUser(&head, loop_count); break;
- 修改
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
相关产品推荐
相关产品推荐

