C语言 day13 | 我的日常分享

C语言 day13

字符串处理

atoi atol atof

atoi函数

  • 头文件:#include<stdlib.h>
  • 函数原型:int atoi(const char *str)
  • 函数功能: 把参数 str 所指向的字符串转换为一个int整数
  • 参数:str – 要转换为整数的字符串。
  • 函数返回值:该函数返回转换后的长整数,如果没有执行有效的转换,则返回零。

atol函数

  • 头文件:#include<stdlib.h>
  • 函数原型:int long atol(const char *str)
  • 函数功能: 把参数 str 所指向的字符串转换为long int
  • 参数:str – 要转换为长整数的字符串。
  • 函数返回值:该函数返回转换后的长整数,如果没有执行有效的转换,则返回零。

案例1:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include<stdio.h>
#include<stdlib.h>
int main(int argc,char *argv[]){

printf("%d\n",atoi("123"));
printf("%d\n",atoi("123abc"));
printf("%d\n",atoi("hello"));//转换失败 返回0
printf("-------------------\n");
printf("%d\n",atol("123"));
printf("%d\n",atol("123abc"));
printf("%d\n",atol("hello"));//转换失败 返回0
printf("-------------------\n");
printf("%f\n",atof("123.32"));
printf("%f\n",atof("123"));
printf("%f\n",atof("123abc"));
printf("%f\n",atof("hello"));//转换失败 返回0
return 0;
}

运行结果:
图片

案例2:自己实现一个atoi

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include<stdio.h>
#include<stdlib.h>
int my_atoi(char *str){
int sum=0;
while(*str!='\0'){
if(!(*str>='0'&&*str<='9')){
return 0;
}
sum=sum*10+(*str-'0');
str++;
}
return sum;
}
int main(int argc,char *argv[]){

printf("%d\n",atoi("123"));
printf("%d\n",atoi("123abc"));
printf("%d\n",atoi("hello"));//转换失败 返回0

return 0;
}

运行结果:
图片


strtoc函数

  • 头文件:#include<string.h>
  • 函数原型:char *strtok(char *str, const char *delim)
  • 函数参数:
    • str – 要被切割的字符串。
    • delim – 分割字符串中包含的所有字符。
  • 返回值:该函数返回被分解的第一个子字符串,如果没有可检索的字符串,则返回一个空指针NULL
  • 注意:不能切割字符串常量,因为他不能被修改

    strrok()在参数str的字符串中发现delim中包含的分割字符串时,则会将该字符串更改为'\0',当连续出现多个时只讲第一个替换为'\0';

在第一次调用时:strtok()必需要给参数str;在第二次到第n次调用时:将str的参数设置为NULL,每次调用成功则返回被分割出的片段的指针。

案例3:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include<stdio.h>
#include<string.h>
int main(int argc,char *argv[]){
char str[]="china:beijing:shanghai:wuhan";
char *arr[32]={NULL};
int i=0;

//第1次切割
arr[i]=strtok(str,":");

//第2~n次切割
while(arr[i] != NULL){
i++;
arr[i]=strtok(NULL,":");
}

int j=0;
/*for(j=0;j<i;j++){
printf("%s\n",arr[j]);
}*/
//遍历切割后的内容
while(arr[j]!=NULL){
printf("%s\n",arr[j]);
j++;
}
return 0;
}

运行结果:
图片

案例3优化1:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include<stdio.h>
#include<string.h>
int main(int argc,char *argv[]){
char str[]="china:beijing:shanghai:wuhan";
char *arr[32]={str,NULL};
int i=0;

//切割 将两次切割代码合在了一起
while(1){
arr[i]=strtok(arr[i],":");
if(arr[i] == NULL){
break;
}
i++;
}

int j=0;
//遍历切割后的内容
while(arr[j]!=NULL){
printf("%s\n",arr[j]);
j++;
}
return 0;
}

运行结果:
图片

案例3优化2:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include<stdio.h>
#include<string.h>
int main(int argc,char *argv[]){
char str[]="china:beijing:shanghai:wuhan";
char *arr[32]={str,NULL};
int i=0;

//切割 将两次切割代码合在了一起
/*while(arr[i]=strtok(arr[i],":")){
i++;
}*/
while(arr[i++]=strtok(arr[i],":")); //devC++无法使用这行代码

int j=0;
//遍历切割后的内容
while(arr[j]!=NULL){
printf("%s\n",arr[j]);
j++;
}
return 0;
}

运行结果:
图片

注意:

  1. 如果要以多个分割符 再delim里面加就行了

案例4:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include<stdio.h>
#include<string.h>
int main(int argc,char *argv[]){
char str[]="china::@@##beijing::::shanghai#@:@#@::wuhan";
char *arr[32]={str,NULL};
int i=0;
//切割 将两次切割代码合在了一起
/*while(arr[i]=strtok(arr[i],":@#")){
i++;
}*/
while(arr[i++]=strtok(arr[i],"::@#")); //devC++无法使用这行代码

int j=0;
//遍历切割后的内容
while(arr[j]!=NULL){
printf("%s\n",arr[j]);
j++;
}
return 0;
}

运行结果:
图片


sprintf组包

  1. printf向终端输出
  2. sprintf向字符串输出
  3. fprintf向文件输出

图片

  • 头文件:#include<stdio.h>
  • 函数原型:int sprintf(char *str, const char *format, ...)
  • 返回值:如果成功,则返回写入的字符总数,不包括字符串追加在字符串末尾的空字符。如果失败,则返回一个负数。

