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

C语言设置UTF-8代码页后scanf读取特殊字符字符串截断问题

问题根因

字符串截断和SetConsoleCP/SetConsoleOutputCP的UTF-8编码配置无关,核心是代码存在两处内存定义与访问的错误:

  • 结构体字段定义错误:char* prod[50] 声明的是长度为50的char指针数组,不是用来存储字符内容的字符数组。32位编译环境下每个指针占4字节,写入UTF-8编码的Açucar时,'A'占1字节、'ç'占2字节,3个字节写满第一个指针的前3字节空间后,第4字节的内存默认值为0x00,被printf识别为字符串终止符,因此输出到'A'就截断。
  • scanf用法错误:对数组名取地址&lojas[x].prod属于类型不匹配的未定义行为;%[^\n]本身就是完整的字符串匹配规则,后面额外加的s是无效写法;同时没有给字符串读取设置长度上限,存在缓冲区溢出风险。

移除UTF-8编码配置后看似读取正常,只是因为系统默认ANSI编码下'ç'只占1字节,暂时没触发内存里的0值截断,属于未定义行为的偶然表现,本质问题没有修复。

修复方案

按以下步骤修改代码即可同时解决截断和乱码问题,不需要依赖<locale.h>,在Embarcadero Dev-C++环境下可直接运行:

  1. 修正结构体的商品名字段,改为定长字符数组,预留足够空间存储UTF-8多字节字符
  2. 修正scanf的传参、格式符,增加字符串读取长度限制避免溢出
  3. 控制台输出前增加缓冲区刷新,避免UTF-8模式下提示语显示异常

修复后的完整代码:

#define NOMINMAX
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>

typedef struct
{
    float preco;
    int quant;
    char prod[100]; // 修正:定长字符数组,预留100字节存商品名
} info;

void imprime(info j)
{
    printf("||  Produto: %s  ||  preço: %.2f  ||  quantidade: %d  ||\n", j.prod, j.preco, j.quant);
}

int main()
{
    SetConsoleCP(CP_UTF8);
    SetConsoleOutputCP(CP_UTF8);
    system("color 0F");
            
    info lojas[50];
    
    for (int x = 0; x < 1; x++)
    {
        printf("Digite o nome do produto: ");
        fflush(stdout); // 刷新输出缓冲区,保证提示语正常显示
        scanf(" %99[^\n]", lojas[x].prod); // 限制最长读取99字符,避免溢出,去掉多余的&和s
        printf("\nDigite o preço do produto: ");
        fflush(stdout);
        scanf(" %f", &lojas[x].preco);
        printf("\nDigite a quantidade desejada do produto: ");
        fflush(stdout);
        scanf(" %d", &lojas[x].quant);
        system("cls");
    }
    
    for (int x = 0; x < 1; x++)
    {
        imprime(lojas[x]);
    }   
    return 0;
}
验证说明
  • 输入Açucar时,UTF-8编码的多字节字符会完整写入字符数组,不会出现截断,控制台可正常输出带特殊字符的内容,无乱码
  • 代码增加了字符串读取长度限制,避免用户输入过长内容导致的内存越界问题

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 01:42:17