Bill the Lizard
Bill the Lizard

Reputation: 406015

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: 21148

Answers (6)

D.Shawley
D.Shawley

Reputation: 59623

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: 507273

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: 546045

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: 347546

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: 400612

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: 75537

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

Upvotes: 2

Related Questions