12.C语言 sscanf的使用

发布于:2025-02-27 ⋅ 阅读:(16) ⋅ 点赞:(0)

目录

描述

核心功能:

适用场景:

返回值:

使用场景

训练内容

%*s或%*d跳过数据

案例1

案例2

%[width]s 读指定宽度的数据

案例1

%[a-z]    匹配a到z中任意字符(尽可能多的匹配)

案例1

案例2

%[aBc]    匹配a、B、c中一员,贪婪性

案例1

案例2

%[^a]     匹配非a的任意字符,贪婪性

案例1

%[^a-z]    表示读取除a-z以外的所有字符

案例

区分ip地址分割

分割内容---取出需要的内容

取出多个字符串

注意事项


描述

sscanf 是 C 语言中一个用于 从字符串中提取格式化数据 的函数。它的作用类似于 scanf,但 scanf 是从标准输入(如键盘)读取数据,而 sscanf 是从一个给定的字符串中按指定格式提取数据。

核心功能:

  1. 解析字符串:根据格式字符串(如 "%d %f %s")的规则,从输入字符串中提取特定类型的数据(如整数、浮点数、字符串等)。

  2. 赋值到变量:将提取到的数据存储到对应的变量中。

char input[] = "Age:25 Height:175.5";
int age;
float height;

// 从 input 字符串中提取整数和浮点数
sscanf(input, "Age:%d Height:%f", &age, &height);

结果:age = 25height = 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一旦匹配失败,后面的就不会在匹配了