string::find returning a value of -1 when it's expected to return a value of 0 [C++]
I have the following code that doesn't work:
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);
When I try to run this code, I get the following error:
terminate called after throwing an instance of 'std::out_of_range' what(): basic_string::substr Aborted (core dumped)
I've figured out that this error is occurring because the line.find
line is returning a value of -1
to the variable open_tag_start
. I can rectify the problem by hard coding a value of 0
into the variable open_tag_start
, but I need this to a generic algorithm that will be able to find the tag at any point in the line, so it has to be a variable. Can anyone see what I'm doing wrong here?
Here's some more info.
My goal with this code if to extract a string line_sub
from string line
, which does indeed contain a string, and when I set size_t open_tag_start = 0
, I am able to compile and execute the开发者_StackOverflow code and observe the expected output. line
is not empty and my problem is that when I replace
line_sub = line.substr(open_tag_start, open_len);
with
line_sub = line.substr(0, open_len);
my problem goes away and I can compile and execute the code.
This is a short version of my program that contains only the parts that are causing the problems. Attempting to compile this code will yield the error message detailed above. The file rss.xml
is the RSS feed for engadget.com http://www.engadget.com/rss.xml
#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);
}
Unless you've left out some code, line
is an empty string, so of course find
fails. It is your expectation that is in error, not the find
function—that's all!
As a side note, you don't need to compensate for '\0'
when using C++ strings. Get rid of the + 1
.
If the substring isn't found in the string, then the find()
method will return std::string::npos
, which is a size_type of value -1. When you call substr()
with open_tag_start
equalling -1, then this is what throws the out_of_range error.
As others have noted, you must check the return value of find() in case the search fails.
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";
Well, are you sure that line
contains <image>
?? One thing to consider is that <ImaGe>
may be capitalized in some way. Also, i dont quite see what you're trying to do, because line_sub
(given that your code works) will just return enter code here
and the next character after that. What are you trying to accomplish?
Remember to sanitize your return values. If find returns -1, deal with the problem or throw an error.
精彩评论