在 Unicode 到 ASCII 转换后声明 std::string 会出现分段错误

Declaring a std::string after Unicode to ASCII conversion is giving Segmentation fault

我正在尝试从 stdin 获取一个 wchar_t 字符串,然后通过函数将其从 unicode 转换为 ASCII。

该函数以某种方式不允许我在程序中进一步使用 std::string。

#include <iostream>
#include <string>
#include <locale>
#include <cstring>
#include <cwchar>
using namespace std;
bool UnicodeToAscii(wchar_t* szUnicode, char* szAscii);
int main()
{
    wchar_t w[100];
    wcin>>w;
    char* c;
    bool x=UnicodeToAscii(w,c);
    cout<<c<<"\n";
    string s="hi";
    return 0;
}
bool UnicodeToAscii(wchar_t* szUnicode, char* szAscii)
{
    int len, i;
    if((szUnicode == NULL) || (szAscii == NULL))
        return false;
    len = wcslen(szUnicode);
    for(i=0;i<len+1;i++)
        *szAscii++ = static_cast<char>(*szUnicode++);
    return true;
}
  • 在写入无效指针之前,您永远不会为 c 分配内存。
  • cin >> 到固定大小的数组是不安全的。您可以考虑 std::wstring.
  • 如果要将 16 位字符转换为 8 位字符,请在 8 位字符串中使用 UTF-8 编码,而不是 ASCII。如果你必须使用 ASCII,如果任何字符超出范围,你将不得不出错,或者用占位符替换它。但是,这会使您得不到国际支持。您应该能够轻松找到有关在 C++ 中将 UTF-16 转换为 UTF-8 的信息。

您没有为 c 分配任何内存,因此您正在将字符数据写入随机内存并破坏您的程序。

您应该停止使用字符数组和原始指针,而开始使用 std::stringstd::wstring。让他们为您管理内存。

试试这个:

#include <iostream>
#include <string>

void UnicodeToAscii(const std::wstring &szUnicode, std::string &szAscii);

int main()
{
    std::wstring w;
    std::wcin >> w; // or std::getline(wcin, w);

    std::string c;
    bool x = UnicodeToAscii(w, c);
    std::cout << c << "\n";

    std::string s = "hi";
    return 0;
}

void UnicodeToAscii(const std::wstring &szUnicode, std::string &szAscii)
{
    szAscii.clear(len);

    int len = szUnicode.length();
    char c;

    szAscii.reserve(len);

    for(int i = 0; i < len; ++i)
    {
        wchar_t w = szUnicode[i];

        if ((w >= 0) && (w < 127))
        {
            // ASCII character
            c = static_cast<char>(w);
        }
        else
        {
            // non-ASCII character
            c = '?';

            // wchar_t is 2 bytes (UTF-16) on some systems,
            // but is 4 bytes (UTF-32) on other systems...
            #if sizeof(wchar_t) == 2
            if ((w >= 0xD800) && (w <= 0xDFFF))
            {
                // skip first unit of a surrogate pair,
                // the loop will skip the second unit...
                ++i;
            }
            #endif
        }

        szAscii.push_back(c);
    }

    return true;
}

当然,这是非常初级的,它只处理真正的 ASCII 字符 (0x00 - 0x7F)。正确处理 Unicode 比这复杂得多。但这回答了您关于为什么在调用函数后不能使用 std::string 的直接问题 - 因为您正在浪费内存。