stdlib.h 中常用函数[2]数字字符处理
基本信息// joen.hong#gmain.com
// 可任意转载,但请注明连接;
// 本文为巩固基础学习之用;
// 2009年10月09日
// 本文内容来源于C库头文件和Linux manual
在stdlib.h中主要包含数字字符处理的函数有 atoi(), atof(), strtol(), strtod(),eccvt()等函数及其扩展函数。
他们之间的共同点以及区别在下面功能描述中有说明,要详细了解需看手册和源代码实现。
函数原型:int atoi(const char *nptr);
long atol(const char *nptr);
long long atoll(const char *nptr);
long long atoq(const char *nptr);
功能描述:atoi() 函数将指针nptr 指向开始的字符转换成int 类型。行为与 strtol(nptr, (char **) NULL, 10)相同;
只是atoi() 不检测错误。atol() atoll() 和atoi() 有相同动作。只是转换类型有所不同,atoq()是atoll()的过时名。
返 回 值:返回转换的值。
参考函数:atof(3), strtod(3), strtol(3), strtoul(3)
函数原型:double atof(const char *nptr);
功能描述:atof() 函数将指针nptr 指向开始的字符转换成double 类型。行为与 strtod(nptr, (char **) NULL)相同;
只是atof() 不检测错误。
返 回 值:返回转换的值。
参考函数:atoi(3), atol(3), strtod(3), strtol(3), strtoul(3)
函数原型:long int strtol(const char *nptr, char **endptr, int base);
long long int strtoll(const char *nptr, char **endptr, int base);
功能描述:strtol() 函数根据base 给的进制将nptr 指向的开始的字符串转换为长整数值,base 必须在2-36之间,或特殊值0.
字符串可能以任意空格为开始,后跟一个‘+’或‘-’的单个选择符。如果base 为0或16,string 可能包含“0x” 前缀,
那么数字将被以16进制读入;base为0被当作10进制,除非符号后下一个字符为‘0’,这种情形被当作8进制。
字符串被显示转换为长整形值,直到遇到第一个基于base 不合法的字符(base 大于10,那么A表示10...Z表示35)。
如果endptr 不为NULL,strtol() 将第一个不合法字符的地址保存在*endptr中。如果根本没有数字,strtol()将字符
串地址,也就是nptr 初始值保存到 *endptr,并返回0。特别的,如果*nptr不是'\0',但在返回时 **endptr是'\0',
整个字符串是合法的。
strtoll() 函数类似strtol(),但返回是long long 整型值。
返 回 值:strtol() 函数返回转换的结果,除非向下溢出(underflow)或向上溢出(overflow)。如果向下溢出,返回LONG_MIN。
如果向上溢出返回LONG_MAX。两种情况的errno都会被设置为ERANGE。也可能返回0,在base 包含不被支持值时。
strtoll()也一样(不过LLONG_MIN 和LLONG_MAX 替代LONG_MIN 和LONG_MAX)。
参考函数:atof(3), atoi(3), atol(3), strtod(3), strtoul(3)
strtoul() 和strtol基本类似,只是返回无符号长整型。
例外说明:这些函数还有本地相关的类型。例如strtol_l(), strtoul_l() 等等。
函数原型:double strtod(const char *nptr, char **endptr);
float strtof(const char *nptr, char **endptr);
long double strtold(const char *nptr, char **endptr);
功能描述:strtod(), strtof(), 和strtold() 函数将nptr 指向开始的字符串转换成double,float 和long double 类型
字符串期望格式开始于sispace() 可辨认的空格,可选正符‘+’号或负符号‘-’,然后是小数,或16进制小数,
无限值(infinity),或NAN(not-a-number)。
小数包含非空系列十进制数字,可能包含一个基数字符(小数点,和本地环境有关,通常为'.'),然后跟着十进制
指数(exponent)。十进制指数包含一个'E'或'e',跟着正负号,非空十进制数字序列,乘幂为10。
十六进制小数包含"0x"或"0X",跟着非空16进制小数数字系列,可能包含一个基数字符(同上),然后跟着二进制
指数。二进制指数包含'P'或'p',跟着可选正负号,跟着非空数字(decimal digits)系列,乘幂为2。最少有一个
基数字符和二进制指数出现。
无限表示为"INF" 或"INFINITY"。为忽略类型。
"NAN" 也是忽略类型,跟着'(',一系列字符,跟着')'。字符串指定和系统实现NAN的方式有关。
返 回 值:如果有转换,就返回转换值。如果endptr 为非NULL,*endptr 指向最后一个被转换字符的后面。
如果没有转换,返回0,nptr的值保存到*endptr(referenced by endptr)。
如果正确值导致向上溢出,根据数值的符号返回正或负的HUGE_VAL(HUNGE_VALF, HUGE_VALL),errno被设置为ERANGE。
如果导致相信溢出,返回0,errno 被设置为ERANGE。
参考函数:atof(3), atoi(3), atol(3), strtol(3), strtoul(3)
函数原型:char *ecvt(double number, int ndigits, int *decpt, int *sign);
char *fcvt(double number, int ndigits, int *decpt, int *sign);
功能描述:ecvt() 函数将number 转换为一个包含ndigits个数字以null终止的字符串。并返回指向字符串的指针。高顺序位数字为非0,
除非number 为0。字符串不包含小数点;但是小数点相对于字符串开始位置保存于*decpt 中。*decpt 为负值,意味着小数点
位于字符串开始的左边。如果number的符号为负,*sign 被设置为非0, 否则设置成0;如果number 是0,不指定*decpt 是0 或1。
fcvt() 与ecvt() 相同,只是ndigits 指定小数点后的数字数量。
返 回 值:返回一静态字符串指针,字符串为ASCII 表示的数字。不可以线程重入。
参考函数:ecvt_r(3), gcvt(3), qecvt(3), setlocale(3), sprintf(3)
函数原型:long a64l(char *str64);
char *l64a(long value);
功能描述:这两个函数提供32-bit 长整型和little-endian 64进制的ASCII 字符串(长度从0到6)转换。
如果str64 长度大于6,那只用前6字节。如果value大于32-bit,那只用value的低32位。a64l对结果符号扩展。
'.' 代表0,'/'代表1,0-9 代表2-11,A-Z 代表12-37,a-z 代表38-63, 和网络版本的64-encode 不同。
所以有123 = 59*64^0 + 1*64^1 = "v/"。
返 回 值:返回相应的值。
下面是一个Linux manual 中的example 代码:
#include
<
stdlib.h
>
#include < limits.h >
#include < stdio.h >
#include < errno.h >
int main( int argc, char * argv[])
{
int base ;
char * endptr, * str;
long val;
if (argc < 2 ) {
fprintf(stderr, " Usage: %s str [base]\n " , argv[ 0 ]);
exit(EXIT_FAILURE);
}
str = argv[ 1 ];
base = (argc > 2 ) ? atoi(argv[ 2 ]) : 10 ;
errno = 0 ; /* 为了区分调用是否成功 */
val = strtol(str, & endptr, base );
/* 检测各种可能的错误,溢出或base 包含非法值 */
if ((errno == ERANGE && (val == LONG_MAX || val == LONG_MIN))
|| (errno != 0 && val == 0 )) {
perror( " strtol " );
exit(EXIT_FAILURE);
}
if (endptr == str) {
fprintf(stderr, " No digits were found\n " );
exit(EXIT_FAILURE);
}
/* 如果能达到这里,strtol 成功解析了一个数字 */
printf( " strtol() returned %ld\n " , val);
if ( * endptr != ' \0 ' ) /* Not necessarily an error */
printf( " Further characters after number: %s\n " , endptr);
exit(EXIT_SUCCESS);
}
#include < limits.h >
#include < stdio.h >
#include < errno.h >
int main( int argc, char * argv[])
{
int base ;
char * endptr, * str;
long val;
if (argc < 2 ) {
fprintf(stderr, " Usage: %s str [base]\n " , argv[ 0 ]);
exit(EXIT_FAILURE);
}
str = argv[ 1 ];
base = (argc > 2 ) ? atoi(argv[ 2 ]) : 10 ;
errno = 0 ; /* 为了区分调用是否成功 */
val = strtol(str, & endptr, base );
/* 检测各种可能的错误,溢出或base 包含非法值 */
if ((errno == ERANGE && (val == LONG_MAX || val == LONG_MIN))
|| (errno != 0 && val == 0 )) {
perror( " strtol " );
exit(EXIT_FAILURE);
}
if (endptr == str) {
fprintf(stderr, " No digits were found\n " );
exit(EXIT_FAILURE);
}
/* 如果能达到这里,strtol 成功解析了一个数字 */
printf( " strtol() returned %ld\n " , val);
if ( * endptr != ' \0 ' ) /* Not necessarily an error */
printf( " Further characters after number: %s\n " , endptr);
exit(EXIT_SUCCESS);
}
atoi() 和strtol() 函数调用的区别:
atoi() 没有错误检测。而strtol()是有错误检测的。
atoi() 不能指定进制基数,一定是10进制;strtol() 可以由base 指定其他进制的。
手册提供测试数据和结果 $ ./a.out 123
strtol() returned 123
$ ./a.out ' 123'
strtol() returned 123
$ ./a.out 123abc
strtol() returned 123
Further characters after number: abc
$ ./a.out 123abc 55
strtol: Invalid argument
$ ./a.out ''
No digits were found
$ ./a.out 4000000000
strtol: Numerical result out of range