我有以下代码来阅读文本文件。
const string FILENAME = PACKAGES_DIR + pname;
//the arguments to ifstream is a cstring and hence the conversion must be made
ifstream freader;
freader.open(FILENAME.c_str(),ios::in);
if(freader.is_open())
{
while(freader.good())
{
string line;
getline(freader,line);
cout<<line<<endl;
if(line.find("PackageId:"))
{
cout<<line.substr(11)<<endl;
}
else if(line.find("Name:"))
{
cout<<line.substr(5)<<endl;
}
else if(line.find("Version:"))
{
cout<<line.find(8)<<endl;
}
else
{
cout<<line<<endl;
}
}
}
有问题的文字内容是
PackageId:994
Name:basket
Version:1.80-1
Deps:kdebase-runtime,libc0.1,libc0.1-udeb,libc6,libc6-udeb,libc6.1,libc6.1-udeb,libgcc1,libgpg-error0,libgpgme11,libkdecore5,libkdeui5,libkfile4,libkio5,libkparts4,libkutils4,libphonon4,libqimageblitz4,libqt4-dbus,libqt4-network,libqt4-qt3support,libqt4-svg,libqt4-xml,libqtcore4,libqtgui4,libstdc++6,libunwind7,libx11-6,phonon
我得到的输出是
PackageId:994
geId:994
Name:basket
Version:1.80-1
0-1
Deps:kdebase-runtime,libc0.1,libc0.1-udeb,libc6,libc6-udeb,libc6.1,libc6.1-udeb,libgcc1,libgpg-error0,libgpgme11,libkdecore5,libkdeui5,libkfile4,libkio5,libkparts4,libkutils4,libphonon4,libqimageblitz4,libqt4-dbus,libqt4-network,libqt4-qt3support,libqt4-svg,libqt4-xml,libqtcore4,libqtgui4,libstdc++6,libunwind7,libx11-6,phonon
e-runtime,libc0.1,libc0.1-udeb,libc6,libc6-udeb,libc6.1,libc6.1-udeb,libgcc1,libgpg-error0,libgpgme11,libkdecore5,libkdeui5,libkfile4,libkio5,libkparts4,libkutils4,libphonon4,libqimageblitz4,libqt4-dbus,libqt4-network,libqt4-qt3support,libqt4-svg,libqt4-xml,libqtcore4,libqtgui4,libstdc++6,libunwind7,libx11-6,phonon
terminate called after throwing an instance of 'std::out_of_range'
what(): basic_string::substr
我想要的输出是:
PackageId:994
994
Name:basket
basket
Version:1.80-1
1.80-1
...
我做错了什么?
答案 0 :(得分:5)
while .good
或while !.eof
几乎总是错误的。扔掉任何书告诉你这样做,do this instead。
在这种情况下,更改的代码看起来有点像这样:
const string FILENAME = PACKAGES_DIR + pname;
//the arguments to ifstream is a cstring and hence the conversion must be made
ifstream freader(FILENAME.c_str(), ios::in);
if (freader) {
string line;
while (getline(freader,line)) { // <-----
cout << line << endl;
if (line.find("PackageId:"))
cout << line.substr(11) << endl;
else if (line.find("Name:"))
cout << line.substr(5) << endl;
else if (line.find("Version:"))
cout << line.find(8) << endl;
else
cout << line << endl;
}
}
您没有正确使用std::string::find
。
line.find("PackageId:")
返回“搜索内容的字符串中第一次出现的位置”,如果找不到匹配则返回成员值npos
。
这与未对std::string::substr
的第一个参数执行边界检查相结合,导致字符串出现问题。
相反,写一下:
if (line.find("PackageId:") != std::string::npos)
cout<<line.find(8)<<endl;
应该说substr
,而不是find
。
您的代码中包含上述某些内容:
const string FILENAME = PACKAGES_DIR + pname;
//the arguments to ifstream is a cstring and hence the conversion must be made
ifstream freader(FILENAME.c_str(), ios::in);
if (freader) {
string line;
while (getline(freader,line)) { // <-----
cout << line << endl;
if (line.find("PackageId:") != std::string::npos && line.size() > 11)
cout << line.substr(11) << endl;
else if (line.find("Name:") != std::string::npos && line.size() > 5)
cout << line.substr(5) << endl;
else if (line.find("Version:") != std::string::npos && line.size() > 8)
cout << line.substr(8) << endl;
else
cout << line << endl;
}
}
答案 1 :(得分:2)
检查抛出的异常,它清楚地告诉你出了什么问题
抛出的异常的what()
打印出来:
what():basic_string :: substr
告诉你,
substr
请参阅 string::substr :
的文档
string substr ( size_t pos = 0, size_t n = npos ) const;
生成子字符串
返回一个字符串对象,其内容初始化为子字符串 当前对象。
此子字符串是以字符开头的字符序列 位置pos,长度为n个字符。
参数的
pos 当前字符串对象中字符的位置,用作子字符串的起始字符。 如果传递的位置超过字符串的结尾,则会抛出out_of_range异常。
n 子字符串的长度。如果此值将使子字符串跨越当前字符串内容的末尾,则仅 使用字符串结尾之前的那些字符。 npos是一个 静态成员常量值,具有最大可能值 因此,当使用此值时,所有类型都是size_t类型的元素 pos和字符串结尾之间的字符用作 初始化子字符串。
答案 2 :(得分:1)
更改
else if(line.find("Version:"))
{
cout<<line.find(8)<<endl; //<--------------------
}
要
else if(line.find("Version:"))
{
cout<<line.substr(8)<<endl; //<----------------------
}
答案 3 :(得分:1)
突出的第一个问题是,您尝试读取一行并使用该行而不检查读取是否成功。您应该将循环更改为以下内容,而不是检查文件在while条件下是否良好:
string line;
while(getline(freader,line))
{
// now you can safely process line
}
答案 4 :(得分:0)
不使用substr
位置的固定常量,而是使用位置变量:
std::string::size_t position = 0;
static const char packageIdFieldName[] = "PackageId:";
position = find(packageIdFieldName);
if (position != std::string::npos)
{
// The "sizeof('\0')" is a blantant reminder to subract
// the size of the terminating nul character.
cout << line.substr(position + sizeof(packageIdFieldName) - sizeof('\0'))
<< endl;
continue;
}