【问题标题】:C++ cin fails when reading more than 127 ASCII values读取超过 127 个 ASCII 值时,C++ cin 失败
【发布时间】:2013-02-21 17:46:53
【问题描述】:

我创建了一个包含 256 个字符的文本文件,文本文件的第一个字符是 ASCII 值 0,文本值的最后一个字符是 ASCII 值 255。介于 0 到 255 之间的字符均匀地递增。所以字符 #27 是 ASCII 值 27。字符 #148 应该是 ASCII 值 148。

我的目标是读取这个文本文件的每个字符。

我试过用cin 阅读这篇文章。我尝试了cin.get()cin.read(),它们都应该读取未格式化的输入。 但是在读取第 26 个字符时都失败了。 我想当我使用 unsigned char 时,cin 说它正在读取 255,这根本不是真的。当我使用普通签名的char 时,cin 说它正在阅读-1。它应该读取与 ASCII 26 等效的任何字符。也许cin 认为它被击中了EOF?但是我之前在单独的 StackOverflow 帖子上读过 EOF 不是一个可以写的实际字符。所以我不知道为什么cin 对代表整数-1 或整数255 的字符值咳嗽。有人可以告诉我我做错了什么,为什么,最好的解决方案是什么,为什么?

没有太多要粘贴的具体代码。我尝试了一些不同的非工作组合,所有这些组合都涉及cin.get()cin.read()charunsigned char,并在两者之间调用转换为charint。我没有运气能够阅读超过第 26 个字符,除了这个:

unsigned char character;

while ( (character = (unsigned char)cin.get()) != EOF) { ... }

有趣的是,虽然这不会在第 26 个字符处停止我的 while 循环,但它也不会继续前进。看起来像cin,无论它的cin.get() 还是cin.read() 在它检测到它不喜欢的东西时都拒绝前进到下一个字符。我也知道存在类似cin.ignore() 的东西,但我的输入是不可预测的;也就是说,我的文本文件的这 256 个字符只是一个测试用例,真正的输入是相当随机的。这是更大的家庭作业的一部分,但这个特定的问题与作业无关;我只是卡在部分过程中。

注意:我是从标准输入流中读取的,而不是特定的文本文件。似乎仍然没有直接的解决方案。我不敢相信以前在cin 上没有这样做过。

更新:

在 Windows 上,它在字符 26 之后停止可能是由于 Ctrl-Z 的原因。我不太关心这个问题。它只需要在 Linux 上运行。

不过,在 Linux 上,它会读取 0 到 127 的所有字符。但它似乎不会读取 127 到 255 的扩展 ASCII 字符。有一个“解决方案”程序可以产生我们应该模仿的输出,并且该程序能够以某种方式读取所有 255 个字符。

问题:如何使用 cin 读取所有 255 个 ASCII 字符?

已解决

使用:

int characterInt;
unsigned char character;

while ( (characterInt = getchar()) != EOF )
{
            // 'character' now stores values from 0 - 255
    character = (unsigned char)(characterInt);
}

【问题讨论】:

  • ASCII 从 0 到 127。字节值 128 到 255 不是 ASCII,尽管有大量(现在)糟糕的编码从 ASCII 中获取 0-127 和 ursup 128-255他们自己的邪恶目的。
  • @delnan 你为什么说糟糕? ISO 8859 编码在欧洲几乎是普遍的,甚至现在也很普遍。 (我倾向于使用 UTF-8,但在法国和德国仍有很多网站使用 ISO 8859-1 或 ISO 8859-15。请记住,isalpha 之类的内容不适用于 UTF-8。)
  • @JamesKanze 我现在说太糟糕了,因为与 Unicode 编码不同,您实际上不能使用其中之一在任何单个字符串中表达大量字符,因为它们彼此不兼容,而且这是不可能的可靠地区分它们。我很清楚其中一些很受欢迎(我住在德国),但这并没有让它们变得更好,只会让它们变得陈旧。我也知道它们在创建时是一个有点合理的解决方案。但一到二十年以来,它们只是编码事故和痛苦的根源,不如 UTF-8。
  • 即使有所有这些 Ctrl-Z 或 text-mode-not-binary-mode 问题,为什么 read()get() 会失败?
  • 可能是因为您错误地使用了get()。正确用法是:int character; while ( (character = cin.get()) != EOF) { ... }

标签: c++ character-encoding cin


【解决方案1】:

我想你是在 Windows 上。在 Windows 平台上,字符 26 是 ctrl-z,它在控制台中用于表示文件结尾,因此 iostreams 认为您的文件以该字符结尾。

它只能在 cin 使用的文本模式下执行此操作,如果您以二进制模式打开 Steam 则不会执行此操作。

【讨论】:

  • 我在 Windows 上编写代码,虽然程序要在 Linux/Unix 上运行。
  • @Jason 您会发现它在 Linux 上的工作方式有所不同,因为运行时库不使用此约定。
  • 是的,我刚刚运行了一个差异,但输出仍然不理想,但它似乎正在读取更多字符。我将不得不花更多的时间在细节上尝试解决它。​​
【解决方案2】:

std::cin 读取文本流,而不是任意二进制数据。

至于为什么第 26 个字符很有趣,您可能正在使用 CP/M 衍生产品(例如 MS-DOS 或 MS-Windows)。在那些操作系统中,Control-Z 用作文本文件中的 EOF 字符。


编辑: 在 Linux 上,使用 g++ 4.4.3,以下程序的行为完全符合预期,打印数字 0 到 255,包括 0 到 255:
#include <iostream>
#include <iomanip>

int main () {
  int ch;
  while( (ch=std::cin.get()) != std::istream::traits_type::eof() )
    std::cout << ch << " ";
  std::cout << "\n";
}

【讨论】:

  • 这适用于标准输入流吗?我并没有真正阅读特定的文本文件。
  • 这可能会有所帮助:stackoverflow.com/questions/7587595/…
  • 如果文件以二进制模式打开,您应该能够读取任何内容。但是一旦打开文件就无法更改模式,std::cin 是由运行时打开的,而不是由您打开的。
  • @Rob,根据那个链接,一些发帖人说没有解决办法。一位海报的“解决方案”看起来很混乱,似乎使用了新的 C++ 功能?另一个“解决方案”是特定于 Windows 的平台。我想要的只是能够阅读我所有的性格价值观并快乐......
【解决方案3】:

这里有两个问题。首先是在 Windows 中cin 的默认模式是文本而不是二进制,导致某些字符被解释而不是输入到程序中。特别是第 26 个字符 Ctrl-Z 被解释为文件结尾,因为向后兼容性达到了极致。

另一个问题是由于cin &gt;&gt; 的工作方式 - 它跳过了空格。这显然包括空格,还包括制表符、换行符等。要从cin 读取每个字符,您需要使用cin.get()cin.read()

【讨论】:

  • 我正在使用cin.get()cin.read()。此外,在 Unix 上,它最多可以读取 127 个字符,但不会更多。对此有何见解?
  • @Jason,使用od -b 确保文件包含您认为的字符。我手头没有可供评估的 Unix 或 Linux 系统,但我确实在 Windows 上使用 Cygwin 对其进行了测试,并且它工作正常。如果有帮助,我可以将代码编辑到答案中。
猜你喜欢
  • 2021-06-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-01-08
  • 1970-01-01
  • 2019-03-07
  • 2011-12-02
  • 2017-10-29
相关资源
最近更新 更多