Thread: Converting string vector to integer vector

  1. #1
    Registered User
    Join Date
    Feb 2010
    Posts
    67

    Smile Converting string vector to integer vector

    Hello

    My goal is to allow the person to input a string of numbers like:
    1 22 333 4444 55555 666666 7777777 88888888 999999999

    and make a vector called ivec that would look like:
    ivec.at(0) = 1
    ivec.at(1) = 22
    ivec.at(2) = 333
    ivec.at(3) = 4444
    ivec.at(4) = 55555
    ivec.at(5) = 666666
    ivec.at(6) = 7777777
    ivec.at(7) = 88888888
    ivec.at(8) = 999999999

    How would I do this?

    This is what I have so far (there's a conversion failure, but I hope the goal is clear enough):

    Code:
    //user is to provide the numbers
    cout << "Numbers: " ;
    
    //user now provides the numbers in string form
    string str_version;
    getline( cin , str_version );
    
    //stringstream is made
    stringstream ss(str_version);
    
    //string version vector is made
    vector<string> svec;
    
    //the string-version numbers provided by the user are written into the vector
    copy( istream_iterator<string>(ss) , istream_iterator<string>() , back_inserter(svec) );
    
    //integer version vector is now made
    vector<int> ivec;    
    
    //this is where the conversion fails, but, atoi() or some other function, would basically
    //convert the string version of the number into an integer and input that at the same
    //slot, only in ivec this time.
    for (int i = 0 ; i < (sizeof(svec) - 1) ; i++)
    {
        ivec.at(i) = atoi(svec.at(i));
    }
    
    //if this worked, then operating between the numbers would be no problem,
    //such as adding two together
    cout << ivec.at(1) + ivec.at(2) << endl;
    
    //closing statements
    cin.clear();
    cin.ignore( numeric_limits < streamsize > ::max(), '\n');
    cin.get();
    main();
    The best method would directly copy the integers into the vector, rather than convert them from a string version (unfortunately I'm working with what I know).

    Thanks for any input

  2. #2
    Registered User
    Join Date
    Aug 2005
    Posts
    266
    you dont need atoi if your gonna use stringstreams i think


    how about this

    Code:
    #include <vector>
    #include <iostream>
    #include <sstream>
    #include <string>
    #include <numeric>
    
    using namespace std;
    
    vector<int> vecstr_to_vecint(vector<string> vs)
    {
    	vector<int> ret;
    	for(vector<string>::iterator it=vs.begin();it!=vs.end();++it)
    	{
    		istringstream iss(*it);
    		int temp;
    		iss >> temp;
    		ret.push_back(temp);
    	}  
    	return ret;
    }
    
    int main()
    {
    	string input, temp;
    	vector<string> tokens;
    
    	getline(cin, input);
    	istringstream iss(input);
    	while(iss >> temp)
    		tokens.push_back(temp);
    	
    	vector<int> input_int = vecstr_to_vecint(tokens);
    
    	//now for test I will print the sum!
    	cout << accumulate(input_int.begin(), input_int.end(), 0) << endl;
    }
    edit: tested it works

    I am not sure what the general consensus on exactly when streams are meant to be used but I frequently use them to convert between types...
    I use istringstream if I want to insert a large string and tokenize it, I use an ostringstream if I want to insert various objects likes strings and ints and spit out a large string with .str()
    Last edited by rodrigorules; 05-08-2010 at 05:45 AM.

  3. #3
    Registered User
    Join Date
    Mar 2009
    Posts
    399
    Why not use the capabilities of the stringstream class instead of atoi()?

    Code:
    #include <sstream>
    #include <iostream>
    #include <string>
    #include <vector>
    
    int main()
    {
        std::string input;
        std::getline(std::cin, input);
    
        std::istringstream iss(input);
        std::vector<int> vec;
        int conversion_result;
    
        while (iss >> conversion_result)
        {
            vec.push_back(conversion_result);
            std::cout << conversion_result << std::endl;
        }
        
        return 0;
    }

  4. #4
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    Ah, a C programmer learning C++.....

    The "conversion failure" is an error message from your compiler that is emitted because atoi() accepts a (const) pointer to char (or an array of char) not a std::string. However, std::string has a method named c_str() that gives an equivalent pointer to char.

    Other problems with your code (other than it being incomplete);

    1) The number of elements of svec is obtained as svec.size(), not as sizeof(svec).

    2) If you are using a vector's at() method, the element you fetch needs to be valid (index in the range 0 to size()-1). Fetching the third element of a 2-element vector, for example, is invalid. ivec is created with zero elements, and never resized before using the at() method. That gives undefined behaviour.

    3) There is no need to use an intermediate vector<string> if you rewrite the copy() operation as copy( istream_iterator<int>(ss) , istream_iterator<int>() , back_inserter(svec) );

    4) Calling main() is forbidden in C++.
    Right 98% of the time, and don't care about the other 3%.

    If I seem grumpy or unhelpful in reply to you, or tell you you need to demonstrate more effort before you can expect help, it is likely you deserve it. Suck it up, Buttercup, and read this, this, and this before posting again.

  5. #5
    The larch
    Join Date
    May 2006
    Posts
    3,573
    Code:
    copy( istream_iterator<string>(ss) , istream_iterator<string>() , back_inserter(svec) );
    This would be OK, except you want to read integers from the stream, not strings.

    Code:
    copy( istream_iterator<int>(ss) , istream_iterator<int>() , back_inserter(svec) );
    You can also use the vector's constructor that takes a pair of iterators, but be aware of the "most vexing parse" (expression interpreted as a function declaration) - note the extra parenthesis to work around that:

    Code:
    vector<int> ivec((istream_iterator<string>(ss)) , istream_iterator<string>() );
    ----

    And if you want to get more advanced, and detect if the user input consists of integers in the first place, rather than silently swallowing errors, you can use Boost's handy lexical_cast, which throws an exception if a string is not fully convertible to target type.

    Code:
    transform(istream_iterator<string>(ss), istream_iterator<string>(), back_inserter(ivec), &boost::lexical_cast<int, string>);
    Last edited by anon; 05-08-2010 at 05:50 AM.
    I might be wrong.

    Thank you, anon. You sure know how to recognize different types of trees from quite a long way away.
    Quoted more than 1000 times (I hope).

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. memory issue
    By t014y in forum C Programming
    Replies: 2
    Last Post: 02-21-2009, 12:37 AM
  2. Looking for constructive criticism
    By wd_kendrick in forum C Programming
    Replies: 16
    Last Post: 05-28-2008, 09:42 AM
  3. Inheritance Hierarchy for a Package class
    By twickre in forum C++ Programming
    Replies: 7
    Last Post: 12-08-2007, 04:13 PM
  4. Classes inheretance problem...
    By NANO in forum C++ Programming
    Replies: 12
    Last Post: 12-09-2002, 03:23 PM
  5. Converting a "Char" string to an Integer Array
    By Jazz in forum C++ Programming
    Replies: 3
    Last Post: 12-14-2001, 01:50 PM

Tags for this Thread