为什么我不能使用 ifstream 读取撇号而不会崩溃?

Why can't I read apostrophes using ifstream without it crashing?

本文关键字:崩溃 读取 不能 ifstream 为什么      更新时间:2023-10-16

我正在使用此代码:

std::string word;
std::ifstream f((file_name + ".txt").c_str());
while (f >> word) {
    good_input = true;
    for (int i = 0; i < word.length(); ++i) {
        if (ispunct(word.at(i))) {
            word.erase(i--, 1);
        }
        else if (isupper(word.at(i))){
            word.at(i) = tolower(word.at(i));
        }
    }

每当我从文本文件中读取"不"一词时,我会收到此错误:

调试断言失败了!
程序: Directory sortingwords(length).exe
文件:minkernel crts ucrt src appcrt convert istype.cpp
线:36
表达式:c> = -1&amp;&amp;c&lt; = 255
有关更多信息,请访问... [等]

当我单击"流产"时,我的程序将带有代码3。不知道这是否有帮助?

看起来可能与撇号有关吗?此代码可在我的文档中找到所有其他单词,直到此编码为止。并且在不包括撇号的文档中效果很好,但其中包括许多其他标点符号...

我尝试更改文本文件的编码(简单地用记事本),但这无济于事。通常发现很多关于撇号的抱怨,但没有工作答案。谁能帮我弄清楚发生了什么事?

作为ispunct的文档说:

如果CH的值不可用,则行为是不确定的 unsigned char,不等于EOF

Visual C 足够好,可以链接到调试运行时,以添加此错误的几乎明确消息(通常使用不确定的行为,这种情况通常是这种情况 - 随着发行时间的发行时间,它只是崩溃或表现出奇怪的;在调试运行时;,您将获得一个错误对话框)。

从理论上讲,这意味着在您的环境使用的字符集中,'不能表示为unsigned char,即其字符代码太大或太低。

实际上,这似乎不太可能,甚至在窗户上甚至不可能。您的文件更有可能真正包含撇号,而是一个像一个看起来像一个的字符,例如口音:´

这是您可以简单地重现问题的方法:

#include <ctype.h>
int main()
{
    ispunct(''');
    ispunct('´'); // undefined behaviour (crash or error message with Visual C++)
}

isupper有相同的问题。

您可以使用static_cast安全地使用这些功能,例如:

if (ispunct(static_cast<unsigned char>(word.at(i))))

当然,现在ispunct将返回该字符的零。如果您确实需要覆盖´,则必须明确地进行此操作,例如使用类似的辅助功能:

bool extended_ispunct(int c)
{
    return static_cast<unsigned char>(c) || c == '´';
}