【C语言 | 字符串处理】sscanf 用法(星号*、集合%[]等)详细介绍、使用例子源码

发布于:2025-07-01 ⋅ 阅读:(18) ⋅ 点赞:(0)

😁博客主页😁:🚀https://blog.csdn.net/wkd_007🚀
🤑博客内容🤑:🍭嵌入式开发、Linux、C语言、C++、数据结构、音视频🍭
⏰发布时间⏰: 2025-06-25

本文未经允许,不得转发!!!


在这里插入图片描述
在这里插入图片描述

🎄一、概述

C语言处理字符串是比较麻烦的,前面有一篇文章介绍了 sscanf 的简单用法,文章链接:sscanf 详细介绍。但最近又遇到一些更复杂的,所以再写一篇博客记录一下笔记。

sscanf 的函数原型如下:

#include <stdio.h>

int scanf(const char *format, ...);
int fscanf(FILE *stream, const char *format, ...);
int sscanf(const char *str, const char *format, ...);
// 返回值:成功则返回参数数目,失败则返回-1,错误原因存于errno中。

其实,sscanf 的使用之所以难懂,就是它的 format 参数比较难理解,本文就是从这个参数的一些常见格式入手,加上一些例子去理解。


在这里插入图片描述

🎄二、sscanf 函数的 str 参数介绍

sscanf 函数的 str 参数是其第一个参数,这是一个 const char *str 的字符串,是我们要处理的字符串。

关于这个str参数,我们只需要知道 sscanf是按照 ' '、'\t'、'\n' 这几个分隔符将str参数划分为多个字符串的,看下面例子:

// str 参数
char first_str[64] = {0,};
char second_str[64] = {0,};
char third_str[64] = {0,};
char fouth_str[64] = {0,};
sscanf("first_str second_str\tthird_str\nfouth_str", "%s%s%s%s", first_str,second_str,third_str,fouth_str);
printf("first_str=[%s],second_str=[%s],third_str=[%s],fouth_str=[%s]\n", first_str,second_str,third_str,fouth_str);

// 清空所有字符串
memset(first_str,0,sizeof(first_str));
memset(second_str,0,sizeof(second_str));
memset(third_str,0,sizeof(third_str));
memset(fouth_str,0,sizeof(fouth_str));
printf("first_str=[%s],second_str=[%s],third_str=[%s],fouth_str=[%s]\n", first_str,second_str,third_str,fouth_str);
	
// 只获取第2、第4字符串
sscanf("first_str second_str\tthird_str\nfouth_str", "%*s%s%*s%s", second_str,fouth_str);
printf("first_str=[%s],second_str=[%s],third_str=[%s],fouth_str=[%s]\n", first_str,second_str,third_str,fouth_str);

运行结果:
在这里插入图片描述


在这里插入图片描述

🎄三、sscanf 函数的 format 参数详解

sscanf 函数的 format 参数是第二个参数,它可以是一个或多个的如下格式:

{% [*] [width] [{hh | h | l | L | ll}] type | ' ' | '\t' | '\n' | 非%符号}

