如何在 c++ 中读取不包含在 ascii 中的字符?
Posted
技术标签:
【中文标题】如何在 c++ 中读取不包含在 ascii 中的字符?【英文标题】:How to read a character not included in ascii in c++? 【发布时间】:2015-12-21 02:13:54 【问题描述】:我正在浏览一个包含编辑标题的文件的文件夹。我正在尝试删除标题的某个部分,但用于分隔标题的括号不是标准的 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));
【问题讨论】:
if (sizeof(NewTitle) != NULL)
非常非常错误。你想用这个比较做什么?
应该是NewTitle.GetLength()
而不是sizeof(NewTitle)
这部分没有任何意义:NewTitle = PulledFile.Left(PulledFile.GetLength() - (Format.GetLength() + 9));
它将NewTitle
设置为NUL。这不是 Unicode 问题。
@IInspectable 他不是在读取文件本身,而是在获取以两种格式(宽字符串或 Unicode)之一返回的文件名。假设您编译正确,文件内部使用的任何编码都不会阻止您执行 OP 尝试执行的操作。
@meneldal:完全错过了,你是对的。除了,您可能想说“MBCS 或 Unicode 编码”。
@IInspectable MBCS 是某种邪恶,无论如何我都不想涉足。最好只知道它存在并尽可能避免它。
【参考方案1】:
您面临的最有可能的问题是编译不正确。根据CString documentation:
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'【'
。
【讨论】:
发布的代码必须已经为 Unicode 编译,因为它调用CString::Find(L'【')
。定义为L'X'
的字符文字属于wchar_t
类型,并且CStringA 没有采用wchar_t
参数的Find
重载。因此,为了使代码完全编译,CString 必须是 CStringW,即定义了 UNICODE 的 Unicode 编译。
@dxiv 感谢您的评论我已经更新了我的答案,现在应该很好了。
感谢您的帮助。我不知道使用 mbcs 和 Unicode 的区别。【参考方案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值的十六进制转义序列。
【讨论】:
我相信像\x3010
这样带有 4 十六进制数字的转义是 MS 扩展。更标准的'\u3010'
、'\u3011'
应该也可以。
它可能仍然会因为 UTF-8/宽字符比较而失败。如果您使用 ASCII 以外的字符,VS 会要求您更改编码,所以我认为这不是问题。
@dxiv - 谢谢。答案固定。
@meneldal - 这是我的期望。但是当我在 VS2015 中使用 const wchar_t* psz = L"【Title】";
作为测试字符串运行本地测试时,Visual Studio 没有 提示或自动编码源。它将它保留为 ascii 并将括号字符视为文字 '?'
(0x3f)。我必须明确将源代码保存为 UTF8 才能使其正常工作。因此,我的建议。我以为他已经在构建 Unicode,因为他在代码中使用了宽字符文字 L'【'
@dxiv - 哎呀。谢谢。以上是关于如何在 c++ 中读取不包含在 ascii 中的字符?的主要内容,如果未能解决你的问题,请参考以下文章
将十六进制转换为从文件 C++ 读取的 ASCII 的正确方法