当前位置: 首页 > news >正文

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

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

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

目录

  • 🎄一、概述
  • 🎄二、sscanf 函数的 str 参数介绍
  • 🎄三、sscanf 函数的 format 参数详解
    • ✨3.1、format 参数的 %type
    • ✨3.2、format 参数带有星号[*]%type
    • ✨3.3、format 参数带有宽度[width]%type
    • ✨3.4、format 参数带有[{hh | h | l | L | ll}]%type
    • ✨3.5、format 参数中的空白字符 ' ' | '\t' | '\n'
    • ✨3.6、format 参数中的集合%[]
  • 🎄四、例子源码
  • 🎄五、总结


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

🎄一、概述

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");//--------------------------// %typeint  			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");// %[*]typechar 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]typeint  	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}]typechar 			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

http://www.dtcms.com/a/263029.html

相关文章:

  • 嵌入式SoC多线程架构迁移多进程架构开发技巧
  • C++ std::list详解:深入理解双向链表容器
  • uniapp小程序蓝牙打印通用版(集成二维码打印)
  • 深度学习04 卷积神经网络CNN
  • 【Python】 Function
  • 计算整数二进制中1的个数
  • 障碍感知 | 基于3D激光雷达的三维膨胀栅格地图构建(附ROS C++仿真)
  • day47 注意力热图可视化
  • 展示折线图的后端数据连接
  • leetcode427.建立四叉树
  • 利润才是机器视觉企业的的“稳定器”,机器视觉企业的利润 = (规模经济 + 技术差异化 × 场景价值) - 竞争强度
  • ViT与CLIP:图像×文本 多模态读心术揭秘
  • 大数据系统架构实践(三):Hbase集群部署
  • 嘉讯科技:医疗信息化、数字化、智能化三者之间的关系和区别
  • EPLAN 中定制 自己的- A3 图框的详细指南(一)
  • 【机器学习深度学习】适合微调的模型选型指南
  • DAOS集群部署-Docker模式
  • CloudBase AI Toolkit 让我用“嘴”开发出的第一款网页游戏
  • 网络安全运维与攻防演练综合实训室解决方案
  • 服务器被入侵的常见迹象有哪些?
  • CentOS服务器SSH远程连接全指南
  • HarmonyOS NEXT应用元服务常见列表操作多类型列表项场景
  • 2025年数字信号、计算机通信与软件工程国际会议(DSCCSE 2025)
  • Excel 如何让表看起来更清晰、专业,而不是花里胡哨?
  • 低功耗MM32L0180系列MCU
  • 【Kafka】docker 中配置带 Kerberos 认证的 Kafka 环境(全过程)
  • [springboot系列] 探秘 JUnit 5:现代 Java 单元测试利器
  • Spring Boot 实现不同用户不同访问权限
  • 基于uniapp的老年皮肤健康管理微信小程序平台(源码+论文+部署+安装+售后)
  • 跨时间潜运动迁移以实现操作中的多帧预测