参考:string.h中常用字符串操作函数说明(strstr,strtok,strrchr,strcat,strcmp,strcpy,strerror,strspn,strchr等)
作者:一只青木呀
发布时间: 2020-09-19 13:57:48
网址:https://blog.csdn.net/weixin_45309916/article/details/108679027
前言
C语言标准库中一个常用的头文件,在使用到字符数组时需要使用。string .h 头文件定义了一个变量类型、一个宏和各种操作字符数组的函数。
使用时都需要加上头文件
string.h
字符串函数大全
函数 | 功能 |
---|---|
memchr | 在内存块中定位字符的位置还有相似函数memrchr和rawmemchr |
memcmp | 把两个内存块的内容进行比较。 |
memcpy | 复制内存块的内容 |
memmove | 移动内存块中的内容 |
memset | 以字节方式填充内存块 |
strcat | 把一个字符串后追加到另一个字符串后 |
strchr | 在字符串中查找一个字符的第一个位置指针 |
strcmp | 比较两个字符串(ASCII) |
strcoll | 比较两个字符串(根据指定的 LC_COLLATE) |
strcpy | 复制字符串 |
strcspn | 在一个字符串中查找另一个字符串中的第一个出现的字符的位置 |
strerror | 解释错误代码 |
strlen | 返回字符串长度 |
strncat | 把一个字符串的 n 个字符后追加到另一个字符串后 |
strncmp | 比较两个字符串的前 n 个字符(ASCII) |
strncpy | 复制字符串中的前 n 个字符 |
strpbrk | 查找字符串中第一个出现的属于另一个字符串的任意字符的指针 |
strrchr | 查找字符串中一个字符的出现的最后位置 |
strspn | 计算字符串的从开头起符合另一个字符串的连续字符个数 |
strstr | 在一个字符串中查找另一个字符串 |
strtok | 根据指定字符集分割一个字符串 |
strxfrm | 根据当前环境转化字符串,将转化后的前 n 个字符复制给另一个字符串 |
输入与输出
字符串长度
strlen(字符串长度,‘\0’之前)
#include<stdio.h>
#include<string.h>//使用strlen时引用的头文件
int main()
{
char arr1[] = "hello";
char arr2[] = { 'h','e','l','l','o' };
char arr3[] = { 'h','e','l','l','o','\0'};
printf("%d\n", strlen(arr1));
printf("%d\n", strlen(arr2));//随机值,只有遇到'\0'才结束,而arr2中没有'\0'
printf("%d\n", strlen(arr3));
}
#include<stdio.h>
int main()
{
//strlen只有在遇到'\0'时才结束
char arr[] = { 'a','b','c','d','e','f' };
printf("%d\n", strlen(arr));//随机值
printf("%d\n", strlen(arr+0));//随机值
printf("%d\n", strlen(&arr));//随机值
printf("%d\n", strlen(&arr+1));//随机值-6
printf("%d\n", strlen(&arr[0]+1));//随机值-1
//printf("%d\n", strlen(*arr));//error
//printf("%d\n", strlen(arr[1]));//error
}
sizeof(内存空间大小,包含字符串结束标志‘\0’)
#include<stdio.h>
int main()
{
//sizeof计算占用内存空间大小时,会计算'\0'的大小
int arr1[10]={1,2,3,4,5};
char arr2[]="hello";//字符串后默认有个'\0'
char arr3[]={'h','e','l','l','o'};//字符后没有'\0'
int arr4[]={0};
printf("%d\n",sizeof(arr1));
printf("%d\n",sizeof(arr2));
printf("%d\n",sizeof(arr3));
printf("%d\n",sizeof(int));
return 0;
}
下面来看两组题目:(sizeof在一维数组中的使用)
#include<stdio.h>
int main()
{
//32位平台下,int为4个字节,在64位平台下,int为8个字节
//数组名表示首元素地址;两个除外 1.sizeof(数组名),表示整个数组的大小; 2.&数组名,表示整个数组的地址
int a[] = { 1,2,3,4 };//4*4=16
printf("%d\n", sizeof(a));//16 ,sizeof(数组名),表示整个数组的大小
printf("%d\n", sizeof(a+0));//4/8 ,数组名表示首元素地址,a+0还是首元素地址,地址的大小就是4/8
printf("%d\n", sizeof(*a));//4 ,*a代表首元素,大小就为4
printf("%d\n", sizeof(a+1));//4/8 ,首元素地址+1为第2个元素的地址,地址的大小就是4/8
printf("%d\n", sizeof(a[1]));//4 ,第2个元素的大小,大小为4
printf("%d\n", sizeof(&a));//4/8 ,取的是整个数组的地址,地址的大小就是4/8
printf("%d\n", sizeof(*&a));//16 ,&a取是的地址,数组的地址解引用访问的数组,sizeof计算的就是整个数组的大小
printf("%d\n", sizeof(&a+1));//4/8 ,&a代表整个数组的地址,+1就是跳过整个数组,但还是地址,地址大小就是4/8
printf("%d\n", sizeof(&a[0]));//4/8 ,a[0]是首元素地址,地址的大小就是4/8
printf("%d\n", sizeof(&a[0]+1));//4/8 ,数组的第二个地址,地址的大小就是4/8
在32位平台和64位平台下打印的结果:
sizeof在二维数组中的使用:
#include<stdio.h>
int main()
{
int a[3][4] = { 0 };
printf("%p\n", &a[0][0]);//首地址
printf("%p\n", a[0]+1);//第一行第二个的地址
printf("%p\n", a+1);//第二行的首地址
printf("%p\n", &a[0]+1);//第二行的首地址
printf("%d\n", sizeof(a));//48,sizeof(数组名),表示整个数组的大小
printf("%d\n", sizeof(a[0][0]));//4,首元素的大小
printf("%d\n", sizeof(a[0]));//16,第一行的大小,相当于第一行作为一维数组的数组名
printf("%d\n", sizeof(a[0]+1));//4,a[0]是第一行的数组名,数组名此时是首元素的地址,a[0]其实就是第一行第一个元素的地址,所以a[0]+1是第一行第二个元素的地址,地址大小是4/8
printf("%d\n", sizeof(*(a[0]+1)));//4,第一行第二个元素的大小
printf("%d\n", sizeof(a+1));//4,第二行首元素大小,a是二维数组的数组名,没有sizeof(a),也没有&(a),所以a是首元素的地址,二维数组的首地址是第一行,a就是第一行(首元素)的地址,a+1就是第二行的首地址
printf("%d\n", sizeof(*(a + 1)));//16,第二行的大小
printf("%d\n", sizeof(&a[0] + 1));//4,第二行的首地址
printf("%d\n", sizeof(*(&a[0] + 1)));//16,第二行的大小
printf("%d\n", sizeof(*a));//16,a是首元素的地址,第一行的地址,就是计算*a第一行的大小
printf("%d\n", sizeof(a[3]));//16,第三行的大小
}
总结:
上面说了sizeof和strlen的区别和使用方法,需要我们特别注意的是,srtlen只有在遇到’\0’时,才会结束,就是只计算’\0’之前的字符,所以我们在使用时一定要记得加上’\0’;在使用sizeof时,我们必须要记住,数组名是首元素地址,有两个除外
- 1.sizeof(数组名),计算的是整个数组的大小,单位是字节;
- 2. &数组名,表示的是整个数组的地址。
字符串拷贝
strcpy
- 函数原型:
char *strcpy(char *dest, const char *src);
-
功能:将 src的内容复制给 des,需要保证 des足够容纳 src的空间
-
返回值: 返回 des。
-
demo:
#include <stdio.h>
#include <string.h>
char s1[] = "abcdefg", s2[100];
int main(){
strcpy(s2, s1);
printf ("s2 is '%s'.\n", s2);
return 0;
}
- 运行效果
strncpy(更保险,strcpy没有\0会一直拷贝)
- 函数原型:
char * strncpy ( char * destination, const char * source, size_t num );
-
函数功能:将 source 中的前 num 个字符复制给 destination。如果 source 的长度大于 num,不会自动追加 \0。若小于,则会填充\0,直到长度为 num。
-
返回值:返回 destination 的指针。
-
demo:
#include <stdio.h>
#include <string.h>
int main(){
char a[1000], b[1000] = "hello world!";
strncpy(a, b, 5); //不会自动补 NULL
a[5] = '\0';
puts(a);
return 0;
}
memcpy
- 函数原型:
void *memcpy(void *dest, const void *src, size_t n);
-
函数功能:从内存区src复制n个字节到内存区dest。内存区不能重叠。只会覆盖。
-
返回值:返回一个指向dest的指针。
-
demo:
#include <string.h>
#include <stdio.h>
char s1[] = "abcdefg", s2[100]={'0'};
int main()
{
memcpy(s2, s1, strlen(s1) + 1);
printf (" s2 is '%s'.\n", s2);
return 0;
}
- 运行结果
memmove
- 函数原型:
void *memmove(void *dest, const void *src, size_t n);
-
函数功能:memmove()函数将n个字节从内存区域src拷贝到内存区域dest。这些内存区域可能重叠:复制发生在虽然src中的字节首先被复制到一个不重叠src或dest的临时数组中,然后到dest的临时数组。
-
返回值:返回一个指向dest的指针。
-
demo
//去掉了字符串前面的 4 个空格。
#include <stdio.h>
#include <string.h>
char s[] = " too space";
int main(){
memcpy(s, s+4, strlen(s+4)+1);
printf ("s is '%s'.\n",s);
return 0;
}
- 运行结果
字符串填充
memset
- 函数原型
void *memset(void *s, int c, size_t n);
-
函数功能:用常量字节c填充s指向的内存区域的前n个字节。
-
返回值:返回一个指向内存区域s的指针。
-
demo
#include <stdio.h>
#include <string.h>
char str[] = "hello world!";
int main(){
memset(str, '-', strlen(str));
puts(str);
return 0;
}
- 运行效果
字符串比较
strcmp
- 函数原型:
int strcmp(const char *s1, const char *s2);
-
功能:比较字符串 str1 和 str2 的字典序大小(ASCII)。
-
返回值:
返回值 | 意义 |
---|---|
小于零 | str1 < str2 |
等于零 | str1 == str2 |
大于零 | str1 > str2 |
- demo:
#include <stdio.h>
#include <string.h>
char s1[] = "abcdefg", s2[] = "abcdfgh";
int main(){
int n = strcmp(s1, s2);
if ( n > 0 ){
printf ("\"%s\" is greater.\n", s1);
}else if( n == 0 ){
printf ("\"%s\" is the same as \"%s\".\n", s1, s2);
}else{
printf ("\"%s\" is greater.\n", s2);
}
return 0;
}
- 运行效果
memcmp
- 函数原型:
int memcmp(const void *s1, const void *s2, size_t n);
-
功能:memcmp()函数比较内存区域s1和s2的前n个字节(每个都被解释为无符号字符)。
-
返回值:返回一个指向dest的指针。
返回值 | 意义 |
---|---|
大于零 | ptr1 < ptr2 |
等于零 | ptr1 == ptr2 |
小于零 | ptr1 > ptr2 |
- demo:
#include <stdio.h>
#include <string.h>
char s1[20], s2[20];
int main(){
while(1)
{
gets(s1);
gets(s2);
int n = memcmp(s1, s2, sizeof(s1));
if ( n > 0 ){
printf ("'%s' is greater.n is %d\n", s1,n);
}else if( n == 0 ){
printf ("'%s' is the same as '%s'. n is %d\n", s1, s2,n);
}else{
printf ("'%s' is greater.n is %d\n", s2,n);
}
memset(s1,0,sizeof(s1));
memset(s2,0,sizeof(s2));
}
return 0;
}
- 运行结果
strcoll
- 函数原型:
int strcoll(const char *s1, const char *s2);
-
功能:默认情况下(LC_COLLATE 为 “POSIX” 或 “C” )和 strcmp 一样根据 ASCII 比较字符串大小。对于设置了 LC_COLLATE 语言环境的情况下,则根据 LC_COLLATE 设置的语言排序方式进行比较。例如:汉字,根据拼音进行比较
-
返回值:
返回值 | 意义 |
---|---|
小于零 | str1 < str2 |
等于零 | str1 == str2 |
大于零 | str1 > str2 |
- demo:
#include <stdio.h>
#include <string.h>
char s1[] = "abcdefg", s2[] = "abcdfgh";
int main(){
int n = strcoll(s1, s2);
if ( n > 0 ){
printf ("\"%s\" is greater.\n", s1);
}else if( n == 0 ){
printf ("\"%s\" is the same as \"%s\".\n", s1, s2);
}else{
printf ("\"%s\" is greater.n\n", s2);
}
return 0;
}
- 运行结果
strncmp
- 函数原型:
int strncmp ( const char * str1, const char * str2, size_t num );
-
函数功能:比较 str1 中的前 num 个字符和 str2 中 的前 num 个字符的大小。
-
返回值:
返回值 | 意义 |
---|---|
小于零 | str1 < str2 |
等于零 | str1 == str2 |
大于零 | str1 > str2 |
- demo
#include <stdio.h>
#include <string.h>
char s1[] = "abcdfgh", s2[] = "abcdefg";
int main(){
int n = strncmp(s1, s2, 4);
if ( n > 0 ){
printf ("\"%s\" is greater in the first 4.\n", s1);
}else if( n == 0 ){
printf ("\"%s\" is the same as \"%s\" in the first 4.\n", s1, s2);
}else{
printf ("\"%s\" is greater in the first 4.\n", s2);
}
return 0;
}
字符串查找
memchr
- 函数原型:
void *memchr(const void *s, int c, size_t n);
-
功能:在参数 s 所指向的内存块的前 n 个字节中搜索第一次出现字符 c(一个无符号字符)的位置,并返回相应的指针。
-
返回值:找到返回相应的指针,否则返回 NULL。
-
demo:
#include <stdio.h>
#include <string.h>
char str[1000], ch, *pch;
int main(){
gets(str);
ch = getchar();//void类型转化成char类型 void也是一种类型
pch = (char*) memchr(str, ch, strlen(str)); // memchr 的使用
if ( pch != NULL){
printf ("%c found at %d.\n", ch, pch - str);//地址减去地址 得到相应的位置
}else{
printf ("%c not found.\n", ch);
}
return 0;
}
- 运行结果:
strchr
- 函数原型:
char *strchr(const char *s, int c);
-
函数功能:返回s中的c出现的第一个位置的指针。
-
返回值:如果找到,返回 s中的 c出现的第一个位置的指针;否则返回 NULL。
-
demo:
#include <stdio.h>
#include <string.h>
char str[] = "hello world!", ch = 'o';
int main(){
char *pch = strchr(str, ch);
if ( pch != NULL){
printf (" '%c' is found at %d.\n", ch, pch - str);
}else{
printf ("'%c' is not found.\n", ch);
}
return 0;
}
- 运行效果
strcspn
- 函数原型:
size_t strspn(const char *s, const char *accept);
-
功能:返回 s 中出现的第一个属于 accept 的字符的位置。
-
返回值: 如果找到返回字符位置,否则返回字符串长度。
-
demo:
#include <stdio.h>
#include <string.h>
int main(){
int pos = strcspn("qwert1234des","0123456789");
printf("%d\n", pos);
return 0;
}
- 运行结果:
strpbrk
- 函数原型:
char * strpbrk ( char * str1, const char * str2 );
-
函数功能:查找字符串 str1 中第一个出现的属于字符串 str2 中的任意字符的指针。
-
返回值:返回字符串 str1 中第一个出现的属于字符串 str2 中的任意字符的指针。若没找到,返回 NULL。
-
demo:
#include <stdio.h>
#include <string.h>
int main(){
char a[] = "This is a test.", b[] = "aeiou";
char *pch = strpbrk(a, b);
printf("%d\n", pch - a);
return 0;
}
strrchr
- 函数原型:
char * strrchr ( char * str, int character );
-
函数功能:在字符串中 str 查找最后一个 character 的指针位置。
-
返回值:如果找到,在字符串中 str 查找最后一个 character 的指针位置。否则返回 NULL。
-
demo:
#include <stdio.h>
#include <string.h>
char str[] = "hello world!", ch = 'o';
int main(){
char *pch = strrchr(str, ch);
if ( pch != NULL ){
printf ("'%c' is found at %d.\n", ch, pch - str);
}else{
printf ("'%c' is not found.\n", ch);
}
return 0;
}
strspn
- 函数原型:
size_t strspn ( const char * str1, const char * str2 );
-
函数功能: 计算 str1 字符串从开头开始的连续字符,且这些字符都完全是 str2 所指字符串中的字符。
-
返回值:返回字符的个数。
-
demo:
#include <stdio.h>
#include <string.h>
int main(){
char a[] = "aaaaauuuuuxxxsada", b[] = "aeiou";
int n = strspn(a, b);
printf("%d\n", n); //输出为10,满足条件的字符串为aaaaauuuuu。
return 0;
}
strstr
- 函数原型:
const char * strstr ( const char * str1, const char * str2 )
char * strstr ( char * str1, const char * str2 )
-
函数功能:查找字符串 str1 中首次出现字符串 str2 的位置,注意:必须是连续的字符串,\0后面就查不到了。
-
返回值:返回 str1 中首次出现 str2 的位置的指针,如果 str1 中不存在 str2 则返回 NULL。
-
demo:
#include <stdio.h>
#include <string.h>
int main(){
char a[] = "hello world!", b[] = "world";
char *pch = strstr(a, b);
printf("%d\n", pch - a);
return 0;
}
字符串带格式拼接
sprintf
#include <stdio.h>
#include <string.h>
int main(){
char s[64];
char* who = "I";
char* whom = "CSDN";
sprintf(s, "%s love %s.", who, whom); //产生:"I love CSDN. " 这字符串写到s中
puts(s);
sprintf(s, "%10.3f", 3.1415626); //产生:" 3.142"
puts(s);
}
snprintf
该函数相比sprintf,名字中多了一个’n’,这里的’n’可以理解为num,对应要格式化的字节数。
函数原型:
int snprintf(char *str, size_t size, const char *format, ...);
参数: str -- 目标字符串。
size -- 拷贝的字节数(bytes).
format -- 格式化参数
... -- 可变参数。
返回值:
(1)如果格式化后的字符串长度小于等于size,则会把字符串全部拷贝到str中,
并且给其后添加一个字符串结束符'\0'.
(2) 如果格式化后的字符串长度大于size,则超过size的部分会被截断,只将其中
的(size - 1)个字符赋值到str中,并且添加字符串结束符'\0',返回值为-1
#include <stdio.h>
int main()
{
int len;
char str[100];
char *s = "1234567890";
len = snprintf(str, 100, "%s\n", s);
printf("str:%s\n count:%d\n", str, len);
return 0;
}
我运行的结果
别人博文
#include <stdio.h>
int main()
{
int len;
char str[100];
char *s = "1234567890";
len = snprintf(str, 6, "%s\n", s);
printf("str:%s\ncount:%d\n", str, len);
return 0;
}
别人博文
我运行的结果
vsprintf
该函数相比sprintf多了一个’v’, 这里的v可以理解为 var ist,也就是使用参数列表格式化输出到字符串中。
函数原型:
int vsprintf(char *str, const char *format, va_list arg);
参数:str -- 目标字符串。
format -- 格式化模式
arg -- 可变参数列表对象,应呗<stdarg>中定义的va_start 宏初始化。
返回值:
如果成功,则返回写入的字符总数,否则返回一个负值。
#include <stdio.h>
#include <stdarg.h>
static char str[100];
int vsprintf_test(char *format, ...)
{
va_list aptr;
int ret;
va_start(aptr, format);
ret = vsprintf(str, format, aptr);
va_end(aptr);
return ret;
}
int main()
{
int i = 5;
float f = 66.6;
char *s = "abcdefgf";
int len;
len = vsprintf_test("%d %f %s", i, f, s);
printf("%s\nlen:%d", str, len);
return 0;
}
vsnprintf
该函数比较 snprintf,多了1个"v",这里的 v可以理解为 var_list,也就是可变参数列表。其他使用类似。
函数原型:
int vsnprintf(char *str, size_t size, const char *format, va_list ap);
参数:str -- 目标字符串。
size -- 最大格式化的字符长度。
format -- 格式化模式
arg -- 可变参数列表对象,应呗<stdarg>中定义的va_start 宏初始化。
参数
- 1、名字中包含’n’的限制了格式化输出的最大字节数,这样有一个好处,加了一道保险,就是防止了内存溢出。
- 2、名字中包含‘v’的,表示支持可变参数列表。
字符串追加
strcat
- 函数原型:
char * strcat ( char * des, const char * src );
-
函数功能:将 src 中的内容追加到 des中。
-
返回值:返回 des指针。
-
demo:
#include <stdio.h>
#include <string.h>
char s1[] = "hello ", s2[] = "world!";
int main(){
strcat(s1,s2);
puts(s1);
return 0;
}
- 运行结果
strncat
- 函数原型:
char * strncat ( char * destination, const char * source, size_t num );
-
函数功能:将 source 中的前 num 个字符串追加到 destination 后。
-
返回值:返回追加后的 destination 指针。
-
demo:
#include <stdio.h>
#include <string.h>
char s1[] = "hello ", s2[] = "world! -----";
int main(){
strncat(s1, s2, 6);
puts(s1);
return 0;
}
字符串分割
strtok
- 函数原型:
char * strtok ( char * str, const char * delimiters );
-
函数功能:根据 delimiters 指定的内容进行分割。第一次需传入待分割的字符串 str 指针,之后的调用传入 NULL 即可。
-
返回值:返回指向分割后相应的片段的指针。
-
demo:
#include <stdio.h>
#include <string.h>
char str[] ="- This is a sample string.";
int main (){
char *pch = strtok(str, " .-,");
while( pch != NULL){
printf("%s\n", pch);
pch = strtok(NULL, " .-,");
}
return 0;
}
错误码
strerror
当我们在调用库函数失败的时候,就会把错误信息放在一个全局的变量errno(错误码)中。
- 函数原型:
char * strerror ( int errnum );
-
函数功能:给出错误代码 errnum 的描述内容。
-
返回值:返回描述错误内容的字符串指针。
-
demo:
#include <stdio.h>
#include <string.h>
#include <errno.h>
int main(){
FILE *f = fopen("unexist.file", "r");
if( f == NULL ){
printf ("Error: %s\n",strerror(errno));
}
return 0;
}
字符串长度
strlen
- 函数原型:
size_t strlen ( const char * str );
-
函数功能:返回字符串 str 的长度。
-
返回值:返回字符串 str 的长度。
-
demo:
#include <stdio.h>
#include <string.h>
int main(){
char a[] = "hello world!";
printf("%d\n", strlen(a));
return 0;
}
sizeof
字符串数字转换
字符串转整形数据
atoi、atol、atoll
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);
使用这些函数需要包含头文件<stdlib.h>。
函数参数和返回值含义如下:
nptr:需要进行转换的字符串。
返回值:分别返回转换之后得到的int 类型数据、long int 类型数据以及long long 类型数据。
目标字符串nptr 中可以包含非数字字符,转换时跳过前面的空格字符(如果目标字符串开头存在空格字符),直到遇上数字字符或正负符号才开始做转换,而再遇到非数字或字符串结束时(’ /0 ')才结束转换,并将结果返回。
使用atoi()、atol()、atoll()函数只能转换十进制表示的数字字符串,即0~9。
测试使用atoi()、atol()、atoll()这三个函数将一个数字字符串转为十进制数据。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
printf("atoi: %d\n", atoi("500"));
printf("atol: %ld\n", atol("500"));
printf("atoll: %lld\n", atoll("500"));
exit(0);
}
测试结果:
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);
使用这两个函数需要包含头文件<stdlib.h>。
函数参数和返回值含义如下:
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”前缀。
测试
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
printf("strtol: %ld\n", strtol("0x500", NULL, 16));
printf("strtol: %ld\n", strtol("0x500", NULL, 0));
printf("strtol: %ld\n", strtol("500", NULL, 16));
printf("strtol: %ld\n", strtol("0777", NULL, 8));
printf("strtol: %ld\n", strtol("0777", NULL, 0));
printf("strtol: %ld\n", strtol("1111", NULL, 2));
printf("strtol: %ld\n", strtol("-1111", NULL, 2));
exit(0);
}
测试结果:
strtoul、strtoull
这两个函数使用方法与strtol()、strtoll()一样,区别在于返回值的类型不同,strtoul()返回值类型是unsigned long int,strtoull()返回值类型是unsigned long long int,函数原型如下所示:
#include <stdlib.h>
unsigned long int strtoul(const char *nptr, char **endptr, int base);
unsigned long long int strtoull(const char *nptr, char **endptr, int base);
测试
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
printf("strtoul: %lu\n", strtoul("0x500", NULL, 16));
printf("strtoul: %lu\n", strtoul("0x500", NULL, 0));
printf("strtoul: %lu\n", strtoul("500", NULL, 16));
printf("strtoul: %lu\n", strtoul("0777", NULL, 8));
printf("strtoul: %lu\n", strtoul("0777", NULL, 0));
printf("strtoul: %lu\n", strtoul("1111", NULL, 2));
exit(0);
}
测试结果:
字符串转浮点型数据
atof 函数
atof()用于将字符串转换为一个double 类型的浮点数据,函数原型如下所示:
#include <stdlib.h>
double atof(const char *nptr);
使用该函数需要包含头文件<stdlib.h>。
函数参数和返回值含义如下:
nptr:需要进行转换的字符串。
返回值:返回转换得到的double 类型数据。
测试
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
printf("atof: %lf\n", atof("0.123"));
printf("atof: %lf\n", atof("-1.1185"));
printf("atof: %lf\n", atof("100.0123"));
exit(0);
}
测试结果:
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);
使用这些函数需要包含头文件<stdlib.h>。
函数参数与strtol()含义相同,但是少了base 参数。
测试
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
printf("strtof: %f\n", strtof("0.123", NULL));
printf("strtod: %lf\n", strtod("-1.1185", NULL));
printf("strtold: %Lf\n", strtold("100.0123", NULL));
exit(0);
}
测试结果:
数字转字符串
数字转换为字符串推荐大家使用前面介绍的格式化IO 相关库函数,譬如使用printf()将数字转字符串、并将其输出到标准输出设备或者使用sprintf()或snprintf()将数字转换为字符串并存储在缓冲区中,具体的使用方法,3.11 内容中已经给大家进行了详细介绍,这里不再重述。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
char str[20] = {0};
sprintf(str, "%d", 500);
puts(str);
memset(str, 0x0, sizeof(str));
sprintf(str, "%f", 500.111);
puts(str);
memset(str, 0x0, sizeof(str));
sprintf(str, "%u", 500);
puts(str);
exit(0);
}
运行结果:
给应用程序传参
正则表达式
正则表达式,又称为规则表达式(英语: 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 语言函数库中也提供了用于处理正则表达式的接口供程序员使用。
编译正则表达式
匹配正则表达式
释放正则表达式
匹配URL 的正则表达式:
^((ht|f)tps?)://[-A-Za-z0-9_]+(\.[-A-Za-z0-9_]+)+([-A-Za-z0-9_.,@?^=%&:/~+#]*[-A-Za-z0-9_@?^=%&/~+#])?$
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <regex.h>
#include <string.h>
int main(int argc, char *argv[])
{
regmatch_t pmatch = {0};
regex_t reg;
char errbuf[64];
int ret;
char *sptr;
int length;
int nmatch; //最多匹配出的结果
if (4 != argc) {
/**********************************
* 执行程序时需要传入两个参数:
* arg1: 正则表达式
* arg2: 待测试的字符串
* arg3: 最多匹配出多少个结果
**********************************/
fprintf(stderr, "usage: %s <regex> <string> <nmatch>\n", argv[0]);
exit(0);
}
/* 编译正则表达式*/
if(ret = regcomp(®, argv[1], REG_EXTENDED)) {
regerror(ret, ®, errbuf, sizeof(errbuf));
fprintf(stderr, "regcomp error: %s\n", errbuf);
exit(0);
}
/* 赋值操作*/
sptr = argv[2]; //待测试的字符串
length = strlen(argv[2]);//获取字符串长度
nmatch = atoi(argv[3]); //获取最大匹配数
/* 匹配正则表达式*/
for (int j = 0; j < nmatch; j++) {
char temp_str[100];
/* 调用regexec 匹配正则表达式*/
if(ret = regexec(®, sptr, 1, &pmatch, 0)) {
regerror(ret, ®, errbuf, sizeof(errbuf));
fprintf(stderr, "regexec error: %s\n", errbuf);
goto out;
}
if(-1 != pmatch.rm_so) {
if (pmatch.rm_so == pmatch.rm_eo) {//空字符串
sptr += 1;
length -= 1;
printf("\n"); //打印出空字符串
if (0 >= length)//如果已经移动到字符串末尾、则退出
break;
continue; //从for 循环开始执行
}
memset(temp_str, 0x00, sizeof(temp_str));//清零缓冲区
memcpy(temp_str, sptr + pmatch.rm_so,
pmatch.rm_eo - pmatch.rm_so);//将匹配出来的子字符串拷贝到缓冲区
printf("%s\n", temp_str); //打印字符串
sptr += pmatch.rm_eo;
length -= pmatch.rm_eo;
if (0 >= length)
break;
}
}
/* 释放正则表达式*/
out:
regfree(®);
exit(0);
}
strxfrm
- 函数原型:
size_t strxfrm ( char * destination, const char * source, size_t num );
-
函数功能说明:根据当前环境(由LC_COLLATE所指定)转化 source 字符串,并将前 num 个字符复制给 destination。
-
返回值:返回转换后的字符串的长度。