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

C语言使用scanf输入含空格的多行字符串时遇到问题如何解决?

问题根源

你遇到的输入中断问题不是%[^\n]读不了空格(该格式符本身就是读到换行才停止,天然支持读取带空格的内容),核心原因是每次读完一行内容后,输入缓冲区中残留的换行符\n没有被消费,下一次进入循环执行scanf("%99[^\n]",...)时,第一个匹配到的字符就是\n,直接匹配失败返回0,后续输入就会卡住。

同时原有代码还有两个隐含问题:

  • while(!feof(stdin))的判断逻辑不可靠,feof是读操作失败后才会标记EOF,会导致最后一行多执行一次内存申请和输入逻辑
  • 没有校验scanf的返回值,匹配失败时会往数组里写入无效内容

解决方案

因为你不能使用getchar系列函数,我们可以直接用scanf自带的格式符能力处理换行:在每次%[^\n]后面加%*1[\n],这里*代表忽略匹配到的内容、不会写入变量,刚好可以匹配并丢弃缓冲区里的换行符,完全符合你的使用限制。

修正后的完整代码如下:

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

int main () {
    int i = 0;
    // 初始支持最多1000行输入,需要更多可以自行调整,或者加动态扩容逻辑
    char **list = malloc(1000 * sizeof(char*));
    if (list == NULL) {
        perror("内存申请失败");
        return 1;
    }

    while(i < 1000) { // 加边界判断避免数组越界
        list[i] = malloc(1000 * sizeof(char));
        if (list[i] == NULL) {
            perror("内存申请失败");
            return 1;
        }
        printf("Enter string with num %d: ", i+1);
        // %99[^\n]读取最多99个非换行字符,%*1[\n]匹配并丢弃后面的1个换行符
        int ret = scanf("%99[^\n]%*1[\n]", list[i]);
        if (ret == EOF) { // 读到输入结束直接退出循环
            free(list[i]); // 释放提前申请的当前行内存
            break;
        }
        i++;
    }

    printf("\n");
    for (int j = 0; j < i; j++) {
        printf("Your strings by num %d: %s\n", j+1, list[j]);
        free(list[j]); // 释放单条字符串内存,避免泄漏
    }
    free(list); // 释放指针数组内存

    return 0;
}

修改说明

  • 调整scanf格式为"%99[^\n]%*1[\n]":不依赖禁用的函数/格式符即可处理残留换行,解决输入中断问题
  • 替换不可靠的while(!feof(stdin))逻辑,改为校验scanf返回值判断输入是否结束,避免无效的内存申请和输入
  • 补充内存申请失败校验和使用后的内存释放逻辑,避免内存泄漏和程序崩溃
  • 调整数组下标从0开始,符合C语言数组的常规使用习惯
  • 如果需要支持更长的单行输入,调整malloc(1000)的数值和scanf里的%99数值即可,注意要留1位空间给字符串结束符\0

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 15:24:04