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

如何限制终端输入字符串长度以避免缓冲区溢出?

解决字符串输入缓冲区溢出问题

问题根源分析

你当前代码存在两个致命问题:

  1. scanf("%5s", str1)中,%5s会读取最多5个字符,再自动追加终止符\0,但str1的数组大小仅为5(MAX_STRG/2=5),直接导致数组越界溢出。正确的格式符应该是%4s,限制读取字符数为数组大小减1,预留终止符的位置。
  2. 你用sizeof(str1)+sizeof(str2)判断输入长度,这是数组的固定内存大小,和实际输入的字符串长度无关,所以这个检查完全无效。

两种可行的解决方案

方案1:改进scanf用法,实时检测输入溢出

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

#define MAX_STRG 10
#define SUB_STR_LEN (MAX_STRG/2)  // 每个子串数组大小为5

int main() {
    char str1[SUB_STR_LEN] = "One", str2[SUB_STR_LEN] = "Two";
    int check = 1;
    char leftover;

    while(check == 1) {
        // 读取第一个字符串,限制最多4个字符
        printf("请输入第一个字符串(最多4个字符)...\n");
        scanf("%4s", str1);

        // 清空输入缓冲区的剩余字符,同时判断是否有溢出
        if ((leftover = getchar()) != '\n' && leftover != EOF) {
            printf("错误:第一个字符串超出长度限制!\n");
            // 彻底清空缓冲区
            while(getchar() != '\n' && getchar() != EOF);
            continue;
        }

        // 读取第二个字符串,同样处理
        printf("请输入第二个字符串(最多4个字符)...\n");
        scanf("%4s", str2);

        if ((leftover = getchar()) != '\n' && leftover != EOF) {
            printf("错误:第二个字符串超出长度限制!\n");
            while(getchar() != '\n' && getchar() != EOF);
            continue;
        }

        // 检查总长度是否符合要求
        if(strlen(str1) + strlen(str2) <= MAX_STRG) {
            check = 0;
        } else {
            printf("错误:两个字符串总长度超过%d字符!\n", MAX_STRG);
        }
    }

    printf("\n最终输入结果:\n字符串1:%s\t字符串2:%s\n总长度:%zu\n", str1, str2, strlen(str1)+strlen(str2));
    return 0;
}

方案2:用fgets实现更安全的读取

fgets支持指定最大读取长度,会自动保留终止符,还能读取带空格的整行输入,安全性比scanf更高:

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

#define MAX_STRG 10
#define SUB_STR_LEN (MAX_STRG/2)

int main() {
    char str1[SUB_STR_LEN] = "One", str2[SUB_STR_LEN] = "Two";
    int check = 1;

    while(check == 1) {
        printf("请输入第一个字符串(最多4个字符)...\n");
        fgets(str1, SUB_STR_LEN, stdin);

        // 去掉fgets读取到的换行符(如果存在)
        str1[strcspn(str1, "\n")] = '\0';

        // 检测输入是否溢出:若读取的字符串长度等于数组大小-1,且缓冲区还有剩余字符
        if(strlen(str1) == SUB_STR_LEN - 1 && getchar() != '\n') {
            printf("错误:第一个字符串超出长度限制!\n");
            // 清空剩余字符
            while(getchar() != '\n' && getchar() != EOF);
            continue;
        }

        printf("请输入第二个字符串(最多4个字符)...\n");
        fgets(str2, SUB_STR_LEN, stdin);
        str2[strcspn(str2, "\n")] = '\0';

        if(strlen(str2) == SUB_STR_LEN - 1 && getchar() != '\n') {
            printf("错误:第二个字符串超出长度限制!\n");
            while(getchar() != '\n' && getchar() != EOF);
            continue;
        }

        if(strlen(str1) + strlen(str2) <= MAX_STRG) {
            check = 0;
        } else {
            printf("错误:两个字符串总长度超过%d字符!\n", MAX_STRG);
        }
    }

    printf("\n最终输入结果:\n字符串1:%s\t字符串2:%s\n总长度:%zu\n", str1, str2, strlen(str1)+strlen(str2));
    return 0;
}

核心注意事项

  • 用scanf时,%Ns中的N必须是数组大小-1,预留终止符\0的位置。
  • 无论用哪种读取方式,都要清空输入缓冲区的剩余字符,避免影响下一次输入。
  • 检测溢出的关键逻辑:若读取的字符串长度达到数组最大可用长度(数组大小-1),且输入缓冲区中还有未读取的非换行字符,说明输入超出限制。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 21:50:15