前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >sscanf,sscanf_s及其相关使用方法「建议收藏」

sscanf,sscanf_s及其相关使用方法「建议收藏」

作者头像
全栈程序员站长
发布于 2022-07-06 13:32:27
发布于 2022-07-06 13:32:27
6.1K00
代码可运行
举报
运行总次数:0
代码可运行

大家好,又见面了,我是全栈君。

#include<stdio.h>

定义函数 int sscanf (const char *str,const char * format,……..);

函数说明 sscanf()会将參数str的字符串依据參数format字符串来转换并格式化数据。格式转换形式请參考scanf()。

转换后的结果存于相应的參数内。

返回值 成功则返回參数数目,失败则返回-1,错误原因存于errno中。 返回0表示失败 否则。表示正确格式化数据的个数 比如:sscanf(str。”%d%d%s”, &i,&i2, &s); 假设三个变成都读入成功会返回3。 假设仅仅读入了第一个整数到i则会返回1。证明无法从str读入第二个整数。

main() { int i; unsigned int j; char input[ ]=”10 0x1b aaaaaaaa bbbbbbbb”; char s[5]; sscanf(input,”%d %x %5[a-z] %*s %f”,&i,&j,s,s); printf(“%d %d %s ”,i,j,s); }

运行 10 27 aaaaa

大家都知道sscanf是一个非常好用的函数,利用它能够从字符串中取出整数、浮点数和字符串等等。它的用法简单,特别对于整数和浮点数来说。但新手可能并不知道处理字符串时的一些高级用法。这里做个简要说明吧。

  1. 常见使用方法。

  charstr[512]={0};   sscanf(“123456″,”%s”,str);   printf(“str=%s”,str);

  2. 取指定长度的字符串。如在下例中,取最大长度为4字节的字符串。

  sscanf(“123456″,”%4s”,str);   printf(“str=%s”,str);

  3. 取到指定字符为止的字符串。如在下例中。取遇到空格为止字符串。

  sscanf(“123456abcdedf”,”%[^]”,str);   printf(“str=%s”,str);

 4. 取仅包括指定字符集的字符串。如在下例中,取仅包括1到9和小写字母的字符串。

  sscanf(“123456abcdedfBCDEF”,”%[1-9a-z]”,str);   printf(“str=%s”,str);

  5. 取到指定字符集为止的字符串。如在下例中。取遇到大写字母为止的字符串。

  sscanf(“123456abcdedfBCDEF”,”%[^A-Z]”,str);   printf(“str=%s”,str);

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

能够用例如以下代码将字符串形式的ip地址转换为四个整数:

  1. char * inputIp
  2. int ip[4];
  3. sscanf_s(inputIp, “%d.%d.%d.%d”, &ip[0], &ip[1],&ip[2],&ip[3]);

注意sscanf_s。当读入的类型是整数或其他长度能够确定的类型时。不能在类型后面跟上长度,可是对于字符串类型(char *)长度无法得知则必须在类型后面明白指出字符串的最大长度(即能够容纳的空间)。举比例如以下:

  1. // crt_sscanf_s.c
  2. // This program uses sscanf_s to read data items
  3. // from a string named tokenstring, then displays them.
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. int main( void )
  7. {
  8. char tokenstring[] = “15 12 14…”;
  9. char s[81];
  10. char c;
  11. int i;
  12. float fp;
  13. // Input various data from tokenstring:
  14. // max 80 character string plus NULL terminator
  15. sscanf_s( tokenstring, “%s”, s, _countof(s) );
  16. sscanf_s( tokenstring, “%c”, &c, sizeof(char) );
  17. sscanf_s( tokenstring, “%d”, &i );
  18. sscanf_s( tokenstring, “%f”, &fp );
  19. // Output the data read
  20. printf_s( “String = %s\n”, s );
  21. printf_s( “Character = %c\n”, c );
  22. printf_s( “Integer: = %d\n”, i );
  23. printf_s( “Real: = %f\n”, fp );
  24. }

