【问题标题】:How do I convert vector of strings into vector of integers in C++?如何在 C++ 中将字符串向量转换为整数向量?
【发布时间】:2011-10-31 14:58:24
【问题描述】:

我有一个字符串向量。需要帮助弄清楚如何将其转换为整数向量,以便能够在算术上使用它。谢谢!

#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;
}

【问题讨论】:

    标签: c++ string vector


    【解决方案1】:

    怎么样:

    #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>);
    }
    

    它可以将vector转换为vector,也可以将其他container转换为container2,例如:list -> list。

    完整代码:

    #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;
    }
    

    【讨论】:

      【解决方案2】:

      将字符串转换为整数的最通用方法是使用 stringstream 和函数模板。如果您正在处理十六进制,您可以选择设置转换的基数。 boost 库在您的示例中也很有帮助。

      #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;
      }
      

      如果你不想或不能使用 boost,你可以去掉 strtotype 中的 sizeof() 检查。但是,请注意不要尝试将字符串转换为单个字节。这样做会因为只转换字节的第一个半字节而静默失败。

      如果你使用 GNU 工具,那么编译如下:

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

      或者,如果您删除了与升压相关的位:

       g++ -Wall -O3 main.cpp 
      

      【讨论】:

        【解决方案3】:

        使用boost::lexical_cast。并用try-catch 块包围它。

        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 
        }
        

        或者你可以使用Boost.Spirit解析器(someone claims is faster甚至比atoi())作为:

        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
        

        使用您的代码的完整演示:http://ideone.com/DddL7

        【讨论】:

        • 我确信 OP 假定为十进制,但对我来说,lexical_cast 缺乏十六进制支持限制了它的用处。
        • @srking:lexical_cast 缺少十六进制支持是什么意思?
        • 例如看这个:stackoverflow.com/questions/1070497/… 确实,lexical_cast("0x10") 咳嗽了一个毛球。
        【解决方案4】:

        这是使用上述 cmets 组成的工作版本。

        #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;
        }
        

        【讨论】:

          【解决方案5】:
          #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);
          
              // ..
          }
          

          您可以将 stringToInteger(..) 的实现替换为您喜欢的转换函数。

          【讨论】:

            【解决方案6】:

            有两个独立的任务。

            1. 将单个字符串转换为整数
            2. 有可以从 A 转换为 B 的东西,将 std::vector&lt;A&gt; 转换为 std::vector&lt;B&gt;

            我建议你尝试分开做,然后结合结果。如果其中一项任务被证明很困难,您将能够提出一个更有针对性的问题。

            【讨论】:

              【解决方案7】:

              有多种方法可以将字符串转换为 int。

              解决方案 1:使用旧版 C 功能

              int main()
              {
                  //char hello[5];     
                  //hello = "12345";   --->This wont compile
              
                  char hello[] = "12345";
              
                  Printf("My number is: %d", atoi(hello)); 
              
                  return 0;
              }
              

              解决方案 2:使用 lexical_cast(最合适且最简单)

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

              包围try-catch 以捕获异常。

              解决方案 3:使用 C++ Streams

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

              【讨论】:

              • std::stringstream 仍然可能失败,即使您检查 if(!str) : ideone.com/YjNY2 。也就是else还是失败了!
              • @Nawaz:这不是失败;流中只剩下一些数据。
              • 如果必须转换 整个 输入才能将转换视为成功,请检查 str.str().empty()(而 str 对于 stringstream 来说是一个非常糟糕的名称对象!)
              • @Tomalak:如果不是失败,那你怎么称呼它? std::stringstream 转换失败或有问题正确报告给你!
              • @Nawaz:在 C++ 中,格式化提取不需要消耗 整个 字符串缓冲区才能被视为成功。否则,一般的顺序解析会相当困难!
              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2016-05-03
              • 2020-02-27
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2019-10-26
              • 1970-01-01
              相关资源
              最近更新 更多