c++用什么方法把字符串(char *)解析成int?健壮和清晰的错误处理是一个加分项(而不是返回零)。


当前回答

从c++ 17开始,你可以从<charconv>头文件中使用std::from_chars。

例如:

#include <iostream>
#include <charconv>
#include <array>

int main()
{
    char const * str = "42";
    int value = 0;

    std::from_chars_result result = std::from_chars(std::begin(str), std::end(str), value);

    if(result.error == std::errc::invalid_argument)
    {
      std::cout << "Error, invalid format";
    }
    else if(result.error == std::errc::result_out_of_range)
    {
      std::cout << "Error, value too big for int range";
    }
    else
    {
      std::cout << "Success: " << result;
    }
}

另外,它还可以处理其他进制,比如十六进制。

其他回答

我认为这三个环节可以概括:

http://tinodidriksen.com/2010/02/07/cpp-convert-int-to-string-speed/ http://tinodidriksen.com/2010/02/16/cpp-convert-string-to-int-speed/ http://www.fastformat.org/performance.html

Stringstream和lexical_cast解决方案与lexical cast使用Stringstream大致相同。

词汇强制转换的一些专门化使用不同的方法,请参阅http://www.boost.org/doc/libs/release/boost/lexical_cast.hpp了解详细信息。整数和浮点数现在专门用于整型到字符串的转换。

可以根据自己的需要专门化lexical_cast,并使其快速运行。这将是让各方满意的最终解决方案,干净而简单。

前面提到的文章展示了转换整数<->字符串的不同方法之间的比较。以下方法是有意义的:旧c-way,精神。Karma, fastformat,简单的循环。

Lexical_cast在某些情况下是可以的,例如int到字符串的转换。

使用词法强制转换将字符串转换为int不是一个好主意,因为它比atoi慢10-40倍,这取决于所使用的平台/编译器。

karma似乎是将整数转换为字符串的最快的库。

ex.: generate(ptr_char, int_, integer_number);

上面文章中提到的基本简单循环是将字符串转换为int的最快方法,显然不是最安全的方法,strtol()似乎是更安全的解决方案

int naive_char_2_int(const char *p) {
    int x = 0;
    bool neg = false;
    if (*p == '-') {
        neg = true;
        ++p;
    }
    while (*p >= '0' && *p <= '9') {
        x = (x*10) + (*p - '0');
        ++p;
    }
    if (neg) {
        x = -x;
    }
    return x;
}

您可以使用Boost的lexical_cast,它将此包装在一个更通用的接口中。 lexical_cast<目标>(源)失败时抛出bad_lexical_cast。

如果你有c++ 11,现在合适的解决方案是<string>中的c++整数转换函数:stoi, stol, stoul, stoll, stoull。当给出不正确的输入时,它们会抛出适当的异常,并在底层使用快速和小型的strto*函数。

如果您被c++的早期版本所困扰,那么在实现中模拟这些函数将是向前可移植的。

我喜欢Dan Moulding的回答,我将添加一点c++风格:

#include <cstdlib>
#include <cerrno>
#include <climits>
#include <stdexcept>

int to_int(const std::string &s, int base = 0)
{
    char *end;
    errno = 0;
    long result = std::strtol(s.c_str(), &end, base);
    if (errno == ERANGE || result > INT_MAX || result < INT_MIN)
        throw std::out_of_range("toint: string is out of range");
    if (s.length() == 0 || *end != '\0')
        throw std::invalid_argument("toint: invalid string");
    return result;
}

通过隐式转换,它对std::string和const char*都有效。它也适用于基转换,例如,所有to_int("0x7b")和to_int("0173")和to_int("01111011", 2)和to_int("0000007B", 16)和to_int("11120", 3)和to_int("3L", 34);返回123。

与std::stoi不同,它可以在pre- c++ 11中工作。也不像std::stoi, boost::lexical_cast和stringstream,它会抛出奇怪的字符串异常,比如“123hohoho”。

注意:此函数允许前导空格,但不允许尾随空格,即to_int("123 ")返回123,而to_int("123 ")抛出异常。确保这对于您的用例是可接受的,或者调整代码。

这样的功能可能是STL的一部分…

传统的C方式仍然有效。我推荐散步或散步。在返回状态和'endPtr'之间,您可以给出良好的诊断输出。它还可以很好地处理多个碱基。