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

C语言中printf使用%s格式符无法输出字符串仅%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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 04:17:32