C语言结构体成员字符串初始化报错问题咨询
解决结构体初始化编译错误及代码中的其他问题
一、编译错误的原因与解决方法
你遇到的编译错误,核心原因是C语言中不能在结构体类型定义时直接给成员变量赋值。结构体定义只是声明一种数据类型,不是创建具体的变量实例,所以不能在定义里写char name[12] = "a";这种初始化语句。
修复方法:
- 先修正结构体定义,去掉成员的赋值:
typedef struct node { char name[12]; // 只声明成员,不赋值 struct node* next; struct node* prev; struct node* lead; } node;
- 如果你需要把
name数组初始化为全'\0'或者初始值为"a",可以在创建结构体实例(malloc之后)进行初始化:- 方法一:用
memset清空整个数组:node* huzong = (node*)malloc(sizeof(node)); memset(huzong->name, 0, sizeof(huzong->name)); // 把name数组全部设为'\0' - 方法二:用
strcpy赋值初始字符串:node* huzong = (node*)malloc(sizeof(node)); strcpy(huzong->name, "a"); // 初始化为"a" - 方法三(C99及以上):在声明结构体栈变量时用初始化列表:
node temp_node = {.name = "a", .next = NULL, .prev = NULL, .lead = NULL};
- 方法一:用
二、代码中其他严重问题排查与修复
除了编译错误,你的代码还有不少逻辑错误和潜在风险,逐一说明:
1. init函数中批量赋值错误
你在init里所有的strcpy都用了huzong->name,比如:
strcpy(huzong->name, "胡总"); // ... strcpy(huzong->name, "王总"); // 这里应该是wangzong->name!
这会导致所有节点的name最后都被覆盖成"小陈",完全不符合预期。必须把每个strcpy的目标改成对应的节点:
strcpy(huzong->name, "胡总"); strcpy(wangzong->name, "王总"); strcpy(zhangzong->name, "张总"); strcpy(lizong->name, "黎总"); strcpy(zhangsan->name, "张三"); // 以此类推,对应每个节点的name
2. list递归函数缺少终止条件
当前的list函数没有判断head是否为NULL,当head->lead或head->next是NULL时,会继续调用list(NULL),然后访问NULL->name,直接导致程序崩溃。修复后:
void list(node* head) { if (head == NULL) return; // 终止条件:空指针直接返回 printf("%s ", head->name); // 加空格分隔,输出更清晰 list(head->lead); list(head->next); }
3. find函数的参数错误与递归逻辑问题
strcmp的第二个参数应该是char*类型,但你写了*ex_name(这是char类型),会导致编译错误;- 递归调用时没有处理返回值,即使子递归找到目标节点,也不会向上返回,最后只会返回
NULL。
修复后的find函数:
node* find(node* head, char* ex_name) { if (head == NULL) return NULL; // 比较两个字符串,参数都是char* if (strcmp(head->name, ex_name) == 0) { return head; } // 先查找lead分支,找到就返回 node* lead_res = find(head->lead, ex_name); if (lead_res != NULL) { return lead_res; } // 再查找next分支,找到就返回 node* next_res = find(head->next, ex_name); if (next_res != NULL) { return next_res; } // 都没找到返回NULL return NULL; }
4. gets函数已被废弃,存在安全风险
gets函数不会检查输入长度,很容易导致缓冲区溢出,应该用fgets替代:
// 替换原来的gets(input); fgets(input, sizeof(input), stdin); // 注意:fgets会把换行符也读进去,需要手动去掉 input[strcspn(input, "\n")] = '\0';
5. main函数中重复调用init导致内存泄漏
你在while(1)循环里每次都调用init(),每次都会malloc一批新节点,但旧的节点没有被free,会导致内存不断泄漏,最终程序崩溃。应该把init()的调用移到循环外面:
int main() { char input[60]="a"; char new_name[12]="a"; char ex_name[12]="a"; node* head = init(); // 只初始化一次 while(1) { node* temp = NULL; // 去掉循环里的head = init(); // ... 后续逻辑 } // 程序结束前记得写一个free函数释放所有节点,避免内存泄漏 }
6. lead和follow函数的逻辑错误
follow函数里,existing->next = new_node;后,new_node->prev应该设为existing,而不是NULL,否则链表的双向链接断裂:
void follow(node* new_node, node* existing) { // 把new_node添加到existing的next位置 new_node->prev = existing; new_node->next = existing->next; if (existing->next != NULL) { existing->next->prev = new_node; } existing->next = new_node; new_node->lead = NULL; }
7. 命令匹配逻辑过于粗糙
你在main里用循环逐个字符匹配init、list等命令,这种方式很容易误触发(比如输入包含这些子串的内容),而且处理new_name和ex_name的逻辑也有问题。建议用strstr或者按空格分割解析命令,比如:
// 替换原来的for循环判断 if (strstr(input, "init") != NULL) { printf("链表构造完成,现有9名员工\n"); } if (strstr(input, "list") != NULL) { list(head); printf("\n"); } // 处理lead命令可以用strtok按空格分割参数,提取新名字和目标名字
内容的提问来源于stack exchange,提问作者Mike
相关产品推荐
相关产品推荐

