c++用什么方法把字符串(char *)解析成int?健壮和清晰的错误处理是一个加分项(而不是返回零)。
当前回答
c++ String工具箱库(StrTk)有以下解决方案:
static const std::size_t digit_table_symbol_count = 256;
static const unsigned char digit_table[digit_table_symbol_count] = {
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0xFF - 0x07
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0x08 - 0x0F
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0x10 - 0x17
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0x18 - 0x1F
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0x20 - 0x27
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0x28 - 0x2F
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, // 0x30 - 0x37
0x08, 0x09, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0x38 - 0x3F
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0x40 - 0x47
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0x48 - 0x4F
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0x50 - 0x57
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0x58 - 0x5F
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0x60 - 0x67
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0x68 - 0x6F
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0x70 - 0x77
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0x78 - 0x7F
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0x80 - 0x87
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0x88 - 0x8F
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0x90 - 0x97
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0x98 - 0x9F
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0xA0 - 0xA7
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0xA8 - 0xAF
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0xB0 - 0xB7
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0xB8 - 0xBF
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0xC0 - 0xC7
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0xC8 - 0xCF
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0xD0 - 0xD7
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0xD8 - 0xDF
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0xE0 - 0xE7
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0xE8 - 0xEF
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0xF0 - 0xF7
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF // 0xF8 - 0xFF
};
template<typename InputIterator, typename T>
inline bool string_to_signed_type_converter_impl_itr(InputIterator begin, InputIterator end, T& v)
{
if (0 == std::distance(begin,end))
return false;
v = 0;
InputIterator it = begin;
bool negative = false;
if ('+' == *it)
++it;
else if ('-' == *it)
{
++it;
negative = true;
}
if (end == it)
return false;
while(end != it)
{
const T digit = static_cast<T>(digit_table[static_cast<unsigned int>(*it++)]);
if (0xFF == digit)
return false;
v = (10 * v) + digit;
}
if (negative)
v *= -1;
return true;
}
InputIterator可以是unsigned char*、char*或std::string迭代器,T应该是signed int,例如signed int、int或long
其他回答
我喜欢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的一部分…
您可以使用Boost的lexical_cast,它将此包装在一个更通用的接口中。 lexical_cast<目标>(源)失败时抛出bad_lexical_cast。
你可以使用c++标准库中的a stringstream:
stringstream ss(str);
int x;
ss >> x;
if(ss) { // <-- error handling
// use x
} else {
// not a number
}
流状态将被设置为失败 当遇到非数字时 正在读取一个整数。
有关c++中错误处理和流的陷阱,请参阅流陷阱。
在C中,你可以使用int atoi (const char * str),
解析c字串str,将其内容解释为整数,该整数作为int类型的值返回。
我认为这三个环节可以概括:
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;
}