对于多个字符串读入的情况。代码例如以下:

  1. sscanf_s(inputString, “%s.%s.%s.%s”, s1, s1.length, s2, s2.length, s3, s3.length, s4, s4.length);

sscanf 函数很好用,竟然我曾经一直不知道这个函数。近期朋友用VS2008敲代码时用到这个函数的安全版本号 sscanf_s 。却出现异常问题。无法解析字符串不说,还会崩溃。

int sscanf_s( const char *buffer, const char *format [, argument ] … );

这是MSDN里面关于函数的定义,没有继续具体查看后面的备注,以及实例的情况下。根本感觉不到sscanf 与 sscanf_s 的差别。以为仍然是像sscanf 一样使用。以致出现奇怪问题。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
Example:
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// crt_sscanf_s.c
// This program uses sscanf_s to read data items
// from a string named tokenstring, then displays them.

#include <stdio.h>
#include <stdlib.h>

int main( void )
{
   char  tokenstring[] = "15 12 14...";
   char  s[81];
   char  c;
   int   i;
   float fp;

   // Input various data from tokenstring:
   // max 80 character string plus NULL terminator
   sscanf_s( tokenstring, "%s", s, _countof(s) );
   sscanf_s( tokenstring, "%c", &c, sizeof(char) );
   sscanf_s( tokenstring, "%d", &i );
   sscanf_s( tokenstring, "%f", &fp );

   // Output the data read
   printf_s( "String    = %s\n", s );
   printf_s( "Character = %c\n", c );
   printf_s( "Integer:  = %d\n", i );
   printf_s( "Real:     = %f\n", fp );
}
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
直到看完整个文档,看到这个实例,才发现原来还有猫腻!sscanf_s 取值的时候。须要在每一个取值后面指定取值的最大大小。

在使用VS2005编译一个程序时,出现了非常多警告,说是用的函数是不安全的。应当使用安全版本号,即函数名称添加“_s”的版本号。 警告内容: warning C4996: ‘sscanf’: This function or variable may be unsafe. Consider using sscanf_s instead. 据了解,“_s”版本号函数是微软后来对c++做得扩展。用来替代原先不安全的函数。比如:printf、scanf、strcpy、fopen等等。

具体參考: ms-help://MS.VSCC.v80/MS.MSDN.v80/MS.VisualStudio.v80.chs/dv_vccrt/html/d9568b08-9514-49cd-b3dc-2454ded195a3.htm

原来安全版本号的函数,对參数和缓冲边界做了检查,添加了返回值和抛出异常。这样添加了函数的安全性,降低了出错的几率。 同一时候这也意味着在使用这些函数时。有时你不得不输入很多其它的关于缓冲区大小的參数,多敲几下键盘能换来更少的麻烦。值得!

以下总结了sscanf的以及sscanf_s的经常用法,也体现了“_s”版本号函数与原函数的特别之处:

1、sscanf和scanf的不同是输入来源。前者是一个字符串,后者则是标准输入设备

2、sscanf的使用。以解析时间字符串为例。将字符串“2009-01-02_11:12:13”解析为整型年月日时分秒

//定义 char cc; tm tm_temp={0}; string stime(“2009-01-02_11:12:13”);

//(1) 必须严格依照分隔符形式匹配填写,若遇到不匹配项则终止解析

sscanf(stime.c_str(), “%4d-%2d-%2d_%2d:%2d:%2d”, &tm_temp.tm_year, &tm_temp.tm_mon, &tm_temp.tm_mday, &tm_temp.tm_hour, &tm_temp.tm_min, &tm_temp.tm_sec ); //(2) 能够不依照切割符号形式填写,字符数必须一致。比如能够正确解析“2009/01/02_11:12:13”

