You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何在C语言中使用含俄文字母的数组?解决俄语元音统计代码的编译报错问题

解决俄语元音统计的窄化转换错误

嘿,我来帮你搞定这个问题!那个「narrowing conversion of '53429' from 'int' to 'char' inside { }」的错误,核心原因是俄语西里尔字母的编码值超出了默认有符号char的范围,再加上你用的gets函数本身已经被废弃,咱们一步步来修正:

错误根源分析

  1. 字符编码与char的局限:默认情况下,char是8位有符号类型,取值范围是-128~127。而俄语元音(比如АЁ)在常见编码里的数值都超过了这个范围:
    • 如果是UTF-8编码,俄语字符是多字节(比如А0xD0 0x90两个字节),用单字节char数组根本没法正确存储单个字符;
    • 如果是单字节编码(比如CP1251),А的数值是192,转换成有符号char会变成负数,编译器在初始化数组时会把这个数值当成int类型,再转成char就触发了「窄化转换」的错误提示。
  2. gets函数的安全问题gets已经被C11标准彻底废弃,它不会检查输入长度,很容易导致缓冲区溢出,引发程序崩溃甚至安全漏洞。

修复方案:使用宽字符处理俄语

最通用、移植性最好的方法是用宽字符类型wchar_t,它能容纳Unicode码点,完美支持俄语等非ASCII字符。下面是修改后的代码:

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

int main() {
    // 设置区域为俄语UTF-8,确保宽字符输入输出正常
    setlocale(LC_ALL, "ru_RU.UTF-8");

    wchar_t stroka[100];
    // 俄语元音的宽字符版本(包含大小写)
    wchar_t glasnii[] = {L'А', L'Е', L'И', L'Ю', L'Ё', L'Ы', L'У', L'Э', L'О', L'Я',
                         L'а', L'е', L'и', L'ю', L'ё', L'ы', L'у', L'э', L'о', L'я'};
    int count = 0;

    wprintf(L"Введите строку: ");
    // 用fgetws代替gets,安全读取宽字符字符串
    fgetws(stroka, sizeof(stroka)/sizeof(wchar_t), stdin);

    // 去掉fgetws读取的换行符
    size_t len = wcslen(stroka);
    if (len > 0 && stroka[len-1] == L'\n') {
        stroka[len-1] = L'\0';
        len--;
    }

    // 双重循环统计元音
    for (int i = 0; i < len; i++) {
        for (int j = 0; j < sizeof(glasnii)/sizeof(wchar_t); j++) {
            if (stroka[i] == glasnii[j]) {
                count++;
                break; // 找到匹配就跳出内层循环,优化效率
            }
        }
    }

    wprintf(L"\nКоличество гласных: %d\n", count);
    return 0;
}

关键改动说明

  • wchar_t类型:替换charwchar_t,用来存储宽字符,每个俄语元音都是单个wchar_t值;
  • 宽字符函数:用wprintffgetwswcslen代替对应的单字节函数,确保宽字符的输入输出和长度计算正确;
  • 区域设置:添加setlocale(LC_ALL, "ru_RU.UTF-8"),让系统识别俄语UTF-8编码,否则宽字符可能显示乱码;
  • 安全输入:用fgetws代替gets,指定最大读取长度,避免缓冲区溢出;
  • 优化内层循环:找到匹配的元音后用break跳出,减少不必要的比对。

备选方案:用无符号单字节字符(仅适用于单字节编码环境)

如果你坚持用单字节char,可以把数组声明为unsigned char(取值范围0~255),这样就能容纳CP1251等单字节编码的俄语字符,避免窄化转换错误。但这种方法依赖系统默认编码为单字节俄语编码,移植性差,不推荐:

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

int main() {
    unsigned char stroka[100];
    unsigned char glasnii[] = {'А', 'Е', 'И', 'Ю','Ё','Ы','У','Э','О','Я','а','у', 'о', 'ы', 'и', 'э', 'я', 'ю', 'ё','е'};
    int count = 0;

    printf("Введите строку: ");
    // 用fgets代替gets,安全读取
    fgets((char*)stroka, sizeof(stroka), stdin);

    size_t len = strlen((char*)stroka);
    if (len > 0 && stroka[len-1] == '\n') {
        stroka[len-1] = '\0';
        len--;
    }

    for (int i = 0; i < len; i++) {
        for (int j = 0; j < sizeof(glasnii)/sizeof(unsigned char); j++) {
            if (stroka[i] == glasnii[j]) {
                count++;
                break;
            }
        }
    }

    printf("\nКоличество гласных: %d\n", count);
    return 0;
}

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

火山引擎 最新活动