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

C语言中scanf将带重音字母计为2字符的问题解决方法

问题解决:scanf限制UTF-8字符数而非字节数

问题根源

scanf("%20s")中的20是字节数限制,而非Unicode字符数。像é这类UTF-8编码的字符占2个字节,所以20字节只能容纳10个é,导致输出时后半部分丢失。

解决方案

方案1:使用宽字符版scanf(优先满足你的scanf使用需求)

改用wchar_t类型存储字符串,配合wscanf的%20ls格式符,此时宽度限制的是宽字符数(即Unicode字符数),直接实现20个字符的限制。

代码示例:

#include <wchar.h>
#include <stdio.h>

int main() {
    wchar_t name[21]; // 20个宽字符 + 终止符
    int num1, hour, minute;
    char flag;

    // 适配你的格式判断逻辑
    if (wscanf(L"%d %20ls %d:%d %hc", &num1, name, &hour, &minute, &flag) == 5) {
        wprintf(L"输入的名称:%ls\n", name);
        // 其他处理逻辑
    }
    return 0;
}
  • 注意:%hc用于在wscanf中读取普通char类型的字符(对应你格式中的最后一个%c),若需读取宽字符则用%lc。
  • 确保终端编码为UTF-8,且编译环境支持宽字符(现代编译器默认支持)。

方案2:用窄字符数组,读取后截断为20个UTF-8字符

如果必须使用char数组,先读取足够多的字节(比如80字节,覆盖20个最多4字节的UTF-8字符),再手动截断到20个合法的UTF-8字符,避免截断到字符中间导致乱码。

实现代码:

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

// 将UTF-8字符串截断为max_chars个字符
void truncate_utf8(char *dest, const char *src, size_t max_chars) {
    size_t char_count = 0;
    while (*src != '\0' && char_count < max_chars) {
        if ((*src & 0x80) == 0) {
            // 单字节ASCII字符
            *dest++ = *src++;
            char_count++;
        } else if ((*src & 0xE0) == 0xC0) {
            // 双字节UTF-8字符
            if (char_count + 1 > max_chars) break;
            *dest++ = *src++;
            *dest++ = *src++;
            char_count++;
        } else if ((*src & 0xF0) == 0xE0) {
            // 三字节UTF-8字符
            if (char_count + 1 > max_chars) break;
            *dest++ = *src++;
            *dest++ = *src++;
            *dest++ = *src++;
            char_count++;
        } else if ((*src & 0xF8) == 0xF0) {
            // 四字节UTF-8字符
            if (char_count + 1 > max_chars) break;
            *dest++ = *src++;
            *dest++ = *src++;
            *dest++ = *src++;
            *dest++ = *src++;
            char_count++;
        } else {
            // 无效UTF-8字节,跳过
            src++;
        }
    }
    *dest = '\0'; // 添加字符串终止符
}

int main() {
    char temp_name[81]; // 足够容纳20个UTF-8字符
    char name[21];
    int num1, hour, minute;
    char flag;

    // 原格式判断,仅加宽name的读取字节数
    if (scanf("%d %80s %d:%d %c", &num1, temp_name, &hour, &minute, &flag) == 5) {
        truncate_utf8(name, temp_name, 20);
        printf("输入的名称:%s\n", name);
        // 其他处理逻辑
    }
    return 0;
}

关键说明

  • 方案1更简洁,直接利用宽字符特性解决计数问题,适合大多数现代环境。
  • 方案2需手动处理UTF-8编码细节,兼容性更强,适合无法使用宽字符的场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 05:01:40