sscanf(stime.c_str(), “%4d%c%2d%c%2d%c%2d%c%2d%c%2d”, &tm_temp.tm_year, &cc, &tm_temp.tm_mon, &cc, &tm_temp.tm_mday, &cc, &tm_temp.tm_hour, &cc, &tm_temp.tm_min, &cc, &tm_temp.tm_sec ); //(3) 能够不依照切割符号形式填写,字符数必须一致。同上,%1s能够等同于%c

sscanf(stime.c_str(), “%4d%1s%2d%1s%2d%1s%2d%1s%2d%1s%2d”, &tm_temp.tm_year, &cc, &tm_temp.tm_mon, &cc, &tm_temp.tm_mday, &cc, &tm_temp.tm_hour, &cc, &tm_temp.tm_min, &cc, &tm_temp.tm_sec );

//(4) 能够不依照切割符形式和数量填写,类型必须一致。比如能够正确解析“2009/01/02___11:12:13” //这里使用了sscanf的正則表達式,与通用的正则表示类似但不全然同样,%*c表示忽略连续多个字符

sscanf(stime.c_str(), “%4d%*c%2d%*c%2d%*c%2d%*c%2d%*c%2d”, &tm_temp.tm_year, &tm_temp.tm_mon, &tm_temp.tm_mday, &tm_temp.tm_hour, &tm_temp.tm_min, &tm_temp.tm_sec ); 3、sscanf_s的使用

//定义 char cc[2]; tm tm_temp={0}; string stime(“2009-01-02_11:12:13”);

//(1) 与sscanf第一种方法同样,能够使用”%4d-%2d-%2d_%2d:%2d:%2d”格式匹配解析

sscanf_s(stime.c_str(), “%4d-%2d-%2d_%2d:%2d:%2d”, &tm_temp.tm_year, &tm_temp.tm_mon, &tm_temp.tm_mday, &tm_temp.tm_hour, &tm_temp.tm_min, &tm_temp.tm_sec ); //(2) 使用%c格式对数据解析时。必须对对应的缓冲区添加长度參数。否则将会出错

sscanf_s(stime.c_str(), “%4d%c%2d%c%2d%c%2d%c%2d%c%2d”, &tm_temp.tm_year, &cc, 1, &tm_temp.tm_mon, &cc, 1, &tm_temp.tm_mday, &cc, 1, &tm_temp.tm_hour, &cc, 1, &tm_temp.tm_min, &cc, 1, &tm_temp.tm_sec ); //(3) 使用%s格式对数据解析时。缓冲长度必须大于字符串长度,否则不予解析

sscanf_s(stime.c_str(), “%4d%1s%2d%1s%2d%1s%2d%1s%2d%1s%2d”, &tm_temp.tm_year, &cc, 2, &tm_temp.tm_mon, &cc, 2, &tm_temp.tm_mday, &cc, 2, &tm_temp.tm_hour, &cc, 2, &tm_temp.tm_min, &cc, 2, &tm_temp.tm_sec );

//(4) 与sscanf一样,sscanf_s相同支持正則表達式

sscanf_s(stime.c_str(), “%4d%*c%2d%*c%2d%*c%2d%*c%2d%*c%2d”, &tm_temp.tm_year, &tm_temp.tm_mon, &tm_temp.tm_mday, &tm_temp.tm_hour, &tm_temp.tm_min, &tm_temp.tm_sec ); 通过以上对照sscanf与sscanf_s的使用,能够看出后者对缓冲区安全有了很多其它的考虑,从而避免了很多不经意的烦恼。

大家都知道sscanf是一个非常好用的函数,利用它能够从字符串中取出整数、浮点数和字符串等等。

它的用法简单。特别对于整数和浮点数来说。但新手可能并不知道处理字符串时的一些高级用法,这里做个简要说明吧。

  1. 常见使用方法。

下面是引用片段:   char str[512] = ;   sscanf(“123456 “, “%s”, str);   printf(“str=%sn”, str);

  2. 取指定长度的字符串。如在下例中,取最大长度为4字节的字符串。

