c++ atoi 设计与实现
http://www.cplusplus.com/reference/cstdlib/atoi/
转换一个string 为 数字
声明:
int atoi(const char* str);
解析传入的c-string 内容,并转换其内容为整数,最终结果,以int 的形式返回。
函数开始将丢弃尽可能多的空白字符(通过isspace判断),直到第一个非空白字符。之后,从这个字符开始,取一个可选的+或-符号,紧接着读取尽可能多的10进制数字,并转换为对应的数值。
该字符串可以在形成整数的字符之后包含其他额外的字符,额外的字符将被忽略。
如果第一个非空白字符不是数字或者+/-符号,或者,如果字符串为空,或者只包含了空白字符,不会执行任何的转换,最终将返回0
参数:
str: c-string ,以一个整数开始。
返回值
成功的话,函数以int形式返回被转换的整数。
如果值超过了int 表示的范围,其行为未定义。如果这种情况存在,参考strtol 的接口设计。
数据冲突
只会访问str 表示的数据
异常:
不会抛出异常。
如果str 不指向合法的c-string,或超出int 表示的范围,将导致未定义的行为。
strtol
http://www.cplusplus.com/reference/cstdlib/strtol/
long int strtol (const char* str, char** endptr, int base);
转换string 为long integer
以base 指定的进制转换str 指定的内容为数字,最终结果以long int 返回。
如果endptr 不为空,函数设置endptr 为该数字的最后一个字符的后一个字符。
函数首先跳过尽可能多的空格;依据base 指定的进制,取尽可能多的合法字符,并转换他们为数字;最后,endptr 指向第一个非法字符。
如果base 为0,语法类似于整数常量的语法,如下:
1. 可选的符号字符(+或-)
2. 可选的前缀,指示8、16进制(0或0x或0X)
3. 十进制数字序列(如果未指定基本前缀)或八进制或十六进制数字(如果存在特定前缀)
如果base 为[2,36],合法数字为'0'到 'z/Z'(36使用)。可能有+/-前缀,如果base 为16,可选的0x或者0X
参数
str
c-string 参数,包含要转换的数字内容
endptr
如果非空,包含转换的字符串的下一个字符串
base
进制。如果为0,将取决于str 的内容(10,8,16)
返回值
成功,以long int 返回转换得到的数字
如哦没有合法的转换,返回0,
如果超范围了,返回LONG_MAX或者 LONG_MIN,errno 被设置为ERANGE
数据竞争
str 指向的数组,如果endptr 非空,将被设置
异常
不主动抛出异常
如果str 指向非法c-string,或endptr 不指向合法对象,将产生未定义行为。
errno
https://en.cppreference.com/w/cpp/error/errno
errno 是一个用于错误处理的预定义宏,c++11 之前定义为静态函数,c++11开始定义为一个线程局部变量。
标准库中的一些函数,通过向errno 设置正整数来指示错误。通常,这些值是一些预定义的宏,定义在cerrno 中,以字符E 开始,之后有一些大写的字母或数字。
程序启动时,errno 被设置为0,尽管无论是否发生错误,都允许库函数将正整数写入errno,但库函数绝不会在errno 中存储0
c++ 的方式std::stoi
https://en.cppreference.com/w/cpp/string/basic_string/stol
//int std::stoi(const string & _Str, size_t * _Idx = nullptr, int _Base = 10)
//C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.28.29333\include\string
// sto* NARROW CONVERSIONS
inline int stoi(const string& _Str, size_t* _Idx = nullptr, int _Base = 10) {
// convert string to int
int& _Errno_ref = errno; // Nonzero cost, pay it once
const char* _Ptr = _Str.c_str();
char* _Eptr;
_Errno_ref = 0;
const long _Ans = _CSTD strtol(_Ptr, &_Eptr, _Base);
if (_Ptr == _Eptr) {
_Xinvalid_argument("invalid stoi argument");
}
if (_Errno_ref == ERANGE || _Ans < INT_MIN || INT_MAX < _Ans) {
_Xout_of_range("stoi argument out of range");
}
if (_Idx) {
*_Idx = static_cast<size_t>(_Eptr - _Ptr);
}
return static_cast<int>(_Ans);
}
stack over flow 上的一些讨论:
https://stackoverflow.com/questions/194465/how-to-parse-a-string-to-an-int-in-c
enum STR2INT_ERROR { SUCCESS, OVERFLOW, UNDERFLOW, INCONVERTIBLE };
STR2INT_ERROR str2int (int &i, char const *s, int base = 0)
{
char *end;
long l;
errno = 0;
l = strtol(s, &end, base);
if ((errno == ERANGE && l == LONG_MAX) || l > INT_MAX) {
return OVERFLOW;
}
if ((errno == ERANGE && l == LONG_MIN) || l < INT_MIN) {
return UNDERFLOW;
}
if (*s == '\0' || *end != '\0') {
return INCONVERTIBLE;
}
i = l;
return SUCCESS;
}
关于c++ 字符串转int 执行效率的一些讨论
https://tinodidriksen.com/2010/02/cpp-convert-string-to-int-speed/