Bill the Lizard
Bill the Lizard

Reputation: 405675

How do you search a std::string for a substring in C++?

I'm trying to parse a simple string in C++. I know the string contains some text with a colon, followed immediately by a space, then a number. I'd like to extract just the number part of the string. I can't just tokenize on the space (using sstream and <<) because the text in front of the colon may or may not have spaces in it.

Some example strings might be:

Total disk space: 9852465

Free disk space: 6243863

Sectors: 4095

I'd like to use the standard library, but if you have another solution you can post that too, since others with the same question might like to see different solutions.

Upvotes: 7

Views: 21137

Answers (6)

D.Shawley
D.Shawley

Reputation: 59553

I'm surprised that no one mentioned regular expressions. They were added as part of TR1 and are included in Boost as well. Here's the solution using regex's

typedef std::tr1::match_results<std::string::const_iterator> Results;

std::tr1::regex re(":[[:space:]]+([[:digit:]]+)", std::tr1::regex::extended);
std::string     str("Sectors: 4095");
Results         res;

if (std::tr1::regex_search(str, res, re)) {
    std::cout << "Number found: " << res[1] << std::endl;
} else {
    std::cerr << "No number found." << std::endl;
}

It looks like a lot more work but you get more out of it IMHO.

Upvotes: 3

Johannes Schaub - litb
Johannes Schaub - litb

Reputation: 506847

Similar to Konrads answer, but using istream::ignore:

int number;
std::streamsize max = std::numeric_limits<std::streamsize>::max();
if (!(std::cin.ignore(max, ':') >> number)) {
    std::cerr << "No number found." << std::endl;
} else {
    std::cout << "Number found: " << number << std::endl;
}

Upvotes: 3

Konrad Rudolph
Konrad Rudolph

Reputation: 545508

I can't just tokenize on the space (using sstream and <<) because the text in front of the colon may or may not have spaces in it.

Right, but you can use std::getline:

string not_number;
int number;
if (not (getline(cin, not_number, ':') and cin >> number)) {
    cerr << "No number found." << endl;
}

Upvotes: 4

Brian R. Bondy
Brian R. Bondy

Reputation: 347206

std::string strInput = "Total disk space: 9852465";
std::string strNumber = "0";
size_t iIndex = strInput.rfind(": ");
if(iIndex != std::string::npos && strInput.length() >= 2)
{
  strNumber = strInput.substr(iIndex + 2, strInput.length() - iIndex - 2)
}

Upvotes: 14

Adam Rosenfield
Adam Rosenfield

Reputation: 400156

For completeness, here's a simple solution in C:

int value;
if(sscanf(mystring.c_str(), "%*[^:]:%d", &value) == 1)
    // parsing succeeded
else
    // parsing failed

Explanation: the %*[^:] says to read in as many possible characters that aren't colons, and the * suppresses assignment. Then, the integer is read in, after the colon and any intervening white space.

Upvotes: 8

orip
orip

Reputation: 75427

const std::string pattern(": ");
std::string s("Sectors: 4095");
size_t num_start = s.find(pattern) + pattern.size();

Upvotes: 2

Related Questions