你的sscanf用对了吗
用sscanf解析输入字符串
我们平常编写的很多应用程序都会处理各种各样的输入,这些输入或来自本地文件,或来自网络,或来自用户的输入。今天,让我们来看看sscanf这个和字符串相关的函数可能给你带来的麻烦。
下面是演示代码,这段代码将一些以字符串形式保存的数据加载到程序中。这些字符串可以来自任何地方,本演示代码对字符串进行了硬编码。
struct Data
{
char item1;
char item2;
char item3;
char item4;
}; int main()
{
Data data;
memset(&data, , sizeof(data)); char data1[] = "";
char data2[] = "";
char data3[] = "";
char data4[] = ""; sscanf_s(data4, "%d", &data.item4);
sscanf_s(data3, "%d", &data.item3);
sscanf_s(data2, "%d", &data.item2);
sscanf_s(data1, "%d", &data.item1); printf_s("item1:%d\n", data.item1);
printf_s("item2:%d\n", data.item2);
printf_s("item3:%d\n", data.item3);
printf_s("item4:%d\n", data.item4); getchar();
return ;
}
你觉得执行结果会是什么?

奇怪吗?
分析
让我们分析一下:
第19行代码将4赋值给了item4,第20行代码将3赋值给了item3, 第21行代码将2赋值给了item2, 第22行代码将1赋值给了item1。似乎没什么问题。
还是来调试下程序吧。
下面几张图片演示了程序在执行过程中的内存布局
执行第一条sscanf_s前的内存布局

执行第一条sscanf_s后的内存布局

执行第二条sscanf_s后的内存布局

执行第三条sscanf_s后的内存布局

执行第四条sscanf_s后的内存布局

到这里,相信大家都已经明白程序的输出结果为何是1,0,0,0了。
演示代码不仅发生了内存越界,而且后续所有的输入都覆盖了上一条的执行结果。
罪魁祸首就是sscanf_s中的格式字符串"%d","%d"表明将输入字符串作为一个int类型来保存到目标地址处。而演示代码的书写方式很显然不符合Data这个结构体中各成员所声明类型的要求。
将个数字符串修改为"%c"后,程序执行正确:

当然,我们其实可以在编译阶段发现这类问题

结语
通过今天这个演示,更加让自己明白了一定要多留意编译期间的警告信息,尽全力将其消灭。
本博客仅仅演示了sscanf_s这类函数的冰山一角,对于其他需要注意的地方可以参考Format Specifiers Checking
你的sscanf用对了吗的更多相关文章
- C语言关于利用sscanf实现字符串相加减
#include<stdio.h>#include<string.h>void main(){ int a; int b; char str1[10] = "9999 ...
- sscanf提取字符串中的数据php
1.需求 理解sscanf的作用 2.例子 $str = "age:30 weight:60kg"; sscanf($str,"age:%d weight:%dkg&qu ...
- sscanf与正则表达式(转)
今天翻google reader的时候看到这样一篇文章,介绍的是sscanf的高级用法.直到今天我才知道sscanf是可以直接用正则表达式的,惭愧. 在msdn中sscanf的声明如下 int ssc ...
- C语言函数sscanf()的用法
从文件读取数据是一件很麻烦的事,所幸有sscanf()函数. C语言函数sscanf()的用法 sscanf() - 从一个字符串中读进与指定格式相符的数据. 函数原型: int sscanf( st ...
- sscanf()函数的使用及其实例
资料引自: 传送门 sscanf函数原型: Int sscanf( const char * src, const char * format, ...); int scanf( const char ...
- C 语言sscanf
C语言以sscanf逗号作为分割符 ]={}; ]={}; ]={}; sscanf(],&buf_b[],&buf_b[]); printf("************** ...
- Babelfish(二分查找,字符串的处理略有难度,用sscanf输入)
Babelfish Time Limit: 3000MS Memory Limit: 65536K Total Submissions: 28581 Accepted: 12326 题目链接: ...
- (转)sscanf() - 从一个字符串中读进与指定格式相符的数据
(转)sscanf() - 从一个字符串中读进与指定格式相符的数据 sscanf() - 从一个字符串中读进与指定格式相符的数据. 函数原型: Int sscanf( string str, stri ...
- sscanf函数
sscanf函数用法举例 #include <stdio.h> #include <string.h> #define N 512 int main() { char buf[ ...
- hdu 1036 (I/O routines, fgets, sscanf, %02d, rounding, atoi, strtol) 分类: hdoj 2015-06-16 19:37 32人阅读 评论(0) 收藏
thanks to http://stackoverflow.com/questions/2144459/using-scanf-to-accept-user-input and http://sta ...
随机推荐
- Cacti监控Windows主机,Windows主机的正确配置
使用cacti监控Windows主机的时候经常遇到无法获取Windows主机的snmp信息和Windows主机的硬件信息,主要原因是Windows主机没有正确配置snmp,以下是正确的配置步骤:1.安 ...
- 关于List、Set集合以及Map的使用
package tingjizifu; import java.util.*; public class TongJi { /* * 使用Scanner从控制台读取一个字符串,统计字符串中每个字符出现 ...
- Delphi之TreeView
TreeView是Delphi中使用频率比较高的一个控件,虽然使用次数很多,但总结不够.借着这次做GDW原型的机会总结一下,写的过程中也会参考网上的博文. TTreeView.TTreeNodes和T ...
- V9 二次开发技术篇之 模型数据库
应V9粉丝的建议,本人今天讲一下 MVC中的M 数据库模型 首先 在 phpcms\model 建一个模型文件test_model.class.php <?phpdefined('IN_PHP ...
- Ubuntu 12.04更换显示器后显示“显示不支援”,只能进恢复模式工作
以前用的一台14寸液晶,换成17寸后,进入系统显示器上“显示不支援” .仔细观查,电脑硬盘自检能显示后,后面都是黑屏. 解决过程. 因为grub 启动菜单不能显示.盲按方向键,发现菜单里的其它项目可 ...
- 用dup2和dup产生一份file descriptor 的拷贝
在类Unix操作系统里面,.dup2和dup都通过系统调用来产生一份file descriptor 的拷贝. dup对我来说还很简单 int dup(int filedes); dup2就 ...
- 怎么加sudo权限
安装好Debian后还不能使用sudo如果没有安装sudo,则在root用户下apt-get install sudo在root设置sudoers配制文件chmod +w /etc/sudoersvi ...
- IO定时器
IoInitializeTimer 初始化定时器 IoStartTime 开启定时器 IoStopTimer 停止定时器 回调函数 VOID IoTimer( __in struct DEVICE_O ...
- 对比iOS网络组件:AFNetworking VS ASIHTTPRequest
对比iOS网络组件:AFNetworking VS ASIHTTPRequest 作者 高嘉峻 发布于 2013年2月28日 | 7 讨论 分享到:微博微信FacebookTwitter有道云笔记邮件 ...
- git设置过滤忽略的文件或文件夹
我们一般向代码仓库提交项目的时候,一般需要忽略编译生成的中间文件以及文件夹的提交,因为它们是无用的,而且也会占用仓库的空间.一般只用提交.pro,.sln,makefile,程序源文件等编译必须用到的 ...