简体   繁体   中英

How do I convert vector of strings into vector of integers in C++?

I have a vector of strings. Need help figuring out how to convert it into vector of integers in order to be able to work with it arithmetically. Thanks!

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

int main(int argc, char* argv[]) {

    vector<string> vectorOfStrings;
    vectorOfStrings.push_back("1");
    vectorOfStrings.push_back("2");
    vectorOfStrings.push_back("3");

    for (int i=0; i<vectorOfStrings.size(); i++)
    {
        cout<<vectorOfStrings.at(i)<<endl;
    }

    vector<int> vectorOfIntegers;

    //HELP NEEDED HERE
    //CONVERSION CODE from vector<string> to vector<int> 

    int sum;
    for (int i=0; i<vectorOfIntegers.size(); i++)
    {
        sum += vectorOfIntegers.at(i);
    }
    cout<<sum<<endl;
    cin.get();

    return 0;
}

There are mulitple ways of converting a string to an int.

Solution 1: Using Legacy C functionality

int main()
{
    //char hello[5];     
    //hello = "12345";   --->This wont compile

    char hello[] = "12345";

    Printf("My number is: %d", atoi(hello)); 

    return 0;
}

Solution 2: Using lexical_cast (Most Appropriate & simplest)

int x = boost::lexical_cast<int>("12345"); 

Surround by try-catch to catch exceptions.

Solution 3: Using C++ Streams

std::string hello("123"); 
std::stringstream str(hello); 
int x;  
str >> x;  
if (!str) 
{      
   // The conversion failed.      
} 

Use boost::lexical_cast . And surround it with try-catch block.

try
{
   for (size_t i=0; i<vectorOfStrings.size(); i++)
   {
      vectorOfIntegers.push_back(boost::lexical_cast<int>(vectorOfStrings[i]));
   }
}
catch(const boost::bad_lexical_cast &)
{
    //not an integer 
}

Or you can use Boost.Spirit parser (which someone claims is faster than even atoi() ) as:

int get_int(const std::string & s)
{
    int value = 0;
    std::string::const_iterator first = s.begin();
    bool r = phrase_parse(first,s.end(),*int_[ref(value)=_1], space);
    if ( !r || first != s.end()) throw "error"; 
    return value;
}

//Usage
int value = get_int("17823");
std::cout << value << std::endl; //prints 17823

The full demo using your code : http://ideone.com/DddL7

#include <string>
#include <vector>

#include <iterator>
#include <algorithm>
#include <boost/lexical_cast.hpp>

using namespace std;

int stringToInteger(const std::string& s)
{
    return boost::lexical_cast<int>(s);
}

int main(int /*argc*/, char* /*argv*/[])
{
    vector<string> vectorOfStrings;

    // ..

    vector<int> vectorOfIntegers;
    std::transform(vectorOfStrings.begin(), vectorOfStrings.end(), std::back_inserter(vectorOfIntegers), stringToInteger);

    // ..
}

You can replace the implementation of stringToInteger(..) with your preferred conversion function.

Here is the working version made up using the above comments.

#include <iostream>
#include <string>
#include <vector>
#include <sstream>

using namespace std;

int main(int argc, char* argv[]) {

    vector<string> vectorOfStrings;
    vectorOfStrings.push_back("1");
    vectorOfStrings.push_back("2");
    vectorOfStrings.push_back("3");

    for (int i=0; i<vectorOfStrings.size(); i++)
    {
        cout<<vectorOfStrings.at(i)<<endl;
    }

    vector<int> vectorOfIntegers;
    int x;
    for (int i=0; i<vectorOfStrings.size(); i++)
    {
        stringstream str(vectorOfStrings.at(i));
        str >> x;
        vectorOfIntegers.push_back(x);
    }

    int sum = 0;
    for (int i=0; i<vectorOfIntegers.size(); i++)
    {
        sum += vectorOfIntegers.at(i);
    }
    cout<<sum<<endl;
    cin.get();

    return 0;
}

What about:

#include <algorithm>
#include <boost/lexical_cast.hpp>

template<typename C1, typename C2>
void castContainer(const C1& source, C2& destination)
{
    typedef typename C1::value_type source_type;
    typedef typename C2::value_type destination_type;
    destination.resize(source.size());
    std::transform(source.begin(), source.end(), destination.begin(), boost::lexical_cast<destination_type, source_type>);
}