这里可以分成三类去理解:

  • {% [*] [width] [{hh | h | l | L | ll}] type:这个都是属于 %type 的类型的,其中的[*]、[width]、[{hh | h | l | L | ll}]都是可选的;
  • ' ' | '\t' | '\n' :这三个都是空白字符,会匹配到第一个参数的空白字符;
  • 非%符号:最后一类是 非%符号 的字符。非符号字符中有一类特殊的,就是集合%[],会在3.6节介绍。

✨3.1、format 参数的 %type

这个小节介绍format 参数的 %type 类是怎么匹配字符串的。

这里的type可以是有对应的取值的,常见的%type有这些:%%, %d, %u, %f, %x, %c, %s,分别匹配到百分号(%)、带符号十进制整数、无符号十进制整数、带符号浮点数、无符号的十六进制整数、字符、字符串。

下面看例子:

int  			int_type_d=0;
unsigned int 	int_type_u=0;
float 			float_type_f=0.0;
int 			int_type_x=0;
char 			char_type_c=0;
char 			str_type_s[64]={0,};
sscanf("123 456 3.14 0xff C str 1080863910568919039", "%d %u %f %x %c %s", 
	&int_type_d,&int_type_u,&float_type_f,&int_type_x,&char_type_c,str_type_s);
printf("int_type_d=[%d],int_type_u=[%u],float_type_f=[%f],int_type_x=[%x],char_type_c=[%c],str_type_s=[%s]\n",
	int_type_d,int_type_u,float_type_f,int_type_x,char_type_c,str_type_s);

运行结果:
在这里插入图片描述


✨3.2、format 参数带有星号[*]%type

%type类型在type前面有三个可选的前缀,如果在type前加上[*],表示跳过这个匹配的数据。例如"%*s %s"表示跳过第一个字符串,读取第二个字符串;

看例子:

// %*type
char str_type1[64] = {0,};
char str_type2[64] = {0,};
sscanf("123 456 3.14 0xff C str 1080863910568919039", "%*d %*u %*f %*x %s %s", str_type1, str_type2);
//sscanf("123 456 3.14 0xff C str 1080863910568919039", "%*s %*s %*s %*s %s %s", str_type1, str_type2);
printf("str_type1=[%s], str_type2=[%s]\n",str_type1, str_type2);

要处理的字符串是"123 456 3.14 0xff C str 1080863910568919039",使用的 format 是"%*d %*u %*f %*x %s %s",跳过前面4个匹配的字符串,从第5个开始读取。

需要注意,使用的 format 改为"%*s %*s %*s %*s %s %s" 也是一样的结果,因为sscanf会把要处理的字符串按空格分隔成多个子字符串。

运行结果:
在这里插入图片描述


✨3.3、format 参数带有宽度[width]%type

type前加上[width],表示匹配的宽度。如果与星号([*])一起使用时,星号需要在[width]前面。例如:

  • 处理字符串"123"时,只读取12存放到一个整数里,可以这样写;
    sscanf("123", "%2d", &i);
    
  • 处理字符串"3.14"时,只读取3.1存放到一个浮点数里,可以这样写;
    sscanf("3.14", "%3f", &f);
    
  • 处理字符串"1080863910568919039"时,想跳过前面11个数字,可以这样写;
    sscanf("1080863910568919039", "%*11s%s", str);
    

看了上面例子,你可以知道怎样使用带宽度的format了,那下面看个复杂的例子,试试能否看懂 😜。

例子:

// %[width]type
int  	int_width = 0;
float 	float_width=0.0;
char str_width1[64] = {0,};
char str_width2[64] = {0,};
sscanf("123 456 3.14 0xff C str 1080863910568919039", "%2d%*d %*u %3f%*s %3s%*s %*s %*s %*11s%s", &int_width, &float_width, str_width1, str_width2);
printf("int_width=%d, float_width=%f, str_width1=[%s], str_width2=[%s]\n",int_width,float_width,str_width1, str_width2);

运行结果:
在这里插入图片描述


✨3.4、format 参数带有[{hh | h | l | L | ll}]%type

type前加上[{hh | h | l | L | ll}],表示后面对应参数的类型。

  • hh:type必须是d, i, o, u, x, X, n之一,表示其后对应的参数指向一个charunsigned char类型的指针;
  • h:表示其后对应的参数指向一个shortunsigned short类型的指针;
  • l:表示其后对应的参数指向一个longunsigned long类型的指针;
  • L:如果type是e、f、g则其后对应的参数指向一个long double 类型的指针;如果type是d, i, o, u, x则其后对应的参数指向一个long long 类型的指针;
  • ll:表示其后对应的参数指向一个long long 类型的指针;

注意:如果没按照[{hh | h | l | L | ll}]在对应的参数给到对应的类型,编译是会有类似这样的警告,warning: format ‘%hhd’ expects argument of type ‘signed char *’, but argument 3 has type ‘short int *’

例子:

// %[{hh | h | l | L | ll}]type
char 			char_c = 0;
unsigned char 	uchar_c = 0;
short  			short_s = 0;
unsigned short 	ushort_s = 0;
long  			long_l = 0;
unsigned long 	ulong_l = 0;
long long 		Long_L = 0;
unsigned long long uLong_L = 0;
sscanf("127 255 123 321 456 654 789 987", "%hhd %hhu %hd %hu %ld %lu %Ld %Lu", 
	&char_c, &uchar_c, &short_s, &ushort_s, &long_l, &ulong_l, &Long_L, &uLong_L);
printf("char_c=[%hhd], uchar_c=[%hhu], short_s=%hd ushort_s=%hu long_l=%ld ulong_l=%lu Long_L=%Ld uLong_L=%Lu\n",
	char_c, uchar_c, short_s, ushort_s, long_l, ulong_l, Long_L, uLong_L);

运行结果:
在这里插入图片描述


✨3.5、format 参数中的空白字符 ’ ’ | ‘\t’ | ‘\n’

前面介绍过,如果第一个参数有空白字符(' '、'\t'、'\n'),sscanf是按照将str参数划分为多个子字符串;而fromat 参数中的空白字符,无论是连续多少个,都是当成一个空格(' ')来匹配的。

可以看看下面例子:

// ' ' | '\t' | '\n'
char  blank_type[64] = {0,};
sscanf("1 \n2", "1\t%s", blank_type);
printf("blank_type=[%s]\n", blank_type);
sscanf("3 \t\t\t\n\n\n\n\t   4", "3\t\t\n  \t\n\t%s", blank_type);
printf("blank_type=[%s]\n", blank_type);
printf("\n");

运行结果:
在这里插入图片描述


✨3.6、format 参数中的集合%[]

支持集合操作:

  • %[]:只要是中括号内的字符都会匹配,例如:
    %[abc ]:表示只要是abc、空格( ) 这几个字符就一直匹配,直到不是这4个字符之一为止;
    %[a-z1-9\t]:表示匹配a-z之间的任意字符,并且也匹配1-9之间的任意字符,还匹配\t字符;
  • %[^]:只要是中括号内的字符都不会匹配
    %[^abc ]:表示只要不是abc、空格( ) 这几个字符就一直匹配,直到是这4个字符之一为止;
    %[^a-z1-9\t]:表示不匹配a-z之间的任意字符,并且也不匹配1-9之间的任意字符,还匹配\t字符;

注意:这个集合操作也可以和星号[*]一起使用,表示跳过匹配到的字符串。

看例子:

// %[]
char  str_abc[64] = {0,};
char  str_NBA[64] = {0,};
sscanf("aabbcc cba abc NBA", "%[abc ]", str_abc);
printf("str_abc=[%s]\n", str_abc);

memset(str_abc, 0, sizeof(str_abc));
sscanf("aabbcc cba abc 13578 246810 NBA", "%[a-z1-9 ]0 %[A-N]", str_abc, str_NBA);
printf("str_abc=[%s], str_NBA=[%s]\n", str_abc, str_NBA);
printf("\n");

memset(str_NBA, 0, sizeof(str_NBA));
sscanf("aabbcc cba abc \t13578 246810 NBA", "%*[a-z0-9 \t] %[A-N]", str_NBA);
printf("str_NBA=[%s]\n", str_NBA);
printf("\n");

// %[^]
memset(str_NBA, 0, sizeof(str_NBA));
sscanf("NBA 246810 13578 aabbcc cba abc", "%[^abc ]", str_NBA);// 只要不是abc
printf("str_NBA=[%s]\n", str_NBA);

memset(str_NBA, 0, sizeof(str_NBA));
sscanf("NBA 246810 13578 aabbcc cba abc", "%[^abc]", str_NBA);// 只要不是abc
printf("str_NBA=[%s]\n", str_NBA);

memset(str_NBA, 0, sizeof(str_NBA));
sscanf("NBA 246810 13578 aabbcc cba abc", "%[^a-z0-9\t]", str_NBA);
printf("str_NBA=[%s]\n", str_NBA);

运行结果:
在这里插入图片描述


在这里插入图片描述

🎄四、例子源码

/**
 * @file sscanf_sample.c
 * @author https://blog.csdn.net/wkd_007
 * @brief 
 * @version 0.1
 * @date 2025-06-30
 * 
 * @copyright Copyright (c) 2025
 * gcc sscanf_sample.c 
 */
#include <stdio.h>
#include <string.h>

int main()
{
	// str 参数
	char first_str[64] = {0,};
	char second_str[64] = {0,};
	char third_str[64] = {0,};
	char fouth_str[64] = {0,};
	sscanf("first_str second_str\tthird_str\nfouth_str", "%s%s%s%s", first_str,second_str,third_str,fouth_str);
	printf("first_str=[%s],second_str=[%s],third_str=[%s],fouth_str=[%s]\n", first_str,second_str,third_str,fouth_str);

	// 清空所有字符串
	memset(first_str,0,sizeof(first_str));
	memset(second_str,0,sizeof(second_str));
	memset(third_str,0,sizeof(third_str));
	memset(fouth_str,0,sizeof(fouth_str));
	printf("first_str=[%s],second_str=[%s],third_str=[%s],fouth_str=[%s]\n", first_str,second_str,third_str,fouth_str);
	
	// 只获取第2、第4字符串
	sscanf("first_str second_str\tthird_str\nfouth_str", "%*s%s%*s%s", second_str,fouth_str);
	printf("first_str=[%s],second_str=[%s],third_str=[%s],fouth_str=[%s]\n", first_str,second_str,third_str,fouth_str);
	printf("\n");
	
	//--------------------------
	// %type
	int  			int_type_d=0;
	unsigned int 	int_type_u=0;
	float 			float_type_f=0.0;
	int 			int_type_x=0;
	char 			char_type_c=0;
	char 			str_type_s[64]={0,};
	sscanf("123 456 3.14 0xff C str 1080863910568919039", "%d %u %f %x %c %s", 
		&int_type_d,&int_type_u,&float_type_f,&int_type_x,&char_type_c,str_type_s);
	printf("int_type_d=[%d],int_type_u=[%u],float_type_f=[%f],int_type_x=[%x],char_type_c=[%c],str_type_s=[%s]\n",
		int_type_d,int_type_u,float_type_f,int_type_x,char_type_c,str_type_s);
	printf("\n");
		
	// %[*]type
	char str_type1[64] = {0,};
	char str_type2[64] = {0,};
	sscanf("123 456 3.14 0xff C str 1080863910568919039", "%*d %*u %*f %*x %s %s", str_type1, str_type2);// 跳过第2、3、4个字符串
	//sscanf("123 456 3.14 0xff C str 1080863910568919039", "%*s %*s %*s %*s %s %s", str_type1, str_type2);// 这个也可以
	printf("str_type1=[%s], str_type2=[%s]\n",str_type1, str_type2);
	printf("\n");
	
	// %[width]type
	int  	int_width = 0;
	float 	float_width=0.0;
	char str_width1[64] = {0,};
	char str_width2[64] = {0,};
    // %2d%*d,表示读取123 的 12,跳过3
    // %3f%*s,表示读取3.14 的 31.2,提过4
    // %*11s%s,表示跳过 1080863910568919039 前11个字符,再开始匹配
	sscanf("123 456 3.14 0xff C str 1080863910568919039", "%2d%*d %*u %3f%*s %3s%*s %*s %*s %*11s%s", &int_width, &float_width, str_width1, str_width2);
	printf("int_width=%d, float_width=%f, str_width1=[%s], str_width2=[%s]\n",int_width,float_width,str_width1, str_width2);
	printf("\n");
	
	// %[{hh | h | l | L | ll}]type
	char 			char_c = 0;
	unsigned char 	uchar_c = 0;
	short  			short_s = 0;
	unsigned short 	ushort_s = 0;
	long  			long_l = 0;
	unsigned long 	ulong_l = 0;
	long long 		Long_L = 0;
	unsigned long long uLong_L = 0;
	sscanf("127 255 123 321 456 654 789 987", "%hhd %hhu %hd %hu %ld %lu %Ld %Lu", 
		&char_c, &uchar_c, &short_s, &ushort_s, &long_l, &ulong_l, &Long_L, &uLong_L);
	printf("char_c=[%hhd], uchar_c=[%hhu], short_s=%hd ushort_s=%hu long_l=%ld ulong_l=%lu Long_L=%Ld uLong_L=%Lu\n",
		char_c, uchar_c, short_s, ushort_s, long_l, ulong_l, Long_L, uLong_L);
	printf("\n");
	
	// ' ' | '\t' | '\n'
	char  blank_type[64] = {0,};
	sscanf("1 \n2", "1\t%s", blank_type);// str参数,format参数中的空白字符都当成空格来处理
	printf("blank_type=[%s]\n", blank_type);
	sscanf("3 \t\t\t\n\n\n\n\t   4", "3\t\t\n  \t\n\t%s", blank_type);
	printf("blank_type=[%s]\n", blank_type);
	printf("\n");
	
	// %[]
    char  str_abc[64] = {0,};
    char  str_NBA[64] = {0,};
    sscanf("aabbcc cba abc NBA", "%[abc ]", str_abc);// 从str参数第一个字符开始扫描,只匹配 a,b,c,' ' 4个字符
    printf("str_abc=[%s]\n", str_abc);

    memset(str_abc, 0, sizeof(str_abc));
    sscanf("aabbcc cba abc 13578 246810 NBA", "%[a-z1-9 ]0 %[A-N]", str_abc, str_NBA);
    printf("str_abc=[%s], str_NBA=[%s]\n", str_abc, str_NBA);

    memset(str_NBA, 0, sizeof(str_NBA));
    sscanf("aabbcc cba abc \t13578 246810 NBA", "%*[a-z0-9 \t] %[A-N]", str_NBA);
    printf("str_NBA=[%s]\n", str_NBA);
	printf("\n");

    // %[^]
    memset(str_NBA, 0, sizeof(str_NBA));
    sscanf("NBA 246810 13578 aabbcc cba abc", "%[^abc ]", str_NBA);// 从str参数第一个字符开始扫描,直到 a,b,c,' ' 4个字符之一停止
    printf("str_NBA=[%s]\n", str_NBA);

    memset(str_NBA, 0, sizeof(str_NBA));
    sscanf("NBA 246810 13578 aabbcc cba abc", "%[^abc]", str_NBA);// 从str参数第一个字符开始扫描,直到 a,b,c 3个字符之一停止
    printf("str_NBA=[%s]\n", str_NBA);

    memset(str_NBA, 0, sizeof(str_NBA));
    sscanf("NBA 246810 13578 aabbcc cba abc", "%[^a-z0-9\t]", str_NBA);
    printf("str_NBA=[%s]\n", str_NBA);
	printf("\n");

    // 实用例子
    char buf[64] = {0,};
    
    // 1.获取到指定字符为止的字符串
    memset(buf, 0, sizeof(buf));
    sscanf("RTSP/1.0 200 OK\r\n", "%[^\r]", buf);
    printf("buf=[%s]\n", buf);

    // 2.获取包含指定字符集的字符串,这里获取IP地址
    memset(buf, 0, sizeof(buf));
    sscanf("192.168.2.183:8554\r\n", "%[0-9.]", buf);
    printf("buf=[%s]\n", buf);

    // 3.从字符串中截取一段字符串,这里截取 // 之后,空格之前 的字符串。
    memset(buf, 0, sizeof(buf));
    sscanf("OPTIONS rtsp://192.168.2.183:8554 RTSP/1.0\r\n", "%*s %*[^/]// %[^ ]", buf);
    printf("buf=[%s]\n", buf);

    // 4.获取mac地址
    int mac[6]={0,};
    sscanf("00:0b:ce:19:09:06", "%2x:%2x:%2x:%2x:%2x:%2x", &mac[0], &mac[1], &mac[2], &mac[3], &mac[4], &mac[5]);
    printf("%02x:%02x:%02x:%02x:%02x:%02x\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
    printf("\n");
    
    return 0;
}

运行结果:
在这里插入图片描述


在这里插入图片描述

🎄五、总结

本文介绍了 sscanf 用法 的详细用法, 结合例子学习,一定有所收益。

在这里插入图片描述
如果文章有帮助的话,点赞👍、收藏⭐,支持一波,谢谢 😁😁😁

参考:
C语言函数sscanf()的用法:https://www.cnblogs.com/lyq105/archive/2009/11/28/1612677.html
关于sscanf函数的使用:https://www.jianshu.com/p/67e50d4d4872