3

What is the best and shortest way to extract integers from a string and save them to an array of integers?

Sample string " 65 865 1 3 5 65 234 65 32 #$!@#"

I tried taking look at some other posts but couldn't find one about this specific issue... Some help and explanation would be great.

Ezz
  • 534
  • 2
  • 8
  • 17
  • Is your string always have non-digit starting as `#` and are put at the end of the string? – taocp Jun 07 '13 at 15:19
  • my string is actually all integers but ends with one non-digit character ex: "1 4 5 2 54 65 3246 53490 80 9 #" – Ezz Jun 07 '13 at 15:21
  • try to take a look at stringstream? Or look at this tutorial from topcoder? I guess this way you could learn more: http://community.topcoder.com/tc?module=Static&d1=features&d2=112106 and this post may be useful: http://stackoverflow.com/questions/236129/splitting-a-string-in-c – taocp Jun 07 '13 at 15:25

4 Answers4

4

It seems this can all be done with std::stringstream:

#include <iostream>
#include <string>
#include <sstream>
#include <vector>
using namespace std;

int main() {
    std::string str(" 65 865 1 3 5 65 234 65 32 #$!@#");
    std::stringstream ss(str);
    std::vector<int> numbers;

    for(int i = 0; ss >> i; ) {
        numbers.push_back(i);
        std::cout << i << " ";
    }
    return 0;
}

Here is a solution that accounts for non digits between numbers:

#include <iostream>
#include <string>
#include <sstream>
#include <vector>
#include <algorithm>
using namespace std;

struct not_digit {
    bool operator()(const char c) {
        return c != ' ' && !std::isdigit(c);
    }
};

int main() {
    std::string str(" 65 865 1 3 5 65 234 65 32 #$!@# 123");
    not_digit not_a_digit;
    std::string::iterator end = std::remove_if(str.begin(), str.end(), not_a_digit);
    std::string all_numbers(str.begin(), end);
    std::stringstream ss(all_numbers);
    std::vector<int> numbers;

    for(int i = 0; ss >> i; ) {
        numbers.push_back(i);
        std::cout << i << " ";
    }
    return 0;
}
andre
  • 7,018
  • 4
  • 43
  • 75
  • It seems using `stringstream` alone will not work in this case `" 65 865 1 3 5 65 234 65 32 #$!@# 123"` – andre Jun 07 '13 at 16:00
  • Ah, now I see it. I'll add this solution in the bottom encase anyone ever needs it. – andre Jun 07 '13 at 16:04
1

Because of the complexities of the delimiters here (you seem to have spaces and non-numeric characters) I'd use the string splitting available in the boost library:

http://www.boost.org/

This allows you to split using regular expressions as delimiters.

First, pick the delimiter which is a regular expression:

boost::regex delim(" "); // I have just a space here, but you could include other things as delimiters.

Then extract as follows:

std::string in(" 65 865 1 3 5 65 234 65 32 ");
std::list<std::string> out;
boost::sregex_token_iterator it(in.begin(), in.end(), delim, -1);
while (it != end){
    out.push_back(*it++);
}

So you can see I've reduced it to a list of strings. Let me know if you need to do the whole step to an array of integers (not sure what array type you want); happy to include that too if you want to go the boost way.

Bathsheba
  • 231,907
  • 34
  • 361
  • 483
0

You can us a stringstream to hold you string data and the read it out into integers using the typical C++ iostream mechanisms:

#include <iostream>
#include <sstream>
int main(int argc, char** argv) {
   std::stringstream nums;
   nums << " 65 865 1 3 5 65 234 65 32 #$!@#";
   int x;
   nums >> x;
   std::cout <<" X is " << x << std::endl;
} // => X is 65

This'll spit out the first number, 65. Getting the data clean will be another matter. You can check

nums.good() 

to see if the read into an int was successful.

Paul Rubel
  • 26,632
  • 7
  • 60
  • 80
0

I like to use istringstream for this

istringstream iss(line);
iss >> id;

Since it is a stream, you can use it just like cin By default, it uses space as a delimiter. You can simply wrap this in a loop and then cast the resulting string as an int.

http://www.cplusplus.com/reference/sstream/istringstream/istringstream/

crand6
  • 114
  • 6