目录
描述
sscanf
是 C 语言中一个用于 从字符串中提取格式化数据 的函数。它的作用类似于 scanf
,但 scanf
是从标准输入(如键盘)读取数据,而 sscanf
是从一个给定的字符串中按指定格式提取数据。
核心功能:
解析字符串:根据格式字符串(如
"%d %f %s"
)的规则,从输入字符串中提取特定类型的数据(如整数、浮点数、字符串等)。赋值到变量:将提取到的数据存储到对应的变量中。
char input[] = "Age:25 Height:175.5";
int age;
float height;
// 从 input 字符串中提取整数和浮点数
sscanf(input, "Age:%d Height:%f", &age, &height);
结果:age = 25
, height = 175.5
。
适用场景:
解析日志、配置文件等格式化的字符串。
将字符串内容转换为数值或其他数据类型。
返回值:
成功提取的参数个数(失败时返回
EOF
)。
简而言之:把字符串当输入源,按规则“拆解”出需要的数据。
使用场景
- 解析配置文件:配置文件通常以文本形式存储,
sscanf
可以方便地从配置行中提取所需的配置信息,如数据库连接信息、服务器端口号等。 - 处理网络数据:在网络编程中,接收到的数据通常是字符串形式,使用
sscanf
可以按照协议规定的格式解析这些数据。 - 命令行参数解析:当程序需要从命令行读取特定格式的参数时,
sscanf
可以帮助解析这些参数。 - 日志文件分析:日志文件记录了程序运行过程中的各种信息,
sscanf
可以从日志行中提取关键信息,如时间戳、事件类型、错误码等。 - 数据转换:将字符串形式的数据转换为整数、浮点数等其他数据类型。
训练内容
格式 | 作用 |
%*s或%*d |
跳过数据 |
%[width]s |
读指定宽度的数据 |
%[a-z] |
匹配a到z中任意字符(尽可能多的匹配) |
%[aBc] |
匹配a、B、c中一员,贪婪性 |
%[^a] |
匹配非a的任意字符,贪婪性 |
%[^a-z] |
表示读取除a-z以外的所有字符 |
%*s或%*d跳过数据
就是通过%*来进行跳过操作
比如123456ddabangzhu,我们只需要dabangzhu那么我们可以通过%*d来进行过滤掉数组类型的内容。
案例1
#include "stdio.h"
#include "string.h"
#include "stdlib.h"
//跳过数据
void test01() {
char* str = "123456dabangzhu";
//通过跳过数据,取出dabangzhu
char buf[1024] = "\0";
int len = 0;
sscanf_s(str, "%*d%s",buf,sizeof(buf));
printf("buf: %s",buf);
}
int main() {
test01();
printf("\n");
return EXIT_SUCCESS;
}
运行结果:
案例2
void test02() {
char* str = "dabangzhu123456";
char buff[1024] = "";
sscanf_s(str,"%s%*d",buff,sizeof(buff));
printf("buff:%s\n",buff);
}
int main() {
test02();
printf("\n");
return EXIT_SUCCESS;
}
运行结果:
从以上结果来看,我们似乎没有过滤掉123456.这种问题需要注意,一串本身就是字符串,我们可以通过空格,或者\t来进行解决问题。
void test02() {
char* str = "dabangzhu 123456";
char buff[1024] = "";
sscanf_s(str,"%s%*d",buff,sizeof(buff));
printf("buff:%s\n",buff);
}
int main() {
test02();
printf("\n");
return EXIT_SUCCESS;
}
运行结果:
%[width]s 读指定宽度的数据
指定字符串获取的长度。
案例1
void test03() {
char* str = "dabangzhu12345";
char buf[1024] = "";
sscanf_s(str,"%9s",buf,sizeof(buf));
printf("buf:%s\n",buf);
}
int main() {
test03();
printf("\n");
return EXIT_SUCCESS;
}
运行结果:
%[a-z] 匹配a到z中任意字符(尽可能多的匹配)
可以匹配相关参数,比如数组,英文字符,0-9 a-z .
案例1
a-z运行
void test04() {
char* str = "dabangzhu123456";
char buf[1024] = "";
sscanf_s(str,"%[a-z]",buf,sizeof(buf));
printf("buf: %s\n",buf);
}
int main() {
test04();
printf("\n");
return EXIT_SUCCESS;
}
运行结果:
案例2
0-9
void test05() {
char* str = "dabangzhu123456";
char buf[1024] = "";
sscanf_s(str,"%*[a-z]%[0-9]",buf,sizeof(buf));
printf("buf: %s\n",buf);
}
int main() {
test05();
printf("\n");
return EXIT_SUCCESS;
}
运行结果:
从上面看从过出0-9,首先要吧前面的数据忽略掉,在进一步过滤0-9
%[aBc] 匹配a、B、c中一员,贪婪性
案例1
void test06() {
char* str = "dabangzhu123456";
char buf[1024] = "";
sscanf_s(str,"%[dabang]",buf,sizeof(buf));
printf("buf:%s",buf);
}
int main() {
test06();
printf("\n");
return EXIT_SUCCESS;
}
运行结果:
从上面运行结果来看保持的就是dabang,从前匹配出想要的。但是有种情况,往下面案例看
案例2
void test07() {
char* str = "dabangzhu123456";
char buf[1024] = "";
sscanf_s(str,"%[daBang]",buf,sizeof(buf));
printf("buf:%s", buf);
}
运行结果:
从上面结果来看吧b该成B运行结果就是这样。
注意:从一开始匹配,如果有一个匹配不成功,后面的全部不匹配。这是这个方法的特性。
%[^a] 匹配非a的任意字符,贪婪性
匹配非a的字符串,比如dangbangzhu , ^z,那么从d开始匹配,一直到z就结束,结果显然是dabang可以以下案例,z后面就不进行匹配了,全部过滤掉
案例1
void test08() {
char * str = "dabangzhu123456";
char buf[1024] = "";
sscanf_s(str,"%[^z]",buf,sizeof(buf));
printf("buf:%s",buf);
}
int main() {
test08();
printf("\n");
return EXIT_SUCCESS;
}
运行结果:
从上面结果来看到z后面就不在进行匹配了。
%[^a-z] 表示读取除a-z以外的所有字符
匹配区间,与上面其实是一致的。
void test09() {
char* str = "dabangzhu123456";
char buf[1024] = "";
sscanf_s(str,"%[^0-9]",buf,sizeof(buf));
printf("buf:%s",buf);
}
int main() {
test09();
printf("\n");
return EXIT_SUCCESS;
}
运行结果:
案例
区分ip地址分割
void test10() {
char* str = "172.1.1.1";
int ip1 = 0;
int ip2 = 0;
int ip3 = 0;
int ip4 = 0;
sscanf_s(str, "%d.%d.%d.%d", &ip1, &ip2, &ip3, &ip4);
printf("ip1:%d\n", ip1);
printf("ip2:%d\n", ip2);
printf("ip3:%d\n", ip3);
printf("ip4:%d\n", ip4);
}
int main() {
test10();
printf("\n");
return EXIT_SUCCESS;
}
运行结果
分割内容---取出需要的内容
void test11() {
char* str = "abdce#dabangzhu@1234";
char buf[1024] = "";
//需求,我们要求取出dabangzhu
sscanf_s(str,"%*[^#]#%[^@]",buf,sizeof(buf));
printf("buf:%s", buf);
}
int main() {
test11();
printf("\n");
return EXIT_SUCCESS;
}
运行结果:
取出多个字符串
需求 hello@dabangzhu,在文本中分别取出hello dabangzhu,请查看以下代码
void test12() {
char* str = "hello@dabangzhu";
char topinfo[1024] = "";
char nameinfo[1024] = "";
sscanf_s(str,"%[a-z]%*[@]%s",topinfo, sizeof(topinfo), nameinfo, sizeof(nameinfo));
printf("top:%s\n",topinfo);
printf("name:%s\n",nameinfo);
}
int main() {
test12();
printf("\n");
return EXIT_SUCCESS;
}
注意事项
- 要确保传递给
sscanf
的变量地址是有效的,避免出现未定义行为。 - 当使用
%s
格式说明符提取字符串时,要注意输入字符串的长度,防止缓冲区溢出。如果可能,建议使用%[
格式说明符来控制输入的长度。 sscanf
函数返回成功匹配并赋值的参数个数,可根据返回值判断提取是否成功。- sscanf一旦匹配失败,后面的就不会在匹配了