【问题标题】:How can I convert a std::string to int?如何将 std::string 转换为 int?
【发布时间】:2011-12-01 14:22:04
【问题描述】:

我想将字符串转换为 int,我指的不是 ASCII 码。

为了快速了解一下,我们以字符串的形式传入一个方程。我们要将其分解,正确格式化并求解线性方程。现在,这么说,我无法将字符串转换为 int。

我知道该字符串将采用 (-5) 或 (25) 等格式,所以它绝对是一个 int。但是我们如何从字符串中提取它呢?

我想的一种方法是在字符串中运行一个 for/while 循环,检查一个数字,然后提取所有数字,然后查看是否有前导“-”,如果有,乘以整数 -1。

不过,对于这样一个小问题,它似乎有点过于复杂。有什么想法吗?

【问题讨论】:

标签: c++ string integer


【解决方案1】:

你可以使用std::stringstream,这是一个例子:

#include <iostream>
#include <sstream>
using namespace std;
string r;
int main() {
    cin >> r;
    stringstream tmp(r);
    int s;
    tmp >> s;
    cout << s;
    return 0;
}

【讨论】:

    【解决方案2】:

    可能的选项如下所述:

    1. sscanf()

        #include <cstdio>
        #include <string>
    
            int i;
            float f;
            double d;
            std::string str;
    
            // string -> integer
            if(sscanf(str.c_str(), "%d", &i) != 1)
                // error management
    
            // string -> float
            if(sscanf(str.c_str(), "%f", &f) != 1)
                // error management
        
            // string -> double 
            if(sscanf(str.c_str(), "%lf", &d) != 1)
                // error management
    

    这是一个错误(cppcheck 也显示),因为“在某些版本的 libc 上,没有字段宽度限制的 scanf 可能会因大量输入数据而崩溃”(请参阅 herehere) .

    2. std::sto()*

        #include <iostream>
        #include <string>
    
            int i;
            float f;
            double d;
            std::string str;
    
            try {
                // string -> integer
                int i = std::stoi(str);
    
                // string -> float
                float f = std::stof(str);
    
                // string -> double 
                double d = std::stod(str);
            } catch (...) {
                // error management
            }   
    

    此解决方案简短而优雅,但仅适用于兼容 C++11 的编译器。

    3.流

        #include <string>
        #include <sstream>
    
            int i;
            float f;
            double d;
            std::string str;
    
            // string -> integer
            std::istringstream ( str ) >> i;
    
            // string -> float
            std::istringstream ( str ) >> f;
    
            // string -> double 
            std::istringstream ( str ) >> d;
    
            // error management ??
    

    但是,使用此解决方案很难区分错误输入(请参阅here)。

    4. Boost 的 lexical_cast

        #include <boost/lexical_cast.hpp>
        #include <string>
    
            std::string str;
    
            try {
                int i = boost::lexical_cast<int>( str.c_str());
                float f = boost::lexical_cast<int>( str.c_str());
                double d = boost::lexical_cast<int>( str.c_str());
                } catch( boost::bad_lexical_cast const& ) {
                    // Error management
            }
    

    但是,这只是sstream 的包装,文档建议使用sstream 来更好地管理错误(请参阅here)。

    5. strto()*

    由于错误管理,这个解决方案很长,这里有描述。由于没有函数返回纯 int,因此在整数的情况下需要进行转换(请参阅 here 了解如何实现此转换)。

    6. Qt

        #include <QString>
        #include <string>
    
            bool ok;
            std::string;
    
            int i = QString::fromStdString(str).toInt(&ok);
            if (!ok)
                // Error management
        
            float f = QString::fromStdString(str).toFloat(&ok);
            if (!ok)
                // Error management 
    
            double d = QString::fromStdString(str).toDouble(&ok);
            if (!ok)
        // Error management     
        
    

    结论

    总结起来,最好的解决方案是 C++11 std::stoi(),或者,作为第二种选择,使用 Qt 库。不鼓励使用所有其他解决方案或存在错误。

    【讨论】:

    • 已修复。感谢您的报告。
    • 漂亮的总结,非常感谢。我是否可以建议添加一个初步评论,建议最终解决方案,以便只有对细节感兴趣的人才能继续阅读?
    • 这应该是公认的答案,你也忘记了(或者更确切地说应该添加因为它是旧答案)from_chars
    • 不要使用sscanf。这是一个 C API 函数,问题是关于 C++ 的。如果您打算使用sscanf,那么至少使用std::
    【解决方案3】:

    我认为从int 转换为std::string 或反之亦然需要一些特殊功能,例如std::stoi() 但是如果您需要将double 转换为string,请使用to_string()(不是 C#。C# 是 .ToString() 而不是 to_string())

    【讨论】:

    • std::stoi 已经在多个其他答案中提到,问题不是关于将双精度转换为字符串。
    • 正如目前所写,您的答案尚不清楚。请edit 添加其他详细信息,以帮助其他人了解这如何解决所提出的问题。你可以找到更多关于如何写好答案的信息in the help center
    【解决方案4】:
     int stringToInt(std::string value) {    
     if(value.length() == 0 ) return 0; //tu zmiana..
    
     if (value.find(  std::string("NULL") ) != std::string::npos) {
         return 0;
      }
     
      if (value.find(  std::string("null") ) != std::string::npos) {
         return 0;
      }
     
     
    int i;
    std::stringstream stream1;
    stream1.clear();
    stream1.str(value);
    stream1 >> i;
    return i;
    

    };

    【讨论】:

      【解决方案5】:

      为了更加详尽(正如 cmets 中所要求的那样),我使用 std::from_chars 添加了 C++17 给出的解决方案。

      std::string str = "10";
      int number;
      std::from_chars(str.data(), str.data()+str.size(), number);
      

      如果要检查是否转换成功:

      std::string str = "10";
      int number;
      auto [ptr, ec] = std::from_chars(str.data(), str.data()+str.size(), number);
      assert(ec == std::errc{});
      // ptr points to chars after read number
      

      此外,要比较所有这些解决方案的性能,请参阅以下快速基准链接:https://quick-bench.com/q/GBzK53Gc-YSWpEA9XskSZLU963Y

      std::from_chars 最快,std::istringstream 最慢)

      【讨论】:

        【解决方案6】:

        如果你没有硬编码:)

        bool strCanBeInt(std::string string){
            for (char n : string) {
                if (n != '0' && n != '1' && n != '2' && n != '3' && n != '4' && n != '5'
                    && n != '6' && n != '7' && n != '8' && n != '9') {
                    return false;
                }
            }
            return true;
        }
        
        int strToInt(std::string string) {
            int integer = 0;
            int numInt;
            for (char n : string) {
                if(n == '0') numInt = 0;
                if(n == '1') numInt = 1;
                if(n == '2') numInt = 2;
                if(n == '3') numInt = 3;
                if(n == '4') numInt = 4;
                if(n == '5') numInt = 5;
                if(n == '6') numInt = 6;
                if(n == '7') numInt = 7;
                if(n == '8') numInt = 8;
                if(n == '9') numInt = 9;
                if (integer){
                    integer *= 10;
                }
                integer += numInt;
            }
            return integer;
        }
        

        【讨论】:

        • 这不处理溢出或负数。第二个函数和atoi很像,不知道为什么要手写。此外,还有一些地方可以改进:不要按值传递字符串,更多地使用标准函数(第一个函数可以使用 std::all_of + std::isdigit 之类的东西重写)。
        【解决方案7】:

        我知道这个问题已经很老了,但我认为有更好的方法来解决这个问题

        #include <string>
        #include <sstream>
        
        bool string_to_int(std::string value, int * result) {
          std::stringstream stream1, stream2;
          std::string stringednumber;
          int tempnumber;
          stream1 << value;
          stream1 >> tempnumber;
          stream2 << tempnumber;
          stream2 >> stringednumber;
          if (!value.compare(stringednumber)) {
            *result = tempnumber;
            return true;
          }
          else return false;
        }
        

        如果我写的代码正确,这将返回一个布尔值,告诉你字符串是否为有效数字,如果为假,则不是数字,如果为真,则为数字并且该数字现在是结果,你可以这样称呼:

        std::string input;
        std::cin >> input;
        bool worked = string_to_int(input, &result);
        

        【讨论】:

          【解决方案8】:

          1。标准::stoi

          std::string str = "10";  
          int number = std::stoi(str); 
          

          2。字符串流

          std::string str = "10";  
          int number;  
          std::istringstream(str) >> number
          

          3。 boost::lexical_cast

          #include <boost/lexical_cast.hpp>
          std::string str = "10";  
          int number;
              
          try 
          {
              number = boost::lexical_cast<int>(str);
              std::cout << number << std::endl;
          }
          catch (boost::bad_lexical_cast const &e) // bad input
          {
              std::cout << "error" << std::endl;
          }
          

          4。 std::atoi

          std::string str = "10";
          int number = std::atoi(str.c_str()); 
          

          5。 sscanf()

           std::string str = "10";
           int number;
           if (sscanf(str .c_str(), "%d", &number) == 1) 
           {
               std::cout << number << '\n';
           } 
           else 
           {
               std::cout << "Bad Input";
           }
          

          【讨论】:

            【解决方案9】:

            要将字符串表示形式转换为整数值,我们可以使用std::stringstream。

            如果转换的值超出整数数据类型的范围,则返回 INT_MIN 或 INT_MAX。

            此外,如果字符串值不能表示为有效的 int 数据类型,则返回 0。

            #include 
            #include 
            #include 
            
            int main() {
            
                std::string x = "50";
                int y;
                std::istringstream(x) >> y;
                std::cout << y << '\n';
                return 0;
            }
            

            输出: 50

            根据上面的输出,我们可以看到它从字符串数字转换为整数。

            来源和更多信息string to int c++

            【讨论】:

              【解决方案10】:
              ll toll(string a){
                  ll ret=0;
                  bool minus=false;
                  for(auto i:a){
                      if(i=='-'){ minus=true; continue; }
                      ret*=10;
                      ret+=(i-'0');
                  } if(minus) ret*=-1;
                  return ret;
                  # ll is defined as, #define ll long long int
                  # usage: ll a = toll(string("-1234"));
              }
              

              【讨论】:

                【解决方案11】:

                我的代码:

                #include <iostream>
                using namespace std;
                
                int main()
                {
                    string s="32";  //String
                    int n=stoi(s);  //Convert to int
                    cout << n + 1 << endl;
                
                    return 0;
                }
                

                【讨论】:

                  【解决方案12】:

                  来自http://www.cplusplus.com/reference/string/stoi/

                  // stoi example
                  #include <iostream>   // std::cout
                  #include <string>     // std::string, std::stoi
                  
                  int main ()
                  {
                    std::string str_dec = "2001, A Space Odyssey";
                    std::string str_hex = "40c3";
                    std::string str_bin = "-10010110001";
                    std::string str_auto = "0x7f";
                  
                    std::string::size_type sz;   // alias of size_t
                  
                    int i_dec = std::stoi (str_dec,&sz);
                    int i_hex = std::stoi (str_hex,nullptr,16);
                    int i_bin = std::stoi (str_bin,nullptr,2);
                    int i_auto = std::stoi (str_auto,nullptr,0);
                  
                    std::cout << str_dec << ": " << i_dec << " and [" << str_dec.substr(sz) << "]\n";
                    std::cout << str_hex << ": " << i_hex << '\n';
                    std::cout << str_bin << ": " << i_bin << '\n';
                    std::cout << str_auto << ": " << i_auto << '\n';
                  
                    return 0;
                  }
                  

                  输出:

                  2001,太空漫游:2001 和 [,太空漫游]

                  40c3: 16579

                  -10010110001:-1201

                  0x7f: 127

                  【讨论】:

                    【解决方案13】:

                    单行版本:long n = strtol(s.c_str(), NULL, base);

                    s 是字符串,baseint,例如 2、8、10、16。)

                    strtol的更多详情可以参考this link


                    核心思想是使用strtol函数,包含在cstdlib中。

                    由于strtol 只处理char 数组,我们需要将string 转换为char 数组。可以参考this link

                    一个例子:

                    #include <iostream>
                    #include <string>   // string type
                    #include <bitset>   // bitset type used in the output
                    
                    int main(){
                        s = "1111000001011010";
                        long t = strtol(s.c_str(), NULL, 2); // 2 is the base which parse the string
                    
                        cout << s << endl;
                        cout << t << endl;
                        cout << hex << t << endl;
                        cout << bitset<16> (t) << endl;
                    
                        return 0;
                    }
                    

                    将输出:

                    1111000001011010
                    61530
                    f05a
                    1111000001011010
                    

                    【讨论】:

                      【解决方案14】:

                      嗯,很多答案,很多可能性。我在这里缺少的是一些通用方法,可以将字符串转换为不同的 C++ 整数类型(short、int、long、bool、...)。 我想出了以下解决方案:

                      #include<sstream>
                      #include<exception>
                      #include<string>
                      #include<type_traits>
                      
                      using namespace std;
                      
                      template<typename T>
                      T toIntegralType(const string &str) {
                          static_assert(is_integral<T>::value, "Integral type required.");
                          T ret;
                          stringstream ss(str);
                          ss >> ret;
                          if ( to_string(ret) != str)
                              throw invalid_argument("Can't convert " + str);
                          return ret;
                      }
                      

                      以下是使用示例:

                      string str = "123";
                      int x = toIntegralType<int>(str); // x = 123
                      
                      str = "123a";
                      x = toIntegralType<int>(str); // throws exception, because "123a" is not int
                      
                      str = "1";
                      bool y = toIntegralType<bool>(str); // y is true
                      str = "0";
                      y = toIntegralType<bool>(str); // y is false
                      str = "00";
                      y = toIntegralType<bool>(str); // throws exception
                      

                      为什么不直接使用 stringstream 输出运算符将字符串转换为整数类型? 这是答案: 假设一个字符串包含一个超出预期整数类型限制的值。例如,在 Wndows 64 上,最大 int 为 2147483647。 让我们为字符串分配一个值 max int + 1:string str = "2147483648"。 现在,将字符串转换为 int 时:

                      stringstream ss(str);
                      int x;
                      ss >> x;
                      

                      x 变成 2147483647,这绝对是一个错误:字符串“2147483648”不应该转换为 int 2147483647。提供的函数 toIntegralType 发现此类错误并引发异常。

                      【讨论】:

                        【解决方案15】:

                        Boost.Lexical_cast 呢?

                        这是他们的例子:

                        以下示例将命令行参数视为数字数据序列:

                        int main(int argc, char * argv[])
                        {
                            using boost::lexical_cast;
                            using boost::bad_lexical_cast;
                        
                            std::vector<short> args;
                        
                            while(*++argv)
                            {
                                try
                                {
                                    args.push_back(lexical_cast<short>(*argv));
                                }
                                catch(bad_lexical_cast &)
                                {
                                    args.push_back(0);
                                }
                            }
                            ...
                        }
                        

                        【讨论】:

                        • 链接已损坏。你能解决它吗?
                        【解决方案16】:

                        这可能有点矫枉过正,但是 boost::lexical_cast&lt;int&gt;( theString )应该去工作 很好。

                        【讨论】:

                        • 一个错字。它应该只是boost::lexical_cast&lt;int&gt;( theString )(其中theString 是包含要转换为int 的字符串的变量的名称)。
                        【解决方案17】:

                        在 Windows 中,您可以使用:

                        const std::wstring hex = L"0x13";
                        const std::wstring dec = L"19";
                        
                        int ret;
                        if (StrToIntEx(hex.c_str(), STIF_SUPPORT_HEX, &ret)) {
                            std::cout << ret << "\n";
                        }
                        if (StrToIntEx(dec.c_str(), STIF_SUPPORT_HEX, &ret)) {
                            std::cout << ret << "\n";
                        }
                        

                        strtol,stringstream如果需要解释十六进制,需要指定基数。

                        【讨论】:

                          【解决方案18】:

                          在 C++11 中,有一些不错的新函数将 std::string 转换为数字类型。

                          所以不是

                          atoi( str.c_str() )
                          

                          你可以使用

                          std::stoi( str )
                          

                          其中str 是您的号码std::string

                          所有类型的数字都有版本: long stol(string), float stof(string), double stod(string),... 见http://en.cppreference.com/w/cpp/string/basic_string/stol

                          【讨论】:

                          • 有关 std::stoi 的问题,请参阅 stackoverflow.com/a/6154614/195527 :它将 "11x" 转换为整数 11
                          • #include /* atoi */
                          • @CC 这也是 atoi 的行为:cplusplus.com/reference/cstdlib/atoi "字符串可以在构成整数的字符之后包含其他字符,这些字符将被忽略并且不会影响此函数的行为。"
                          • 你介意用 C++17 中的from_chars 更新这个答案吗?它应该比stoi 快几个数量级。
                          • stoi 应该是首选。见Why shouldn't I use atoi()?
                          【解决方案19】:

                          还有另一种简单的方法:假设您有一个像 c='4' 这样的角色,因此您可以执行以下步骤之一:

                          第一个:int q

                          q=(int) c ; (q is now 52 in ascii table ) . q=q-48; remember that adding 48 to digits is their ascii code .

                          第二种方式:

                          q=c-'0'; the same , character '0' means 48

                          【讨论】:

                          • 问题是关于从string 转换为int 而不是从char 转换为string
                          • 有问题且与问题不匹配
                          【解决方案20】:

                          使用atoi函数将字符串转换为整数:

                          string a = "25";
                          
                          int b = atoi(a.c_str());
                          

                          http://www.cplusplus.com/reference/clibrary/cstdlib/atoi/

                          【讨论】:

                          • 永远不要使用atoistrtol 做所有atoi 做的事情,但更好,并且安全失败。
                          • 扩展@BenVoigt 的评论:避免atoi 的一个重要原因是它仅通过返回0 来报告转换失败! atoi 与其说是不安全地失败,不如说是默默地失败
                          • @VainsteinK:返回0 会报告一些故障。其他人使用atoi 导致未定义的行为。这使得它对于验证不受信任的输入毫无用处。 wiki.sei.cmu.edu/confluence/display/c/…
                          【解决方案21】:

                          诚然,我的解决方案不适用于负整数,但它会从包含整数的输入文本中提取所有正整数。它使用numeric_only locale:

                          int main() {
                                  int num;
                                  std::cin.imbue(std::locale(std::locale(), new numeric_only()));
                                  while ( std::cin >> num)
                                       std::cout << num << std::endl;
                                  return 0;
                          }
                          

                          输入文字:

                           the format (-5) or (25) etc... some text.. and then.. 7987...78hjh.hhjg9878
                          

                          输出整数:

                           5
                          25
                          7987
                          78
                          9878
                          

                          numeric_only 类定义为:

                          struct numeric_only: std::ctype<char> 
                          {
                              numeric_only(): std::ctype<char>(get_table()) {}
                          
                              static std::ctype_base::mask const* get_table()
                              {
                                  static std::vector<std::ctype_base::mask> 
                                      rc(std::ctype<char>::table_size,std::ctype_base::space);
                          
                                  std::fill(&rc['0'], &rc[':'], std::ctype_base::digit);
                                  return &rc[0];
                              }
                          };
                          

                          完整的在线演示:http://ideone.com/dRWSj

                          【讨论】:

                            【解决方案22】:

                            atoi 是一个将字符串转换为整数的内置函数,假设字符串以整数表示形式开头。

                            http://www.cplusplus.com/reference/clibrary/cstdlib/atoi/

                            【讨论】:

                            • 任何时候想到atoi,请改用strtol
                            【解决方案23】:
                            std::istringstream ss(thestring);
                            ss >> thevalue;
                            

                            为了完全正确,您需要检查错误标志。

                            【讨论】:

                            • 这不会从(-5)中提取-5
                            • @Nawaz,括号是否真的存在,或者这就是 OP 展示他的字符串的方式?
                            • 我不知道。我只是指出这种方法的局限性。
                            • @Nawaz,它也不能对输入“WERWER”进行操作。我不认为括号实际上是他实际字符串的一部分,而且我不认为我不解析它们的事实是相关的。
                            • @Nawaz,好吧...我不这么认为,但我知道你怎么能这样做。
                            猜你喜欢
                            • 2011-06-07
                            • 1970-01-01
                            • 1970-01-01
                            • 1970-01-01
                            • 2015-01-07
                            • 2010-11-04
                            • 2016-01-28
                            相关资源
                            最近更新 更多