用法、参数、格式化输出等与printf基本相同,只是不是输出在终端而是在,字符串中而已

案例4:

1
2
3
4
5
6
7
8
9
10
#include<stdio.h>
int main(int argc,char *argv[]){
char str[128]="";
int year=2020;
int mon=5;
int day=15;
sprintf(str,"%d年%d月%d日",year,mon,day);
printf("%s\n",str);
return 0;
}

运行结果:
图片

案例5:

1
2
3
4
5
6
7
8
9
10
11
#include<stdio.h>
int main(int argc,char *argv[]){
char str[128]="";
char name[]="小花";
int age=18;
char sex[]="女";
char addr[]="湖北省武汉市";
sprintf(str,"名字:%s \n性别:%s \n年龄:%d \n地址:%s",name,sex,age,addr);
printf("%s\n",str);
return 0;
}

运行结果:
图片

特殊的用法:利用sprintf将数字转换成字符串

1
2
3
4
5
6
7
8
#include<stdio.h>
int main(int argc,char *argv[]){
int num=12345;
char str[128]="";
sprintf(str,"%d",num);
printf("%s\n",str);
return 0;
}

运行结果:
图片


sscanf解包

  1. printf从终端中获取输入
  2. sprintf从字符串中获取输入
  3. fprintf从文件中获取输入

图片

  • 头文件:#include<stdio.h>
  • 函数原型:int sscanf(const char *str, const char *format, ...))
  • 返回值:如果成功,该函数返回成功匹配和赋值的个数。如果到达文件末尾或发生读错误,则返回 EOF。

用法、参数、格式化输出等与scanf基本相同,只是不是输出在终端而是在,字符串中而已

案例6:

1
2
3
4
5
6
7
8
9
10
11
12
#include<stdio.h>
int main(int argc,char *argv[]){
char str[]="2020年5月15日";
int year=0;
int mon=0;
int day=0;

sscanf(str,"%d年%d月%d日",&year,&mon,&day);

printf("year=%d mon=%d day=%d",year,mon,day);
return 0;
}

运行结果:
图片

注意%s获取输入时 遇到空格、回车、’\0’ 停止获取,与scanf类似

案例7:

1
2
3
4
5
6
7
8
9
10
11
12
#include<stdio.h>
int main(int argc,char *argv[]){
char str[]="2020年5月15日";
char year[128]="";
char mon[128]="";
char day[128]="";

sscanf(str,"%s年%s月%s日",year,mon,day);

printf("year=%s mon=%s day=%s",year,mon,day);
return 0;
}

运行结果:
图片

分析:
第一个%s将全部字符都获取到了,后面的两个%s就没有字符获取了

sscanf高级用法:

1. 使用%s、%d…跳过提取内容

案例8:请取出5678,且不要取1234

1
2
3
4
5
6
7
8
9
#include<stdio.h>
int main(int argc,char *argv[]){
int num=0;
//sscanf("1234 5678","%*d%d",&num);
sscanf("1234 5678","%*d %d",&num);
//sscanf("1234 5678","%*s %d",&num);
printf("num=%d",num);
return 0;
}

运行结果:
图片

2. 使用%[n]s、%[n]d…跳过指定宽度n的字符串或数据([]的意思是说n是变化的不是真的要写[])

案例9:请取出4567,且不要取123abc

1
2
3
4
5
6
7
8
9
#include<stdio.h>
int main(int argc,char *argv[]){
int num=0;

//sscanf("123ab4567","%*5s%d",&num);
sscanf("123ab4567","%*3d%*2s%d",&num);
printf("num=%d",num);
return 0;
}

运行结果:
图片

2. 集合操作

  1. 使用 %[a-z] 提取a-z的字符串
    • 注意:只要遇到 %[] 都是按字符串提取
    • 当遇到不符合其格式的就会停止提取

案例9:

1
2
3
4
5
6
7
8
9
#include<stdio.h>
int main(int argc,char *argv[]){
char str1[]="abcDeFg";
char str2[128]="";

sscanf(str1,"%[a-z]",str2);
printf("%s\n",str2); //当遇到不符合其格式的就会停止提取 所以不是输出abceg
return 0;
}

运行结果:
图片

  1. 使用 %[bCe] 匹配b、C、e

案例10:

1
2
3
4
5
6
7
8
9
#include<stdio.h>
int main(int argc,char *argv[]){
char str1[]="bbCCebCabCe";
char str2[128]="";

sscanf(str1,"%[bCe]",str2);//当遇到'a'是不是b、C、e停止获取
printf("%s\n",str2);
return 0;
}

运行结果:
图片

  1. 使用%[^abc],只要不是a、b、c都获取

案例11:

1
2
3
4
5
6
7
8
9
#include<stdio.h>
int main(int argc,char *argv[]){
char str1[]="hello world! Caeu";
char str2[128]="";

sscanf(str1,"%[^aCu]",str2);
printf("##%s##\n",str2); //当遇到a、C、u时停止获取
return 0;
}

运行结果:
图片

> 拓展案例:歌词解析

图片

  • 题目:请提取出msg中的时、分和歌词
1
2
3
4
5
6
7
8
9
10
#include<stdio.h>
int main(int argc,char *argv[]){
char msg[]="[00:26.44]说不上为什么我变得很主动";
int min=0,sec=0;
char lrc[128]="";

sscanf(msg,"[%d:%d%*3s]%s",&min,&sec,lrc);
printf("min=%d sec=%d lrc=%s\n",min,sec,lrc);
return 0;
}

运行结果:
图片