1

I want to extract integers from a certain string in order to perform mathematical operations on them.

For example for a string

25 1 3; 5 9 2; 1 3 6

I only want to extract

25, 1, 3, 5, 9, 2, 1, 3, 6

is there a way I can do that?

PStarczewski
  • 479
  • 2
  • 17

4 Answers4

2

I would just use the String Toolkit to parse the strings using spaces, brackets and semicolon as the delimiters.

I have answered the questions before Extract Data from a line

I paraphrased that code below:

#include <strtk.hpp>   // http://www.partow.net/programming/strtk

std::string src = "[25 1 3; 5 9 2; 1 3 6]";

std::string delims(" [];");

std::vector<int> values;

strtk::parse(src, delims, values );

// values will contain all the integers in the string.
// if you want to get floats & integers the vector needs to be float
DannyK
  • 1,342
  • 16
  • 23
0

There are many various methods for doing that. For example you can use <regex> and pick them, but I think extracting from string stream will be easier.

void extractIntegerWords(string str)
{
  stringstream ss;

  /* Storing the whole string into string stream */
  ss << str;

  /* Running loop till the end of the stream */
  string temp;
  int found;

  while (!ss.eof()) {

    /* extracting word by word from stream */
    ss >> temp;

    /* Checking the given word is integer or not */
    if (stringstream(temp) >> found)
        cout << found << " ";

    /* To save from space at the end of string */
    temp = "";
  }
}

// Driver code 
int main()
{
  string str = "25 1 3; 5 9 2; 1 3 6";
  extractIntegerWords(str);
  return 0;
}

Code taken from here: Extract integers from string

PStarczewski
  • 479
  • 2
  • 17
0

if you want to extract them from a string having any content (you do not know what are the other characters) you can use a stringstream

For instance supposing the number are int and wanted the extracted int in a list :

#include <sstream>
#include <iostream>
#include <string>
#include <list>

int main(int argc, char ** argv)
{
  if (argc == 2) {
    std::stringstream iss(argv[1]);
    std::list<int> l;

    for (;;) {
      int v;

      if (iss >> v)
        // ok read an int
        l.push_back(v);
      else {
        // was not an int, clear error
        iss.clear();

        // try to read a string to remove non digit
        std::string s;

        if (!(iss >> s))
          // EOF, end of the initial string
          break;
      }
    }

    for (auto v : l)
      std::cout << v << ' ';
    std::cout << std::endl;
  }

  return 0;
}

Compilation and execution :

pi@raspberrypi:~ $ g++ -pedantic -Wall -Wextra c.cc
pi@raspberrypi:~ $ ./a.out "25 1 3; 5 9 2; 1 3 6"
25 1 3 5 9 2 1 3 6 
pi@raspberrypi:~ $

Note in that solution "123 a12 13" will produce 123 and 13, not 123 12 13.

To produce 123 12 13 from "123 a12 13" just read a character rather than a string in case of an error :

#include <sstream>
#include <iostream>
#include <string>
#include <list>

int main(int argc, char ** argv)
{
  if (argc == 2) {
    std::stringstream iss(argv[1]);
    std::list<int> l;

    for (;;) {
      int v;

      if (iss >> v)
        l.push_back(v);
      else {
        iss.clear();

        char c;

        if (!(iss >> c))
          break;
      }
    }

    for (auto v : l)
      std::cout << v << ' ';
    std::cout << std::endl;
  }

  return 0;
}

Compilation and execution :

pi@raspberrypi:~ $ g++ -pedantic -Wall -Wextra c.cc
pi@raspberrypi:~ $ ./a.out "25 1 3; 5 9 2; 1 3 6"
25 1 3 5 9 2 1 3 6 
pi@raspberrypi:~ $ ./a.out "123 a12 13"
123 12 13 
bruno
  • 32,421
  • 7
  • 25
  • 37
0

A one pass solution can scan the string looking for a range starting with the next digit available and stopping where there is a non-digit character. Then create an integer from the characters in the range and continue until the end of the string is reached.

vector<int> extract_ints( std::string const& str ) {
  auto& ctype = std::use_facet<std::ctype<char>>(std::locale{});
  auto p1 = str.data(), p2 = str.data();

  vector<int> v;
  for (auto e = &str.back() + 1; p1 < e; p1++) {
    p1 = ctype.scan_is( ctype.digit, p1, e );
    p2 = ctype.scan_not( ctype.digit, p1 + 1, e );
    int x = 0;
    while (p1 != p2) {
      x = (x * 10) + (*p1 - '0');
      p1++;
    }
    v.push_back(x);
  }
  return v;
}

Example:

auto v = extract_ints("[1,2,3]");
for (int i=0; i<v.size(); i++)
  cout << v[i] << " ";

Output:

1 2 3
David G
  • 94,763
  • 41
  • 167
  • 253