下面是引用片段:   sscanf(“123456 “, “%4s”, str);   printf(“str=%sn”, str);

  3. 取到指定字符为止的字符串。如在下例中。取遇到空格为止字符串。

下面是引用片段:   sscanf(“123456 abcdedf”, “%[^ ]”, str);   printf(“str=%sn”, str);

  4. 取仅包括指定字符集的字符串。如在下例中。取仅包括1到9和小写字母的字符串。

下面是引用片段:   sscanf(“123456abcdedfBCDEF”, “%[1-9a-z]”, str);   printf(“str=%sn”, str);

  5. 取到指定字符集为止的字符串。

如在下例中,取遇到大写字母为止的字符串。

下面是引用片段:   sscanf(“123456abcdedfBCDEF”, “%[^A-Z]”, str);   printf(“str=%sn”, str);

发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/116614.html原文链接:https://javaforall.cn

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022年1月1,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
C++ time_t与格式化日期时间字符串的转换
代码中,第一部分是time转格式化字符串,这里要注意,time库提供了time_t和tm两种格式的时间,time_t是1970年01月01日00时00分00秒到现在所经过的秒数,而tm是一个结构体,如下:
Cloudox
2021/11/23
4.8K0
用于用户输入|的内置库函数scanf, fscanf, sscanf, scanf_s, fscanf_s, sscanf_s
开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第8天,点击查看活动详情
鲸落c
2022/12/18
1.8K0
Linux应用层系统时间写入RTC时钟的方法
Jack_Cui
2017/12/28
3.4K0
Linux应用层系统时间写入RTC时钟的方法
sscanf函数-----字符串拆分函数
sscanf的作用:从一个字符串中读进于指定格式相符的数据。利用它可以从字符串中取出整数、浮点数和字符串。 sscanf和scanf的区别:scanf是以键盘作为输入源,sscanf是以字符串作为输入源。
大忽悠爱学习
2021/03/02
3.7K0
sscanf函数-----字符串拆分函数
C风格简易本地log系统
该C风格简易log日志系统,适合与Linux平台系统,主要用于格式化输出日志到本地指定的文件中,可指定log文件数目、最大大小、行数、按时间切换等功能,可满足基本的log日志功能。从项目中提炼出来,附上使用的demo,简单易懂,能快速上手。具体接口说明,参见源码。
恋喵大鲤鱼
2018/08/03
8930
c语言函数库学习~sscanf~格式化输入
今天算是被打击到了吧,由郑轻的acm老师来我学院指导安排了个现场的小比赛,,俺们居然有还是输给一个大一的新手,,哎,情何以堪,,所以还是要重视下基础编程能力的培训,现在嘛我就开始学习下格式化的输入,,很复杂但是很有效果的。。。
十四君
2019/11/23
1.9K0
c语言函数库学习~sscanf~格式化输入
环保 HJ212协议解析
由于是做环保相关的,有时需要对212协议进行拆包和解包。HJ212协议是一种字符串协议,数据传输通讯包主要由包头、数据段长度、数据段、CRC校验、包尾组成,其中“数据段”内容包括请求编码、系统编码、命令编码、密码、设备唯一标识、总包数、包号、指令参数。请求编码为请求的时间戳,系统编码ST统一规定为22,命令编码CN为该数据包的时间类型,访问密码、设备唯一标识在对接时由平台提供,指令参数为数据内容。通讯协议的数据结构如图4所示。
ccf19881030
2020/09/22
3.3K0
环保 HJ212协议解析
time&datetime模块详解
 一.time模块 1.时间格式转换图: 2.time模块中时间表现的格式主要有三种:   a、timestamp时间戳,时间戳表示的是从1970年1月1日00:00:00开始按秒计算的偏移量   b
