2016-07-07 29 views
0

我想从连续的字符串数据流中提取线。但数据格式不正确,我想放弃提取的行,以便内存不会超出界限。从连续的字符串流中提取线

例如,我有串行端口输出,诸如这样的:

批次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代码不起作用()修改字符串流,使没有更多的数据可以被插入到它,我想保持stringstream的内存小了。所以我不认为我可以使用getline()并使用类似'popline()'的东西(如果存在)。

+1

不确定,但尝试在内部'while()'循环后调用'ss.clear()'? –

+0

为什么不使用'std :: deque'来保存行(每个都是'std :: string')?你想要的是一个“循环缓冲区”,并且流类没有被设计为表现这种方式。 (在标准库中也没有其他的东西。) – davidbak

回答

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... 
    } 
} 
0

主要功能改变什么杀OP的第一刀是在由πάνταῥεῖ暗示。

while(getline(ss, oneline)) 

最终到达ss的末尾并设置EOF错误标志。一旦发生这种情况,流将不会执行任何操作,直到错误标志被clear确认。

它也会提取到流尾,抓取任何部分行,并破坏OP在读取之间缓冲数据的尝试。

我在想,OP可能想要变得更原始一点。我通常使用read函数的char数组来做类似的事情。这是完全愚蠢和愚蠢的。与findsubstring的方法相比,很可能这会失去几个速度,但更容易得到正确的结果。

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. 
     } 
    } 
}