【问题标题】:Reading cyrillic from Console C++从控制台 C++ 读取西里尔字母
【发布时间】:2016-11-03 17:30:55
【问题描述】:

我正在尝试从控制台读取西里尔字母(“Иванчо говори само глупости”),但我得到的只是“??????”。我第一次用 C++ 编写,如果有人帮助我解决这个问题,我将非常感激。

这是我的代码

#include<iostream>
#include<string>
#include<map>
#include<Windows.h>
#include<clocale>

using namespace std;

bool CheckLetters(int letter)
{
    SetConsoleCP(1251);
    SetConsoleOutputCP(1251);

    bool isCyrillic = ('\u0410' <= letter && letter <= '\u044f');
    if ((letter >= 'a' && letter <= 'z')
        || (letter >= 'A' && letter <= 'Z')
        || isCyrillic)
    {
        return true;
    }
    return false;
}

int main()
{
    string input;
    map<unsigned char, int> letters;

    getline(cin, input);

    for (int i = 0; i < input.size(); i++)
    {
        unsigned char currentLetter = input[i];
        if (CheckLetters(currentLetter))
        {
            map<unsigned char, int>::iterator elementIter = letters.find(currentLetter);
            if (elementIter == letters.end())
            {
                letters[currentLetter] = 1;
            }
            else
            {
                letters[currentLetter] ++;
            }
        }

    }

    for (map<unsigned char, int>::iterator current = letters.begin();
         current != letters.end(); current++)
    {
        pair<unsigned char, int> currentElement = *current;
        cout << currentElement.first << " " << currentElement.second <<endl;
    }

    return 0;
}

【问题讨论】:

  • 你试过wchar_t而不是char吗?
  • 不,我会尝试:)
  • 不,不适用于 wchar_t
  • 当然,您还必须使用w 版本作为std::wcin、'std::wsting' 等。

标签: c++


【解决方案1】:

建议使用 Unicode,而不是将代码页更改为俄语或任何特定语言。 Windows API 使用 UTF16,不幸的是 Windows 控制台对 Unicode 的支持有限。这是一个特定于 Windows 控制台和 Visual Studio 的解决方案(例如,它不适用于 MinGW)。它仍然不适用于某些亚洲语言(或者至少我不知道如何使它工作)

#include <iostream>
#include <string>
#include <io.h> //for _setmode
#include <fcntl.h> //for _O_U16TEXT

int main() 
{
    _setmode(_fileno(stdout), _O_U16TEXT);
    _setmode(_fileno(stdin), _O_U16TEXT);
    std::wcout << L"ελληνικά Иванчо English\n";

    std::wstring str;
    std::wcin >> str;
    std::wcout << "output: " << str << "\n";

    return 0;
}

请注意,将模式更改为 UTF16 后,您将无法使用 std::cinstd::cout。如果您想继续使用 ANSI 输入/输出,则必须将模式设置回 _O_TEXT。示例:

_setmode(_fileno(stdout), _O_TEXT);
_setmode(_fileno(stdin), _O_TEXT);
std::cout << "Test\n";

在接收到 UTF16 的输入后,您可能需要使用 WideCharToMultiByte(CP_UTF8, ...) 转换为 UTF8(存储在 char 中)以兼容网络功能等。

【讨论】:

    【解决方案2】:

    这个组合怎么样?

    setlocale(LC_ALL, "Russian");
    SetConsoleOutputCP(866);
    

    【讨论】:

    • 这不是标准的 c++。
    • @πάνταῥεῖ 这是从控制台读取文本。我认为(不是 100% 肯定)标准 C++ 中没有“控制台”或“终端”的概念。据我所知,无论何种解决方案都必须至少取决于平台特定的行为。
    【解决方案3】:

    我的主要问题是,我一开始没有在 VS 中设置编码。因此,我创建了新项目并将代码页设置为 1251。这是我的代码:

    #include<iostream>
    #include<string.h>
    #include<map>
    #include<windows.h>
    #include<locale>
    
    using namespace std;
    
    bool CheckLetters(wchar_t letter)
    {
        bool isCyrillic = 65472 <= letter && letter <= 65535;
        if ((letter >= 'a' && letter <= 'z')
            || (letter >= 'A' && letter <= 'Z')
            || isCyrillic)
        {
            return true;
        }
        return false;
    }
    
    
    int main()
    {
    
        SetConsoleCP(1251);
        SetConsoleOutputCP(1251);
    
        wstring input;
        map<wchar_t, int> letters;
    
        getline(wcin, input);
    
        for (int i = 0; i < input.size(); i++)
        {
            char currentLetter = input[i];
    
            if (CheckLetters(currentLetter))
            {
                map<wchar_t, int>::iterator elementIter = letters.find(currentLetter);
                if (elementIter == letters.end())
                {
                    letters[currentLetter] = 1;
                }
                else
                {
                    letters[currentLetter] ++;
                }
            }
    
        }
    
        for (map<wchar_t, int>::iterator current = letters.begin();
            current != letters.end(); current++)
        {
            pair<wchar_t, int> currentElement = *current;
            cout << (char)(currentElement.first) << " = " << currentElement.second << endl;
        }
    
        return 0;
    }
    

    感谢所有给我建议的人。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-10-27
      • 1970-01-01
      • 2021-06-10
      • 1970-01-01
      • 2019-06-13
      • 1970-01-01
      相关资源
      最近更新 更多