2016-07-07 58 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. 
     } 
    } 
}