如何在c++中读取非ascii字符?

3

我正在编辑一个文件夹中的文件标题。我想要删除标题中的某一部分,但是用来分隔标题的括号不是标准的ASCII字符,所以我无法找到删除它的方法。这是标题的示例:【删除这一部分】保留这一部分。我已经包含了我使用的编码。我使用一个cstring来存储标题,然后使用cstring::find()来定位这一部分,但是它无法定位到这种类型的括号。

    //sets definition
    HANDLE hfind;
    WIN32_FIND_DATA data;

    //creates string for to search for a specific file
    CString FileFormat = FolderPath + Format;
    CString NewTitle, PulledFile;

    //sets definition for retrieving first file
    hfind = FindFirstFile(FileFormat, &data);

    //runs loop if handle is good
    if (hfind != INVALID_HANDLE_VALUE)
    {
    //loops until it hits the end of the folder
    do {
        //adds filename to vector
        PulledFile = data.cFileName;
        if(PulledFile.Find(L'【') != -1)
        {
            while (PulledFile.Find(L'】') != -1)
            {
                PulledFile = PulledFile.Right(PulledFile.GetLength() - 1);
            }
        }
        NewTitle = PulledFile.Left(PulledFile.GetLength()-(Format.GetLength() + 9));
        if (sizeof(NewTitle) != NULL)
        {
            v.push_back(NewTitle);
        }
    } while (FindNextFile(hfind, &data));
    }

2
if (sizeof(NewTitle) != NULL)非常非常错误。你想用这个比较做什么? - andlabs
@IInspectable并没有读取文件本身,而是获取一个以两种格式之一返回的文件名(宽字符串或Unicode)。假设您编译正确,文件内部使用的任何编码都不会阻止您执行OP正在尝试的操作。 - meneldal
@meneldal:完全错过了那个,你是对的。除了,你可能想说“MBCS或Unicode编码”。 - IInspectable
@IInspectable MBCS 是某种邪恶的编码方式,我宁愿不去涉足。最好只是知道它的存在,如果可以的话就避免使用它。 - meneldal
@meneldal:我指的是“宽字符串或Unicode” - 这两个是同义词。 - IInspectable
显示剩余4条评论
2个回答

2

很可能您的编辑器没有正确地将硬编码的【和】转换为您所需的Unicode字符。Visual Studio有时会通过自动将源文件编码为UTF8来正确处理此问题,但这并不总是可靠的,并且可能无法在期望ASCII的源代码控制系统中生存。

最简单的方法是使用\uNNNN语法来匹配这些字符。

    if(PulledFile.Find(L'\u3010') != -1)
    {
        while (PulledFile.Find(L'\u3011') != -1)
        {
            PulledFile = PulledFile.Right(PulledFile.GetLength() - 1);
        }
    }

\u3010\u3011分别是Unicode值为【和】的十六进制转义序列。


1
一个如 \x3010 的转义符加上 4 个十六进制数字是微软的扩展,我相信。更标准的 '\u3010''\u3011' 应该也可以使用。 - dxiv
它可能仍然会失败,因为UTF-8 /宽字符比较的关系。如果您在ASCII范围之外使用字符,VS将要求您更改编码,因此我假设这不是问题所在。 - meneldal
1
@dxiv - 謝謝您。回答已經修正了。 - selbie
@meneldal - 这也是我的期望。但是,当我在VS2015中运行本地测试时,使用const wchar_t * psz = L"【Title】";作为测试字符串,Visual Studio 没有提示或自动编码源代码。它将其保留为ASCII,并将括号字符视为文字'?'(0x3f)。我必须显式将源代码保存为UTF8才能使其正常工作。因此,这是我的建议。我假设他已经构建为Unicode,因为他在代码中使用了宽字符文字'L'【' - selbie
@dxiv - 哎呀,谢谢提醒。 - selbie
谢谢你的帮助。 - Brandon Nece

2
您面临的最可能问题是编译错误。根据CString文档
- CStringW对象包含wchar_t类型并支持Unicode字符串。 - CStringA对象包含char类型并支持单字节和多字节(MBCS)字符串。 - CString对象支持char类型或wchar_t类型,具体取决于编译时是否定义了MBCS符号或UNICODE符号。
实际基础类型取决于编译参数。最可能发生的情况是它试图将Unicode字符串与您的MBCS字符串文字值进行比较,并且没有返回任何内容。
如果要解决此问题,您应该决定使用Unicode还是MBCS,并相应地更新编译参数,定义MBCS或UNICODE之一。
如果使用Unicode,则必须更改字符串文字值,因为它当前适用于MBCS。您可以使用代码点L'\u3010',它将返回正确的字符,或确保文件使用Unicode编码并使用u'【'。

一个快速检查这种情况的方法是在调试模式下运行,这样您就可以看到字符串如何转换(或不转换)以及为什么会出现这样的结果。 - meneldal
1
发布的代码必须已经编译为Unicode,因为它调用了CString::Find(L'【')。定义为L'X'的字符字面量是wchar_t类型的,并且CStringA没有接受wchar_t参数的Find重载。因此,为了让代码能够编译,CString必须是CStringW,即使用UNICODE定义的Unicode编译。 - dxiv
@dxiv 感谢您的评论,我已经更新了我的答案,现在应该没问题了。 - meneldal
感谢您的帮助。我之前不知道使用mbcs和Unicode的区别。 - Brandon Nece

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接