C中,数字字符串以char[]形式定义。
相关api见《c++中数字与string转换》
#include
atoi --- 转int
atod --- 转double
strtod --- 转double
strtol --- 转long
四兄弟的工作原理都可以用相似的语言描述:
函数会扫描参数 nptr字符串,跳过前面的空白字符等,直到遇上数字或正负符号才开始做转换,再遇到非数字或字符串结束时('\0')结束转换。
去空白,留正负,存数字。
四兄弟中,strtod和strtol双胞胎的特殊之处在于:
它们的参数含2个指针,第二个指针返回扫描结束的位置的指针。
int atoi(const char *nptr);
double atof(const char *nptr);
long int strtol(const char *nptr,char **endptr,int base);
double strtod(const char *nptr,char **endptr);
2.1 atoi
int Atoi(const char *pstr)
{
int sign = 1;
int num = 0;
while (*pstr == ' ' || *pstr == '\t') //原文是'/t'有误
{
pstr++;
}
if (*pstr == '-')
{
sign = -1;
pstr++;
}
while (*pstr)
{
if (*pstr >= '0' && *pstr <= '9')
{
num = 10 * num + *pstr - '0';
}
else
{
return num * sign;
}
pstr++;
}
return (num * sign);
}
2.2 atof
double Atof(const char *pstr)
{
double sign = 1.0;
double num1 = 0.0;
double num2 = 0.0;
double point = 0.1;
while (*pstr == ' ' || *pstr == '/t')
{
pstr++;
}
if (*pstr == '-')
{
sign = -1;
pstr++;
}
while (*pstr)
{
if (*pstr == '.')
{
pstr++;
while (*pstr >= '0' && *pstr <= '9')
{
num1 += point * (*pstr - '0');
point *= 0.1;
pstr++;
}
}
else if (*pstr >= '0' && *pstr <= '9')
{
num2 = num2 * 10 + *pstr -'0';
}
else
{
return (num1 + num2) * (sign);
}
pstr++;
}
return (num1 + num2) * (sign);
}
2.3 strtol
#define TOLOWER(x) ((x) | 0x20)
#define isxdigit(c) (('0' <= (c) && (c) <= '9') /
|| ('a' <= (c) && (c) <= 'f') /
|| ('A' <= (c) && (c) <= 'F'))
#define isdigit(c) ('0' <= (c) && (c) <= '9')
unsigned long strtoul(const char *cp,char **endp,unsigned int base)
{
unsigned long result = 0,value;
if (!base) {
base = 10;
if (*cp == '0') {
base = 8;
cp++;
if ((TOLOWER(*cp) == 'x') && isxdigit(cp[1])) {
cp++;
base = 16;
}
}
} else if (base == 16) {
if (cp[0] == '0' && TOLOWER(cp[1]) == 'x')
cp += 2;
}
while (isxdigit(*cp) &&
(value = isdigit(*cp) ? *cp-'0' : TOLOWER(*cp)-'a'+10) < base) {
result = result*base + value;
cp++;
}
if (endp)
*endp = (char *)cp;
return result;
}
long strtol(const char *cp,char **endp,unsigned int base)
{
if(*cp=='-')
return -strtoul(cp+1,endp,base);
return strtoul(cp,endp,base);
}
2.4 strtod
double Strtod(char *str, char **endstr){
double num1 = 0.0;
double num2 = 0.0;
double point = 0.1;
int sign = 1;
int len = strlen(str) + 1;
*endstr = new char[len];
memset(*endstr, 0, len);
if (*str == '-')
{
sign = -1;
++str;
}
if (!isdigit(*str))
{
strcpy(*endstr, str);
return 0.0;
}
while (*str && isdigit(*str))
{
if (*str == '.')
{
++str;
while (*str && isdigit(*str))
{
num2 += point * ((*str) - '0');
point *= 0.1;
++str;
}
strcpy(*endstr, str);
break;
}
else
{
num1 = 10 * num1 + *str - '0';
str++;
if (!*str || !isdigit(*str))
{
strcpy(*endstr, str);
break;
}
}
}
return (num1 + num2) * sign;
}
{
double num1 = 0.0;
double num2 = 0.0;
double point = 0.1;
int sign = 1;
int len = strlen(str) + 1;
*endstr = new char[len];
memset(*endstr, 0, len);
if (*str == '-')
{
sign = -1;
++str;
}
if (!isdigit(*str))
{
strcpy(*endstr, str);
return 0.0;
}
while (*str && isdigit(*str))
{
if (*str == '.')
{
++str;
while (*str && isdigit(*str))
{
num2 += point * ((*str) - '0');
point *= 0.1;
++str;
}
strcpy(*endstr, str);
break;
}
else
{
num1 = 10 * num1 + *str - '0';
str++;
if (!*str || !isdigit(*str))
{
strcpy(*endstr, str);
break;
}
}
}
return (num1 + num2) * sign;
}
参考如下文章,修正了源码中的部分错误。
atoi atof源码
strtoul, strtol实现代码