C++ 阻止回车出现在stringstream中

C++ 阻止回车出现在stringstream中,c++,stream,iostream,C++,Stream,Iostream,我有一些文本解析,无论是从文件还是从stringstream读取,我都希望它们的行为相同。因此,我尝试使用std::istream来执行所有工作。在字符串版本中,我试图从我创建的静态内存字节数组(最初来自文本文件)中读取它。假设原始文件如下所示: 4 std::istringstream iss(byte_array); std::istream& is = iss; 相应的字节数组如下所示: const char byte_array[] = { 52, 13, 10 }; 其中

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

4
std::istringstream iss(byte_array);
std::istream& is = iss;
相应的字节数组如下所示:

const char byte_array[] = { 52, 13, 10 };
其中52是字符4的ASCII,然后是回车符,然后是换行符

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

当我尝试以“字符串模式”阅读时,如下所示:

4
std::istringstream iss(byte_array);
std::istream& is = iss;
最后,我使用以下方法从stringstream检索到的字符串的末尾卡住了回车符:

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


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

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

std::istringstream
不对源字符串进行任何解释,而是像字符串中的字节一样传递所有字节

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

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


另一种方法是编写一个流包装器,它接受
std::istream
并将读取操作委托给它,动态地转换行结尾。这种方法是可行的,但要想正确使用可能会很棘手。(有效地处理搜索尤其困难。)

我的猜测是,
ifstream
在文本模式下打开文件时会删除CR字符,但是
istringstream
没有“文本模式”的概念,因此总是在二进制模式下有效运行。(试着用mode
ios_base::binary
打开文件,看看文件是否出现问题。)我认为解决方案是从
byte_数组中删除“13”元素。这是一个很好的备份解决方案,需要做一些工作,但可能会治愈症状。我觉得有点奇怪,istringstream不会在“文本模式”下运行!这是给弦的@aardvarkk:
文本模式
仅与文件流相关。当您从文件读写时,行尾总是为您翻译的,因此在代码中您只需处理
\n
。使用StrugScript,它应该是相同的。@ C++中的AdvARKK字符串是事物的序列,而不一定是文本的字符。例如,code>std::string
是一个字节序列——如何解释这些字节取决于类的使用者<代码>istringstream不执行任何解释或特殊处理。在这种情况下,解释/处理应该发生在您读取文件时,即代码生成之前。我的解决方案符合您的建议。因为我可以控制二进制数据的写入过程,所以我只是阻止它在输出端写入回车。之后不需要在输入端进行检查。