我想从连续的字符串数据流中提取行。但数据格式不正确,我想丢弃提取的行,以便内存不会超出限制。
例如,我有串口输出,如:
批次1
POS 30 10 20\n
POS 30 10 21\n
POS 30 1
批次2
0 22\n
POS 30 10 23\n
PO
有没有办法有效地保存数据并从中提取线?
这是我的代码:
stringstream ss;
while (SP->IsConnected())
{
string result = SP->ReadData();
ss << result;
string oneline;
while(getline(ss, oneline))
{
cout << oneline << endl;
// or do something more interesting...
}
}
但是我的代码不起作用,因为getline()修改了字符串流,因此不能再插入数据,我想保持字符串流内存较小。所以我不认为我可以使用getline()并使用类似&#39; popline()&#39;相反,如果它存在。
答案 0 :(得分:0)
从评论中获取提示,我想出了我自己的popline(),它不使用stringstream。感谢您的评论。
// like getline() for istream, but made for string and pops out the line from the input
bool popline(string& input, string& output, char delim = '\n')
{
size_t i = 0;
string line;
for (char ch : input)
{
line.push_back(ch);
++i;
if (ch == delim)
{
output = line;
input.erase(0, i); // erase the extracted line (unlike getline)
return true;
}
}
return false; // return without producing the line string when end is reached (unlike getline)
}
所以我的主要功能变为
string st;
while (SP->IsConnected())
{
string result = SP->ReadData();
st += result;
string oneline;
while(popline(st, oneline))
{
cout << oneline << endl;
// or do something more interesting...
}
}
答案 1 :(得分:0)
πάνταῥεῖ暗示了OP的第一次切割是什么。
while(getline(ss, oneline))
最终点击ss
的结尾并设置EOF错误标志。一旦发生这种情况,在使用clear
确认错误标志之前,流将不会执行任何操作。
它还将提取到流的末尾,抓取任何部分行并破坏OP尝试在读取之间缓冲数据。
我认为OP可能想要更原始一点。我通常使用char
函数中的read
数组执行此类操作。这完全是愚蠢和万无一失的。与find
和substring
方法相比,这很可能会失去一些速度点,但更容易做对。
stringstream ss;
while (SP->IsConnected())
{
string result = SP->ReadData(); // get blob of unknown size and contents
for (char ch: result) // read through blob character by character
{
if (ch != '\n') // not a delimiter, store
{
ss << ch;
}
else // got a complete token. May have taken multiple ReadData calls
// note that this also leaves the delimiter out of the data passed
// on to further parsing. Usually a good thing.
{
cout << ss.str()<< endl; // handle token
ss.str(std::string());
// depending on how you parse ss, you may need
ss.clear();
// to clean up error flags like EOF.
}
}
}