C语言中printf使用%s格式符无法输出字符串仅%c可输出首字符的问题排查
嘿,我帮你梳理下代码里的核心问题,这几个指针和逻辑错误直接导致了printf("Name: %s\n", temp->name);没输出的情况:
1. 未初始化的指针变量(最关键问题)
你在main里声明了char *name, *gender;,但这两个指针只是空指针,没有指向任何有效的内存空间。直接用scanf("%s%s", &name, &gender);会把输入的字符串写入未知的内存地址,这属于未定义行为——后续访问temp->name时,指针指向的是无效内存,所以用%s输出时没有内容,而%c只是读取了这个无效地址的第一个字节(刚好是输入字符串的首字符,这完全是巧合)。
解决方法:给指针分配足够的内存,或者直接用字符数组(更简单)。比如改成:
char name[50], gender[10]; // 定义固定大小的数组,足够存储输入的姓名和性别
然后scanf的时候直接传数组名(数组名本身就是指针):
scanf("%s%s", name, gender);
2. 队列判空函数的调用错误
在enqueue1和enqueue2里,你写的是if (isempty1)和if (isempty2),这是在判断函数指针是否非空,而不是调用函数判断队列是否为空。正确的写法应该是调用函数:
if (isempty1()) // 注意括号,调用判空函数
同理enqueue2里也要改成if (isempty2()),否则队列的插入逻辑会一直走首次插入的分支,导致链表结构错误。
3. displayB函数的逻辑错误
displayB里的temp2->link = temp2;会把当前节点的link指向自己,造成死循环,正确的应该是移动指针到下一个节点:
temp2 = temp2->link;
另外,用%c输出temp2->name是错误的,temp2->name是指针,%c会把指针的地址值当成字符输出,正确获取字符串首字符的写法是temp2->name[0]或者*(temp2->name)。
修正后的完整代码
#include <stdio.h> #include <stdlib.h> #include <string.h> // 新增strlen和strcpy需要的头文件 struct lkg { char *name; char *gender; struct lkg *link; } *new, *temp, *front = NULL, *rear = NULL, *new2, *front2 = NULL, *rear2 = NULL, *temp2; int isempty1() { return (front == NULL); } void enqueue1(char *data, char *gend) { new = malloc(sizeof(struct lkg)); // 为每个节点的name和gender分配独立内存,避免后续输入覆盖之前的内容 new->name = malloc(strlen(data) + 1); strcpy(new->name, data); new->gender = malloc(strlen(gend) + 1); strcpy(new->gender, gend); if (isempty1()) { // 修正:调用判空函数 front = rear = new; printf("\ninsertion sucess\n"); printf("\n__________________\n"); } else { rear->link = new; rear = new; } } int isempty2() { return (front2 == NULL); } void enqueue2(char *data, char *gend) { new2 = malloc(sizeof(struct lkg)); // 同样分配内存拷贝字符串 new2->name = malloc(strlen(data) + 1); strcpy(new2->name, data); new2->gender = malloc(strlen(gend) + 1); strcpy(new2->gender, gend); if (isempty2()) { // 修正:调用判空函数 front2 = rear2 = new2; } else { rear2->link = new2; rear2 = new2; } } void displayA() { temp = front; while (temp != NULL) { printf("Name: %s\n", temp->name); temp = temp->link; } } void displayB() { temp2 = front2; while (temp2 != NULL) { printf("Name: %s\n", temp2->name); // 现在可以正常用%s输出了 // printf("Name: %c\n", temp2->name[0]); // 如果要输出首字符,用这个 temp2 = temp2->link; // 修正:移动指针到下一个节点 } } int main() { // main的返回类型应该是int,不是void int choice; char name[50], gender[10]; // 用固定大小数组存储输入 do { printf("press 1 to enter enroll in LKG A \n Press 2 to enter enroll in LKG B\n press -1 to exit:\n"); scanf("%d", &choice); if (choice == 1) { printf("you are enrolling for lkgA\n"); printf("enter the name and gender:\n"); scanf("%s%s", name, gender); // 直接传数组名 enqueue1(name, gender); } else if (choice == 2) { printf("you are enrolling for lkg- B\n"); // 加上换行符,输出更清晰 printf("enter the name and gender:\n"); scanf("%s%s", name, gender); enqueue2(name, gender); } else if (choice != -1) { // 只在不是-1的情况下提示无效选择 printf("not a valid choice\n"); } } while (choice != -1); printf("\n--- LKG A List ---\n"); displayA(); printf("\n--- LKG B List ---\n"); displayB(); // 注意:实际使用时要记得释放malloc分配的内存,避免内存泄漏 return 0; }
额外说明:我在enqueue1和enqueue2里添加了malloc和strcpy,因为如果直接把数组的地址赋值给new->name,所有队列节点的name都会指向同一个数组,后续输入会覆盖之前的内容。分配内存拷贝字符串后,每个节点会保存独立的字符串内容。
内容的提问来源于stack exchange,提问作者sathish

