将字符范围转换为 int
Converting a character range to int
假设我们有一个字符范围:
// For example
const char *valueBegin="123blahblah"; // Beginning of value
const char *valueEnd=valueBegin+3; // One past end of value
...,我想把它转换成一个整数:
int value=...// Given valueBegin and valueEnd, calculate
// the number stored starting at valueBegin
有哪些好的 C++11 方法可以做到这一点?
显然你可以创建一个 std::string
并使用 stoi
,或者将它复制到一个临时的以 NUL 结尾的字符数组,然后就很容易了(例如,通过 atoi
或 strtol
).
考虑一种不涉及将字符复制到某个临时文件的方法 array/object - 换句话说,一种可以就地处理字符数据的函数。
更新:
很多答案,但请先思考再回答。该范围未 NUL
终止,因此需要 valueEnd
。你不知道什么超出了值(即,可能 valueEnd 超出了包含该值的缓冲区),所以如果你的答案没有使用 valueEnd
,那是错误的。此外,如果您的答案创建了一个临时 std::string
对象,则它不在该问题的指导范围内。
std::cout << boost::lexical_cast<int>(sBegin, 3) << std::endl;
这不会创建任何临时文件并支持任何类型的字符范围。也挺fast.
如果你想避免使用长度说明符,那么你可以使用 boost::iterator_range
:
std::cout << boost::lexical_cast<int>(boost::make_iterator_range(begin, end)) << std::endl;
没有任何错误检查,这看起来很简单。
int number = 0;
for ( char* cp = valueBegin; cp != valueEnd; ++cp )
{
number += number*10 + (cp-'0');
}
如果您需要停在第一个非数字,
int number = 0;
for ( char* cp = valueBegin; cp != valueEnd && isdigit(*cp); ++cp )
{
number += number*10 + (cp-'0');
}
如果您需要能够提取负数并能够优雅地处理前导 +/-
符号,代码将变得稍微复杂一些。
int number = 0;
char* cp = valueBegin;
int sign = 1;
if ( *cp == '-' )
{
sign = -1;
++cp;
}
if ( *cp == '+' )
{
++cp;
}
for ( ; cp != valueEnd && isdigit(*cp); ++cp )
{
number += number*10 + (cp-'0');
}
number *= sign;
如果您不想使用 Boost 并且不介意将数字复制到临时字符串,您可以使用 std::stoi
:
std::cout << std::stoi(std::string(valueBegin, valueEnd)) << std::endl;
还有其他适用于不同数字类型的转换器 - stol
、stoul
、stoll
、stoull
、stof
、stod
, stold
.
这些在 C++11 中定义。
(就个人而言,我会选择 Boost 选项,但有些人可能不想要额外的依赖项。)
假设我们有一个字符范围:
// For example
const char *valueBegin="123blahblah"; // Beginning of value
const char *valueEnd=valueBegin+3; // One past end of value
...,我想把它转换成一个整数:
int value=...// Given valueBegin and valueEnd, calculate
// the number stored starting at valueBegin
有哪些好的 C++11 方法可以做到这一点?
显然你可以创建一个 std::string
并使用 stoi
,或者将它复制到一个临时的以 NUL 结尾的字符数组,然后就很容易了(例如,通过 atoi
或 strtol
).
考虑一种不涉及将字符复制到某个临时文件的方法 array/object - 换句话说,一种可以就地处理字符数据的函数。
更新:
很多答案,但请先思考再回答。该范围未 NUL
终止,因此需要 valueEnd
。你不知道什么超出了值(即,可能 valueEnd 超出了包含该值的缓冲区),所以如果你的答案没有使用 valueEnd
,那是错误的。此外,如果您的答案创建了一个临时 std::string
对象,则它不在该问题的指导范围内。
std::cout << boost::lexical_cast<int>(sBegin, 3) << std::endl;
这不会创建任何临时文件并支持任何类型的字符范围。也挺fast.
如果你想避免使用长度说明符,那么你可以使用 boost::iterator_range
:
std::cout << boost::lexical_cast<int>(boost::make_iterator_range(begin, end)) << std::endl;
没有任何错误检查,这看起来很简单。
int number = 0;
for ( char* cp = valueBegin; cp != valueEnd; ++cp )
{
number += number*10 + (cp-'0');
}
如果您需要停在第一个非数字,
int number = 0;
for ( char* cp = valueBegin; cp != valueEnd && isdigit(*cp); ++cp )
{
number += number*10 + (cp-'0');
}
如果您需要能够提取负数并能够优雅地处理前导 +/-
符号,代码将变得稍微复杂一些。
int number = 0;
char* cp = valueBegin;
int sign = 1;
if ( *cp == '-' )
{
sign = -1;
++cp;
}
if ( *cp == '+' )
{
++cp;
}
for ( ; cp != valueEnd && isdigit(*cp); ++cp )
{
number += number*10 + (cp-'0');
}
number *= sign;
如果您不想使用 Boost 并且不介意将数字复制到临时字符串,您可以使用 std::stoi
:
std::cout << std::stoi(std::string(valueBegin, valueEnd)) << std::endl;
还有其他适用于不同数字类型的转换器 - stol
、stoul
、stoll
、stoull
、stof
、stod
, stold
.
这些在 C++11 中定义。
(就个人而言,我会选择 Boost 选项,但有些人可能不想要额外的依赖项。)