6.8 字符串与数字互转
在编程中,经常会需要将数字组成的字符串转换为相应的数字、或者将数字转换为字符串,在 C 函数库中同样也提供了相应的函数,本小节就向大家介绍这些函数的用法。
6.8.1 字符串转整形数据
C 函数库中提供了一系列函数用于实现将一个字符串转为整形数据,主要包括 atoi()、atol()、atoll()以及strtol()、strtoll()、strtoul()、strtoull()等,它们之间的区别主要包括以下两个方面:
⚫ 数据类型(int、long int、unsigned long 等)。
⚫ 不同进制方式表示的数字字符串(八进制、十六进制、十进制)。
atoi、atol、atoll 函数
atoi()、atol()、atoll()可将字符串分别转换为 int、long int 以及 long long 类型的数据。
#include <stdlib.h>
int atoi(const char *nptr);
long atol(const char *nptr);
long long atoll(const char *nptr);
/*函数参数:
nptr:需要进行转换的字符串。
返回值:
分别返回转换之后得到的 int 类型数据、long int 类型数据以及 long long 类型数据。*/
目标字符串 nptr 中可以包含非数字字符,转换时跳过前面的空格字符(如果目标字符串开头存在空格字符),直到遇上数字字符或正负符号才开始做转换,而再遇到非数字或字符串结束时(' /0 ')才结束转换,并将结果返回。
使用 atoi()、atol()、atoll()函数只能转换十进制表示的数字字符串,即 0~9。
strtol、strtoll 函数
strtol()、strtoll()两个函数可分别将字符串转为 long int 类型数据和 long long ing 类型数据,与 atol()、atoll()之间的区别在于strtol()、strtoll()可以实现将多种不同进制数(譬如二进制数字字符串、八进制数字字符串、十六进制数字字符串)表示的字符串转换为整形数据。
#include <stdlib.h>
long int strtol(const char *nptr, char **endptr, int base);
long long int strtoll(const char *nptr, char **endptr, int base);
/*函数参数:
nptr:需要进行转换的目标字符串。
endptr:char **类型的指针
如果 endptr 不为 NULL,则 strtol()或 strtoll()会将字符串中第一个无效字符的地址存储在*endptr
如果根本没有数字,strtol()或 strtoll()会将 nptr 的原始值存储在*endptr 中(并返回 0)。
也可将参数 endptr 设置为 NULL,表示不接收相应信息。
base:数字基数
参数 base 必须介于 2 和 36(包含)之间,或者是特殊值 0。
参数 base 决定了字符串转换为整数时合法字符的取值范围,
譬如,当 base=2 时,合法字符为' 0 '、' 1 '(表示是一个二进制表示的数字字符串);
当 base=8 时,合法字符为' 0 '、' 1 '、' 2 '、' 3 '......' 7 '(表示是一个八进制表示的数字字符串);
当 base=16 时,合法字符为' 0 ' 、' 1 '、' 2 '、' 3 '......' 9 '、' a '......' f '(表示是一个十六进制表示的数字字符串);
当 base 大于 10 的时候,' a '代表 10、' b '代表 11、' c '代表 12,依次类推,' z '代表 35(不区分大小写)。
返回值:
分别返回转换之后得到的 long int 类型数据以及 long long int 类型数据。*/
需要进行转换的目标字符串可以以任意数量的空格或者 0 开头,转换时跳过前面的空格字符,直到遇上数字字符或正负符号(' + '或' - ')才开始做转换,而再遇到非数字或字符串结束时(' /0 ')才结束转换,并将结果返回
在 base=0 的情况下,如果字符串包含一个了“0x”前缀,表示该数字将以 16 为基数;如果包含的是“0”前缀,表示该数字将以 8 为基数。当 base=16 时,字符串可以使用“0x”前缀。
strtoul、strtoull 函数
这两个函数使用方法与 strtol()、strtoll()一样,区别在于返回值的类型不同,strtoul()返回值类型是 unsignedlong int,strtoull()返回值类型是 unsigned long long int。
用法,参数一样。
6.8.2字符串转浮点型数据
C 函数库中用于字符串转浮点型数据的函数有 atof()、strtod()、strtof()、strtold()。
atof 函数
atof()用于将字符串转换为一个 double 类型的浮点数据
#include <stdlib.h>
double atof(const char *nptr);
/*函数参数:
nptr:需要进行转换的字符串。
返回值:
返回转换得到的 double 类型数据。*/
strtod、strtof、strtold 函数
strtof()、strtod()以及 strtold()三个库函数可分别将字符串转换为 float 类型数据、double 类型数据、long double 类型数据。
#include <stdlib.h>
double strtod(const char *nptr, char **endptr);
float strtof(const char *nptr, char **endptr);
long double strtold(const char *nptr, char **endptr);
用法与参数参考strtol()函数。
6.8.3数字转字符串
数字转换为字符串推荐大家使用前面介绍的格式化 IO 相关库函数,譬如使用 printf()将数字转字符串、并将其输出到标准输出设备或者使用 sprintf()或 snprintf()将数字转换为字符串并存储在缓冲区中。
6.9 给应用程序传参
一个能够接受外部传参的应用程序往往使用上会比较灵活,根据参入不同的参数实现不同的功能。譬如 open 打开的文件路径是固定的,意味着如果:需要打开另一个文件则需要修改代码、修改文件路径,然后再重新编译、运行,非常麻烦、不够灵活。
其实可以将这些可变的信息通过参数形式传递给应用程序。譬如,当执行应用程序的时候,把需要打开的文件路径作为参数传递给应用程序,就可以在不重新编译源码的情况下,通过传递不同的参数打开不同的文件。
在第一章内容中便给大家介绍了 main 函数的两种常用写法,如果在执行应用程序时,需要向应用程序传递参数,则写法如下:
int main(int argc, char **argv)
{
/* 代码 */
}
或者写成如下形式:
int main(int argc, char *argv[])
{
/* 代码 */
}
传递进来的参数以字符串的形式存在,字符串的起始地址存储在 argv 数组中,参数 argc 表示传递进来的参数个数,包括应用程序自身路径名,多个不同的参数之间使用空格分隔开来。
如果参数本身带有空格、则可以使用双引号" "或者单引号' '的形式来表示。
测试:
获取执行应用程序时,向应用程序传递的参数。
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
int i = 0;
printf("Number of parameters: %d\n", argc);
for (i = 0; i < argc; i++)
printf(" %s\n", argv[i]);
exit(0);
}
输出结果如下图:
6.10 正则表达式
在许多的应用程序当中,通常会有这样的需要:给定一个字符串,检查该字符串是否符合某种条件或规则、或者从给定的字符串中找出符合某种条件或规则的子字符串,将匹配到的字符串提取出来。这种需要在很多的应用程序当中是存在的。
例如:很多应用程序都有这种校验功能,譬如检验用户输入的账号或密码是否符合它们定义的规则,如果不符合规则通常会提示用户按照正确的规则输入用户名或密码。
譬如给定一个字符串,在程序当中判断该字符串是否是一个 IP 地址,对于实现这个功能,大家可能首先想到的是,使用万能的 for 循环。当然使用 for 循环自然是可以解决这个问题,但是在程序代码处理上会比较麻烦。对于这些需求,其实只需要通过一个正则表达式就可以搞定了。
6.10.1 初识正则表达式
正则表达式,又称为规则表达式(英语: Regular Expression),正则表达式通常被用来检索、替换那些符合某个模式(规则)的字符串。正则表达式描述了一种字符串的匹配模式(pattern),可以用来检查一个给定的字符串中是否含有某种子字符串、将匹配的字符串替换或者从某个字符串中取出符合某个条件的子字符串。
在 Linux 系统下运行命令的时候,相信大家都使用过?或*通配符来查找硬盘上的文件或者文本中的某个字符串。?通配符匹配 0 个或 1 个字符,而*通配符匹配 0 个或多个字符。譬如"data?.txt"这样的匹配模式可以将下列文件查找出来:
data.dat
data1.dat
data2.dat
datax.dat
dataN.dat
尽管使用通配符的方法很有用,但它还是很有限。
正则表达式其实也是一个字符串,该字符串由普通字符(譬如,数字 0~9、大小写字母以及其它字符)和特殊字符(称为“元字符”)所组成,由这些字符组成一个“规则字符串”,这个“规则字符串”用来表达对给定字符串的一种查找、匹配逻辑。
许多程序设计语言都支持正则表达式。譬如,在 Perl 中就内建了一个功能强大的正则表达式引擎、Python提供了内置模块 re 用于处理正则表达式,正则表达式这个概念最初是由 Unix 中的工具软件(例如 sed 和grep)普及开的,使用过 sed 命令的朋友想必对正则表达式并不陌生。同样,在 C 语言函数库中也提供了用于处理正则表达式的接口供程序员使用。