使用 istringstream 丢失随机字符
Posted
技术标签:
【中文标题】使用 istringstream 丢失随机字符【英文标题】:Losing random characters with istringstream 【发布时间】:2013-05-03 21:49:13 【问题描述】:我正在将文本文件的行读入变量 myline,然后尝试使用 istringstream 标记这些行。但是,似乎我正在丢失原始文本文件字符串中的随机字符。
cout<< myline << buff << flush; //print original text file line
istringstream iss(myline);
string sub;
while (iss >> sub)
cout << "[" << sub << "]" << endl;
如果您查看我的输出,您会发现我从文本文件中获得了正确的字符串,但是当我使用 istringstream 然后打印各个标记(在 [] 括号内看到)时,一些标记被过早截断.
#include <iostream>
[#include]
[<iostream]
#include <sstream>
[#include]
[<sstream>]
using namespace std;
[using]
[namespace]
[st]
int main()
[int]
[main(]
string str(" SOME LONG STRING\twith\nSPACES ");
[string]
[str("]
[SOME]
[LONG]
[STRING\twith\nSPACES]
istringstream iss(str);
[istringstream]
[iss(str);]
string s;
[strin]
while (iss >> s)
[while]
[(iss]
[>>]
cout << "[" << s << "]" << endl;
[cout]
[<<]
["["]
[<<]
[s]
[<<]
["]"]
[<<]
[e]
return 0;
[retur]
有人知道我做错了什么吗?提前致谢!
编辑:这是可以完全编译的代码版本。您可以使用任何文本文件运行它
#include <cstring>
#include <cstdio>
#include <iostream>
#include <iomanip>
#include <string>
#include <sstream>
#include <vector>
#include <algorithm>
#include <iterator>
using namespace std;
class MyFileReader
public:
//constructor
MyFileReader(const char* p);
//destructor
~MyFileReader();
//getLine()
int getLine(char *buffer, int size);
//getCurrentLineNumber()
int getCurrentLineNumber();
void tokenizeLine(vector<string>& vec);
FILE * pFile;
;
//constructor
MyFileReader::MyFileReader(const char* p)
pFile = fopen(p, "r");
//destructor
MyFileReader::~MyFileReader()
fclose(pFile);
//getLine()
int MyFileReader::getLine(char *buffer, int size)
char *out = fgets(buffer, size, pFile);
if (out==NULL)
return -1;
char *pch = strpbrk(out,"\n");
if (pch != NULL)
return 1;
else
return 0;
int MyFileReader::getCurrentLineNumber()
static int mynumber=2;
return mynumber++;
//tokenizeLine
void MyFileReader::tokenizeLine(vector<string>& vec)
string myline("");
char buff[10];
while (1)
int result = getLine(buff, sizeof(buff));
if (result == -1 )
if (myline.length() > 0)
cout << myline << flush;
break;
else if (result == 0)
myline += buff;
else if (result == 1)
cout<< myline << buff << flush;
istringstream iss(myline);
string sub;
while (iss >> sub)
cout << "[" << sub << "]" << endl;
myline = "";
else
printf("PANIC");
return;
int main(int argc, char **argv)
vector<string> v;
const char *filename = argv[1];
MyFileReader f(filename);
f.tokenizeLine(v);
return 0;
为了生成上面的输出,我运行它:
#include <iostream>
#include <sstream>
using namespace std;
int main()
string str(" SOME LONG STRING\twith\nSPACES ");
istringstream iss(str);
string s;
while (iss >> s)
cout << "[" << s << "]" << endl;
return 0;
【问题讨论】:
SSCCE + 原始输入会很好 ..error...cannot..reproduce...need...更多你的代码... 用可编译代码@DyP编辑 【参考方案1】:错误就在这里:
else if (result == 1)
cout<< myline << buff << flush;
istringstream iss(myline);
string sub;
while (iss >> sub)
cout << "[" << sub << "]" << endl;
myline = "";
如果result == 1
,则意味着buff
包含 \n
,并不意味着它仅包含\n
。 IE。如果缓冲区包含\n
,则删除它。因此,如果该行恰好有 n*10 (sizeof buffer) 个字符,则您的代码可以工作,否则,行的最后一个字符不会复制到 myline
而是删除。
快速解决办法是:
else if (result == 1)
myline += buff; // copy the rest of the line into `myline`
cout<< myline << flush; // buff now is part of myline
istringstream iss(myline);
string sub;
while (iss >> sub)
cout << "[" << sub << "]" << endl;
myline = "";
尽管您可能想考虑从缓冲区中删除 \n
,例如:
int MyFileReader::getLine(char *buffer, int size)
char *out = fgets(buffer, size, pFile);
if (out==NULL)
return -1;
//char *pch = strpbrk(out,"\n");
char *pch = strchr(out,'\n'); // no need to search for a string
if (pch != NULL)
*pch = '\0'; // drop the '\n'
return 1;
else
return 0;
不过,您必须将 cout<< myline << flush;
更改为 cout<< myline << endl;
。
除了这个错误,请考虑使用ifstream
:
#include <iostream>
#include <fstream>
#include <sstream>
using namespace std;
int main()
ifstream file("test.txt");
if(!file)
/* error */
else
string line;
while(getline(file, line))
istringstream iss(line);
string s;
while (iss >> s)
cout << "[" << s << "]" << endl;
【讨论】:
谢谢!我没有考虑缓冲区的其余部分,这很有意义。【参考方案2】:您的行缓冲区只有 10 个字节长。这还不够长,无法容纳一整行。
void MyFileReader::tokenizeLine(vector<string>& vec)
string myline("");
char buff[10];// this is too short
....
编辑
当您在输入文件中检测到 \n 时,Dyp 正确指出您的附加逻辑不正确。
【讨论】:
但 OP 使用myline
添加缓冲区以形成行。 myline += buff;
是的,DyP 是正确的。我在那里跳得有点快。我将编辑帖子以表明这一点。
谢谢大家!我花了很多时间想知道为什么我的输出不符合预期,而不仔细考虑我的 if 语句。以上是关于使用 istringstream 丢失随机字符的主要内容,如果未能解决你的问题,请参考以下文章
在 C++ 中使用 istringstream 将字符串拆分为整数
C++ 使用 istringstream 将整数读取为无符号字符