【问题标题】:Stop carriage return from appearing in stringstream阻止回车出现在字符串流中
【发布时间】:2013-08-14 06:41:33
【问题描述】:

我有一些文本解析,无论是从文件还是从字符串流中读取,我都希望其行为相同。因此,我正在尝试使用std::istream 来执行所有工作。在字符串版本中,我试图让它从我创建的静态内存字节数组(最初来自文本文件)中读取。假设原始文件如下所示:

4

对应的字节数组是这样的:

const char byte_array[] = { 52, 13, 10 };

其中 52 是字符 4 的 ASCII,然后是回车,然后是换行。

当我直接从文件中读取时,解析工作正常。

当我尝试像这样以“字符串模式”阅读它时:

std::istringstream iss(byte_array);
std::istream& is = iss;

我最终将回车卡在使用此方法从字符串流中检索到的字符串的末尾:

std::string line;
std::getline(is, line);

这搞砸了我的解析,因为string.empty() 方法不再在“空白”行上被触发——每行至少包含一个13 用于回车,即使它在生成二进制文件的原始文件中是空的数据。

为什么ifstream 在这方面的行为与istringstream 不同?如何让istringstream 版本像ifstream 版本一样丢弃回车?

【问题讨论】:

  • 我的猜测是ifstream 在以文本模式打开文件时会删除 CR 字符,但istringstream 没有“文本模式”的概念,因此始终以二进制模式有效运行。 (尝试以ios_base::binary 模式打开文件,然后查看文件是否出现问题。)我认为解决方案是从byte_array 中删除“13”元素。
  • 这是我考虑过的一件事——从我的二进制生成中删除 CR。这是一个很好的备份解决方案,需要一些工作,但可能会治愈症状。对我来说,istingstream not 在“文本模式”下运行似乎有点奇怪!这是字符串!
  • @aardvarkk: text mode 仅与文件流相关。当您从文件读取和写入时,总是会为您翻译行尾,因此在代码中您应该只需要处理\n。使用字符串流,应该是一样的。
  • @aardvarkk C++ 中的字符串是事物的序列,不一定是文本字符。例如,std::string 是一个字节序列——如何解释这些字节取决于类的使用者。 istringstream 不做任何解释或特殊处理。在这种情况下,解释/处理应该发生在您读取文件时,即代码生成之前。

标签: c++ stream iostream


【解决方案1】:

std::ifstream 默认以文本模式运行,这意味着它将非 LF 行尾转换为单个 LF。在这种情况下,std::ifstreamstd::getline() 看到之前删除了 CR 字符。

std::istringstream 不对源字符串做任何解释,并传递字符串中的所有字节。

请务必注意,std::string 表示 字节 的序列,而不是字符。通常使用std::string 来存储ASCII 编码的文本,但它们也可以用于存储任意二进制数据。假设是,如果您已将文件中的文本读入内存,则您已经完成了任何文本转换,例如行尾标准化。

正确的做法是在读取文件时转换行尾。在这种情况下,看起来您正在从文件生成代码。读取文件并将其转换为代码的程序应该消除 CR 字符。

另一种方法是编写一个流包装器,它接受std::istream 并将读取操作委托给它,即时转换行尾。这种方法是可行的,但可能很难做到正确。 (尤其是有效地处理搜索将很困难。)

【讨论】:

  • 我的解决方案符合您的建议。由于我可以控制二进制数据的写入过程,我只是阻止它在输出端写入回车。之后输入端不需要检查。
猜你喜欢
  • 1970-01-01
  • 2013-02-14
  • 2011-08-28
  • 1970-01-01
  • 2011-03-04
  • 1970-01-01
  • 2023-03-11
  • 2011-06-21
  • 2015-12-09
相关资源
最近更新 更多