string :: find当它返回值0时返回值-1 [C ++]

时间:2010-11-21 19:06:04

标签: c++

我有以下代码不起作用:

string line;
string line_sub;
size_t open_tag_start;
const string open_tag = "<image>";
const int open_len = open_tag.length() + 1;

open_tag_start = line.find(open_tag);
line_sub = line.substr(open_tag_start, open_len);

当我尝试运行此代码时,出现以下错误:

terminate called after throwing an instance of 'std::out_of_range'
what():  basic_string::substr
Aborted (core dumped)

我发现发生此错误是因为line.find行将值-1返回给变量open_tag_start。我可以通过将0的值硬编码到变量open_tag_start中来解决问题,但我需要这个能够在行中的任何位置找到标记的通用算法,所以它必须是一个变量。谁能看到我在这里做错了什么?

以下是更多信息。

我的目标是使用此代码从string line_sub中提取string line,确实包含字符串,当我设置size_t open_tag_start = 0时,我能够编译并执行代码并观察预期的输出。 line不是空的,我的问题是当我更换

line_sub = line.substr(open_tag_start, open_len);

line_sub = line.substr(0, open_len);

我的问题消失了,我可以编译并执行代码。

这是我的程序的简短版本,仅包含导致问题的部分。尝试编译此代码将产生上面详述的错误消息。文件rss.xml是engadget.com http://www.engadget.com/rss.xml

的RSS源
#include <iostream>
#include <string>
#include <sstream>
#include <fstream>
#include <cstring>
using namespace std;

void get_tag_contents(ifstream& rssfile, string line, string open_tag);

int main()
{
    const string open_tag = "<image>";

    ifstream rssfile;
    rssfile.open("rss.xml");
    string line;

    getline(rssfile, line, '\n');
    get_tag_contents(rssfile, line, open_tag);

    return 0;
}

void get_tag_contents(ifstream& rssfile, string line, string open_tag)
{   
    const int open_len = open_tag.length() + 1;
    size_t open_tag_start;
    string line_sub;

    open_tag_start = line.find(open_tag);
    line_sub = line.substr(open_tag_start, open_len);
}

4 个答案:

答案 0 :(得分:3)

除非你遗漏了一些代码,line是一个空字符串,所以当然find失败了。你的期望是错误的,而不是find函数 - 这就是全部!

作为旁注,在使用C ++字符串时,您无需补偿'\0'。摆脱+ 1

答案 1 :(得分:2)

如果在字符串中找不到子字符串,则find()方法将返回std::string::npos,这是一个值为-1的size_type。当您使用substr()等于-1来调用open_tag_start时,这就是抛出out_of_range错误的原因。

答案 2 :(得分:1)

正如其他人所说,如果搜索失败,你必须检查find()的返回值。

std::string line("this is <image> a test");
std::string line_sub;
const std::string open_tag = "<image>";

size_t open_tag_start = line.find(open_tag);

if (open_tag_start != std::string::npos)
{
    line_sub = line.substr(open_tag_start, open_tag.length());
}

std::cout << line << "\n" << line_sub << "\n";

答案 3 :(得分:0)

嗯,你确定line包含<image>吗?需要考虑的一件事是<ImaGe>可能以某种方式大写。此外,我不太明白你要做什么,因为line_sub(假设你的代码有效)将只返回enter code here和之后的下一个字符。你想要完成什么?

请记住清理您的返回值。如果find返回-1,则处理问题或抛出错误。