当它们进入`std :: stringstream`时,我可以去除回车吗? [英] Can I strip carriage returns as they go into a `std::stringstream`?
问题描述
struct T
{
void eat(std::string const& segment)
{
buffer << segment;
std::string sentence;
while (std::getline(buffer, sentence))
std::cout << "[" << sentence.size() << "]";
}
std::stringstream buffer;
};
int main() {
T t;
t.eat("A\r\nB\nC\nD");
// ^^ ^ ^ ^
}
// Actual output: [2][1][1][1]
// Desired output: [1][1][1][1]
我希望std::stringstream
为我剥离回车符(并且希望不必复制和修改segment
).
I would like the std::stringstream
to strip that carriage return for me (and would prefer not to have to copy and modify segment
).
我该怎么办?我本以为在文本模式下,在Linux上,无论如何都会发生这种情况……但是,也许这种机制符合 file 流的逻辑.
How might I go about this? I would have thought that this would happen anyway, on Linux, for a stream in text mode... but perhaps that mechanism is in the logic of file streams.
推荐答案
这是在Unix机器上读取创建在UNIX上的文件时的普遍问题. Windows机器.我建议在输入处进行清理 级别.
This is a general problem on Unix machines when reading files created on a Windows machine. I would suggest doing the clean-up at the input level.
在读取基于行的文件时,我发现的最佳解决方案之一是 创建一个类似这样的类:
One of the best solution I've found when reading line based files is to create a class something like:
class Line
{
std::string myText;
public:
friend std::istream& operator>>( std::istream& source, Line& dest )
{
std::getline( source, dest.myText );
if ( source ) {
dest.myText.erase(
std::remove( dest.myText.begin(), dest.myText.end(), '\015' ),
dest.myText.end() );
}
return source;
}
operator std::string() const
{
return myText;
}
};
您可以根据需要添加其他功能:自动类型转换
例如,在尝试匹配模板时无法播放,而我发现了
添加朋友来包装boost::regex_match
很有用.
You can add other functions as necessary: the automatic type conversion
doesn't play when trying to match templates, for example, and I found it
useful to add friends to wrap boost::regex_match
.
即使不需要,我也使用此命令(无需删除'\015'
)
担心Windows/Linux的差异;它支持使用
例如std::istream_iterator<Line>
.
I use this (without the '\015'
removal) even when I don't have to
worry about Windows/Linux differences; it supports reading lines using
std::istream_iterator<Line>
, for example.
另一种解决方案是使用插入到 输入流.这也很简单:
Another solution would be to use a filtering streambuf, inserted into the input stream. This is also very simple:
class RemoveCRStreambuf : public std::streambuf
{
std::streambuf* mySource;
char myBuffer; // One char buffer required for input.
protected:
int underflow()
{
int results = mySource->sbumpc();
while ( results == '\015' ) {
results = mySource->sbumpc();
}
if ( results != EOF ) {
myBuffer = results;
setg( &myBuffer, &myBuffer + 1, &myBuffer + 1 );
}
return results;
}
public:
RemoveCRStreambuf( std::streambuf* source )
: mySource( source )
{
}
};
要插入它:
std::streambuf* originalSB = source->rdbuf();
RemoveCRStreambuf newSB( originalSB );
source->rdbuf( &newSB );
// Do input here...
source->rdbuf( originalSB ); // Restore...
(显然,使用某种RAII进行恢复
更好.我自己的过滤streambuf有一个构造函数,该构造函数需要
std::istream
;他们也保存了指向该指针的信息,并恢复了
销毁它们的析构函数.)
(Obviously, using some sort of RAII for the restoration would be
preferable. My own filtering streambuf have a constructor which takes
an std::istream
; they save a pointer to this as well, and restore the
streambuf in their destructor.)
这篇关于当它们进入`std :: stringstream`时,我可以去除回车吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!