It can convert vector<string> into vector<int>, and also other container<T1> into container2<T2>, eg: list -> list.

Full code:

#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>
#include <string>
#include <boost/lexical_cast.hpp>

template<typename C1, typename C2>
void castContainer(const C1& source, C2& destination)
{
    typedef typename C1::value_type source_type;
    typedef typename C2::value_type destination_type;
    destination.resize(source.size());
    std::transform(source.begin(), source.end(), destination.begin(), boost::lexical_cast<destination_type, source_type>);
}

template<typename T, typename T2>
std::vector<T>& operator<<(std::vector<T>& v, T2 t)
{
    v.push_back(T(t));
    return v;
}

main(int argc, char *argv[])
{   
    std::vector<std::string> v1;
    v1 << "11" << "22" << "33" << "44";
    std::cout << "vector<string>: ";
    std::copy(v1.begin(), v1.end(), std::ostream_iterator<std::string>(std::cout, ", "));
    std::cout << std::endl;

    std::vector<int> v2;
    castContainer(v1, v2);

    std::cout << "vector<int>: ";
    std::copy(v2.begin(), v2.end(), std::ostream_iterator<int>(std::cout, ", "));
    std::cout << std::endl;
}

There are two independent tasks.

  1. Convert a single string to an integer
  2. Having something that can convert from A to B, convert std::vector<A> to std::vector<B>

I suggest you try to do them separately, and then combine the results. If one of these tasks proves difficult, you will be able to ask a more focused question.

The most general way to convert strings to integers is with stringstream and a function template. You can optionally set the base for the conversion if you're dealing with hexadecimal. The boost library would also be helpful in your example.

#include <iostream>
#include <string>
#include <vector>

#include <sstream>
#include <stdexcept>
#include <boost/static_assert.hpp>
#include <boost/foreach.hpp>

/******************************************************************************
 * Handy string to type conversion
 * First parameter is the string to convert
 * Second optional parameter is the number base, e.g. std::hex
 * 
 * Because this is a function template, the compiler will instantiate one
 * instance of the function per type
 *****************************************************************************/
// the std::dec thingy is actually a function, so extra glue required.
typedef std::ios_base& (*ios_base_fn)( std::ios_base& str );
template <class T>
T strtotype( const std::string& s, ios_base_fn base = std::dec )
{
    // C++ can't convert 8-bit values, they are *always* treated
    // as characters. :(  At least warn the user.
    // this gives a cryptic error message, but better than nothing.
    BOOST_STATIC_ASSERT( sizeof(T) > 1 );

    T val;
    std::istringstream iss(s);
    iss >> base >> val;
    if( iss.fail() )
        throw std::runtime_error( "Error: strtotype(): Can't convert string '" + s + "' to numeric value" );
    return val;
}

using namespace std;

int main(int argc, char* argv[]) {

    vector<string> vectorOfStrings;
    vectorOfStrings.push_back("1");
    vectorOfStrings.push_back("2");
    vectorOfStrings.push_back("3");

    for (int i=0; i<vectorOfStrings.size(); i++)
    {
        cout<<vectorOfStrings.at(i)<<endl;
    }

    vector<int> vectorOfIntegers;

    for( size_t i = 0; i < vectorOfStrings.size(); i++ )
        vectorOfIntegers.push_back( strtotype<int>( vectorOfStrings[i] ));

    // or better yet, use boost_foreach
    BOOST_FOREACH( const string& s, vectorOfStrings )
        vectorOfIntegers.push_back( strtotype<int>( s ));

    int sum;
    for (int i=0; i<vectorOfIntegers.size(); i++)
    {
        sum += vectorOfIntegers.at(i);
    }
    cout<<sum<<endl;
    cin.get();

    return 0;
}

If you don't want or can't use boost, you can remove the sizeof() check in strtotype. However, be careful never to try to convert to strings to individual bytes. Doing so will fail silently by only converting the first nibble of the byte.

If you're suing GNU tools, then compile like so:

 g++ -Wall -O3 -I /path/to/boost/include main.cpp

or, if you delete the boost related bits:

 g++ -Wall -O3 main.cpp 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM