11.9 把字符串转换为数字
数字既能以字符形式存储,也能以数值形式存储。把数字存储为字符串就是存储数字字符。例如,数字213以'2'、'1'、'3'、'\0'的形式被存储在字符串数组中。以数值形式存储213,存储的是int类型的值。
C要求用数值形式进行数值运算。但是在屏幕上显示数字则要求字符串形式,因为屏幕显示的是字符。printf()和sprintf(),通过%d和其他转换说明,把数字从数值形式转换为字符串形式,scanf()可以把输入字符串转换为数值形式。C还有一些函数专门用于把字符串形式转换成数值形式。
假设你编写的程序需要使用数值命令形参,但是命令形参被读取为字符串。因此,要使用数值形式必须先把字符串转换为数字。如果需要整数,可以使用atoi()函数(用于把字母数字转换成整数),该函数接受一个字符串作为参数,返回相应的整数值。
/*hello.c --- 把命令行参数转换为数字*/
#include <stdio.h>
#include <stdlib.h>
int main( int argc, char *argv[] ){
int i, times;
if( argc < 2 || (times = atoi(argv[1])) < 1 ){
printf( "Usage: %s positive-number\n", argv[0] );
} else{
for( i = 0; i < times; i++ ){
puts( "Hello, good looking!" );
}
}
return 0;
}
/* 输出:
*/
$是UNIX和Linux的提示符(一些UNIX系统使用%)。命令行参数被存储为3\0。
如果字符串仅以整数开头,atoi函数也能处理,它只把开头的整数转换为字符。例如,atoi("42regular")将返回整数42。如果命令行参数不是数字,atoi()函数返回0。然而C标准规定,这种情况下的行为是未定义的。因此,使用有错误检查功能的strtol()函数会更安全。
该程序包含了stdlib.h头文件,因为从ANSI C开始,该头文件包含了atoi()函数的原型。除此之外,还包含了atof()和atol()函数的原型。
atof()函数把字符串转换成double类型的值,atol()函数把字符串转换成long类型的值。atof()和atol()的工作原理和atoi()类似,因为它们分别返回double类型和long类型。
ANSI C还提供了一套更智能的函数:strtol()把字符串转换成long类型的值,strtoul()把字符串转换成unsigned long类型的值。strtod()把字符串转换成double类型的值。这些函数的只能之处在于识别字符串中的首字符是否是数字。而且,strtol()和strtoul()还可以指定数字的进制。
strtol()函数的原型如下:
long strtol( const char *restrict nptr, char **restrict endptr, int base );
这里,nptr是指向待转换字符串的指针,endptr是一个指针的地址,该指针被设置为标识输入数字结束字符的地址,base标识以什么进制写入数字。
/* strcnvt.c -- try strtol() */
#include <stdio.h>
#include <stdlib.h>
#define LIM 30
char * s_gets(char * st, int n);
int main()
{
char number[LIM];
char * end;
long value;
puts("Enter a number (empty line to quit):");
while(s_gets(number, LIM) && number[0] != '\0')
{
value = strtol(number, &end, 10); /* base 10 */
printf("base 10 input, base 10 output: %ld, stopped at %s (%d)\n",
value, end, *end);
value = strtol(number, &end, 16); /* base 16 */
printf("base 16 input, base 10 output: %ld, stopped at %s (%d)\n",
value, end, *end);
puts("Next number:");
}
puts("Bye!\n");
return 0;
}
char * s_gets(char * st, int n)
{
char * ret_val;
int i = 0;
ret_val = fgets(st, n, stdin);
if (ret_val)
{
while (st[i] != '\n' && st[i] != '\0')
i++;
if (st[i] == '\n')
st[i] = '\0';
else // must have words[i] == '\0'
while (getchar() != '\n')
continue;
}
return ret_val;
}
/* 输出:
*/
第1次转换在读到空字符时结束,此时end指向空字符。
strtol()函数把十六进制数10a转换成十进制数266。
strtol()函数最多可以转换三十六进制,'a'~'z'字符都可用作数字。strtoul()函数与该函数类似,但是它把字符串转换为无符号值。strtod()函数只以十进制转换,因此它只需要两个参数。
许多实现使用itoa()和ftoa()函数分别把整数和浮点数转换为字符串。但是这两个函数并不是C标准库的成员,可以用sprintf()函数代替它们,因为sprintf()的兼容性更好。
11.10 关键概念
许多程序都要处理文本数据。C程序通过字符串的方式来处理它们。
11.11 本章小结
C字符串是一系列char类型的字符,以空字符('\0')结尾。字符串还可以用字符串常量来表示,里面都是字符,括在双引号中(空字符除外)。编译器提供空字符。
字符串常量也叫作字符串字面量。
函数使用指向字符串首字符的指针来表示待处理的字符串。
main()函数中的第2个参数argv是一个指向数组的指针。argv[0]指向命令名称,argv[1]指向第1个命令行参数,依次类推。