【问题标题】:c++ parse int from string [duplicate]c ++从字符串解析int [重复]
【发布时间】:2011-05-25 11:12:44
【问题描述】:

可能重复:
How to parse a string to an int in C++?

我做了一些研究,有些人说要使用 atio,有些人说它不好,反正我无法让它工作。

所以我只想问清楚,将字符串转换为 int 的正确方法是什么。

string s = "10";
int i = s....?

谢谢!

【问题讨论】:

  • 你的意思可能是 (std::)string s = "10"
  • @lijie - 也许,但我从来没有在我的代码中这么说......我应该是吗?
  • @adam - 嗯,看起来不错的解决方案,不幸的是,谷歌上没有出现 stackoverflow 结果,我在输入问题时没有看到这些结果。
  • @kralco626:我的意思是引号。你想把字符串“10”转换成整数10,对吧?

标签: c++ string int


【解决方案1】:
  • 在 C++11 中,使用 std::stoi 作为:

     std::string s = "10";
     int i = std::stoi(s);
    

    注意std::stoi会抛出std::invalid_argument类型的异常,如果转换不能执行,或者std::out_of_range如果转换导致溢出(即当字符串值对于int类型来说太大时)。您可以使用std::stolstd:stoll,但如果int 对于输入字符串来说似乎太小。

  • 在 C++03/98 中,可以使用以下任何一种:

     std::string s = "10";
     int i;
    
     //approach one
     std::istringstream(s) >> i; //i is 10 after this
    
     //approach two
     sscanf(s.c_str(), "%d", &i); //i is 10 after this
    

请注意,上述两种方法对于输入 s = "10jh" 会失败。他们将返回 10 而不是通知错误。因此,安全可靠的方法是编写自己的函数来解析输入字符串,并验证每个字符以检查它是否为数字,然后相应地工作。这是一个强大的实现(虽然未经测试):

int to_int(char const *s)
{
     if ( s == NULL || *s == '\0' )
        throw std::invalid_argument("null or empty string argument");

     bool negate = (s[0] == '-');
     if ( *s == '+' || *s == '-' ) 
         ++s;

     if ( *s == '\0')
        throw std::invalid_argument("sign character only.");

     int result = 0;
     while(*s)
     {
          if ( *s < '0' || *s > '9' )
            throw std::invalid_argument("invalid input string");
          result = result * 10  - (*s - '0');  //assume negative number
          ++s;
     }
     return negate ? result : -result; //-result is positive!
} 

这个解决方案是my another solution的略微修改版本。

【讨论】:

  • 一般我会避免在用户提供的输入中使用atoi,因为当你得到一个0时,你不知道是因为字符串包含"0"还是因为它是无效。
  • Atoi 和 itoa 经常引起问题,所以我建议避免使用这些函数。我会改用 boost 或 stringstream。
  • 非常适合快速项目,因为它很简单
  • 是的,Java 为此类常见任务提供了强大的库。但是您的 Java 示例是错误的 - 您不应该为字符串文字分配新实例。
  • 呃什么?在 C# 中,你会写 int.Parse("10")(或使用 TryParse 来避免异常)
【解决方案2】:

您可以使用istringstream

string s = "10";

// create an input stream with your string.
istringstream is(str);

int i;
// use is like an input stream
is >> i;

【讨论】:

    【解决方案3】:

    你可以使用boost::lexical_cast:

    #include <iostream>
    #include <boost/lexical_cast.hpp>
    
    int main( int argc, char* argv[] ){
    std::string s1 = "10";
    std::string s2 = "abc";
    int i;
    
       try   {
          i = boost::lexical_cast<int>( s1 );
       }
       catch( boost::bad_lexical_cast & e ){
          std::cout << "Exception caught : " << e.what() << std::endl;
       }
    
       try   {
          i = boost::lexical_cast<int>( s2 );
       }
       catch( boost::bad_lexical_cast & e ){
          std::cout << "Exception caught : " << e.what() << std::endl;
       }
    
       return 0;
    }
    

    【讨论】:

    • boost lexical_cast 非常非常非常慢。他们还认为它需要异常处理,这使得它使用起来更加麻烦。仅适用于以用户速度输入的输入,仅此而已。
    • @dman:确实 lexical_cast 比 atoi/strtol/sscanf 慢,但是 1) OP 没有询问最快的方法(并且问题标记为 c++)2) lexical_cast 是通用解决方案并且是其中的一部分Boost 可以告诉你一些关于实现质量的事情 3) bad_lexical_cast 异常为你提供了一种检测转换错误的方法,为正确的错误处理付出了很小的代价 4) 如果 lexical_cast 是你的瓶颈,那么很容易为你实现一个专业化数据类型
    • 对此+1。我喜欢你的论点,我实际上喜欢这个解决方案。作为一个 Java 人,我喜欢 try catch 并且将来可能会使用这个解决方案。
    【解决方案4】:

    没有“正确的方法”。如果您想要一个通用(但次优)的解决方案,您可以使用boost::lexical cast

    C++ 的一个常见解决方案是使用std::ostream&lt;&lt; operator。您可以使用stringstreamstringstream::str() 方法转换为字符串。

    如果您确实需要快速机制(记住 20/80 规则),您可以寻找“专用”解决方案,例如 C++ String Toolkit Library

    最好的问候,
    马辛

    【讨论】:

    • "没有'正确的方法'" - 你必须喜欢一种没有“正确方法”来解析字符串的语言...... :(
    【解决方案5】:

    一些方便的快速功能(如果您不使用 Boost):

    template<typename T>
    std::string ToString(const T& v)
    {
        std::ostringstream ss;
        ss << v;
        return ss.str();
    }
    
    template<typename T>
    T FromString(const std::string& str)
    {
        std::istringstream ss(str);
        T ret;
        ss >> ret;
        return ret;
    }
    

    例子:

    int i = FromString<int>(s);
    std::string str = ToString(i);
    

    适用于任何可流式传输的类型(浮点数等)。您需要#include &lt;sstream&gt;,可能还需要#include &lt;string&gt;

    【讨论】:

    • 这是 boost::lexical_cast 使用的解决方案
    • Actualla boost::lexical_cast 不使用原始的标准字符串流,而是一些经过调整的流类,应该使它比这些函数快一点。它还包括错误检查(包括检查输入是否被提取操作符完全使用),因此使用起来比这两个函数安全得多。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-08-12
    • 2016-06-29
    • 2023-03-15
    • 1970-01-01
    • 2017-09-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多