用户1679793
2018/04/28
1.2K0
time&datetime模块详解
C/C++获取本地时间常见方法
(1)UTC (Coordinated Universal Time):协调世界时,又称世界标准时间。曾由格林威治平均时间(Greenwich Mean Time,GMT)提供,现在由原子钟提供。比如,中国内地的时间与UTC的时差为+8,也就是UTC+8。美国是UTC-5。
恋喵大鲤鱼
2018/08/03
1.4K0
C语言标准的输入输出
C语言提供了`printf()`和`scanf()`两个用于格式化输入输出的函数。`printf()`函数用于向控制台输出格式化的数据,而`scanf()`函数用于从控制台读取格式化的数据。
GG Bond1
2024/06/14
3890
【C语言笔记】时间日期函数
time.h是C/C++中的日期和时间头文件。用于需要时间方面的函数。下面分享time.h头文件中几个常用函数的用法:
正念君
2019/06/26
3.5K0
【C语言笔记】时间日期函数
介绍Linux下时间处理的相关操作(RTC、延时、闹钟、转换)
这篇文章主要介绍Linux下时间处理的相关函数与操作。 比如: 系统时间设置,读取、RTC时间设置,读取、时间单位转换、延时函数、闹钟信号等等。
DS小龙哥
2022/01/12
3.5K0
介绍Linux下时间处理的相关操作(RTC、延时、闹钟、转换)
socket 实现服务端客户端时间同步
这个小案例主要是演示了服务端客户端通信,时间获取和设定的函数均是从网络上查询的,代码可以顺利编译运行,具体请查看代码和注释。
我与梦想有个约会
2023/10/20
3610
socket 实现服务端客户端时间同步
【C语言】时间函数详解
在C语言中,时间处理功能由标准库 time.h 提供。使用这些函数时,需要包含 #include <time.h> 头文件。以下是一些常用的时间函数的详细讲解,包括函数原型、参数说明、返回值说明以及示例代码和表格汇总。
LuckiBit
2024/12/11
3680
【C语言】时间函数详解
基于EasyX的天气预报小程序
上一篇分享了:分享一个有趣的库,让你学习C语言不会觉得那么枯燥。有几位小伙伴发表了自己的看法让我陷入思考。
DeROy
2021/04/21
6830
基于EasyX的天气预报小程序
c++ format 函数包含_C语言库函数之strftime()详解
size_t strftime(char *str, size_t maxsize, const char *format, const struct tm *timeptr)
用户7886150
2021/02/17
1.2K0
c++如何获取系统当前时间(超级详细)
获取系统当前日历时间 UTC 1970-01-01 00:00:00开始的unix时间戳
风骨散人Chiam
2020/10/28
13.6K2
sscanf
sscanf与scanf类似,都是用于输入的,只是后者以键盘(stdin)为输入源,前者以固定字符串为输入源。    第一个参数可以是一个或多个 {%[*] [width] [{h | l | I64 | L}]type | ' ' | '\t' | '\n' | 非%符号} 注:   1、 * 亦可用于格式中, (即 %*d 和 %*s) 加了星号 (*) 表示跳过此数据不读入. (也就是不把此数据读入参数中)   2、{a|b|c}表示a,b,c中选一,[d],表示可以有d也可以没有d。   3、
用户1624346
2018/04/11
1.8K0
UNIX时间戳和北京时间的相互转换
准确的说,应该是unix时间戳,是从1970年1月1日(UTC/GMT的午夜)开始所经过的秒数,不考虑闰秒。一个小时表示为UNIX时间戳格式为:3600秒;一天表示为UNIX时间戳为86400秒,闰秒不计算。在很多API接口中,数据的更新时间并不是一个字符串,而是一个长整形数据,如1593003485,表示是北京时间2020-06-24 20:58:05。
单片机点灯小能手
2020/07/17
11.6K1
UNIX时间戳和北京时间的相互转换
mysql 数据库to_days,str_to_date函数的使用
如果你操作数据库时想通过时间加以限制,那么请以这样的形式存储时间:year-month-day hour:minute:second,给一个linux下的存储方法:void  *gettime(char name[])   
MickyInvQ
2020/09/27
8980
相关推荐
C++ time_t与格式化日期时间字符串的转换
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档