title: 你真的会用C语言的fscanf_s吗
date: 2021-06-21 00:28:05


1.前言

最近学校让做一个C语言工程实践,我写的是一个基于链表的图书管理系统,本来这个系统的难度不是很大,但是在写的过程中总是会出一些莫名奇妙的Bug,接下来就让我给大家分享我在这个项目中踩过哪些坑,希望能够帮到大家少走一些弯路。

2.一切还得从编辑器说起

2.1.DEV++

这是我入门C语言用的编辑器,这个编辑器还是很适合新手用的,相对简单的操作步骤,以及自带编译环境,不用像CLion,VSC那样自行配置。我还是比较推荐新手用它的,除了它对新手更加友好以外,其相对笨拙的编辑提示(没有代码补全功能)有利于巩固基础知识。

不过DEV相对来说太笨拙,没有代码智能检测,也就是说有可能你会因为一些很低级的语法错误找bug找半天,而其他编辑器在你出错时会直接给你爆红

#include<stdio.h>
int mian(void)
{printf("hello world");return 0;
}

曾经初学我就因为上面的错误而浪费了我好多时间,不知道聪明的你有没有发现哪里错了呢。

2.2.Clion

后来因为用惯了IDEA,就考虑迁移到Clion,不得不说,Clion强大的功能值得大家为它付费,不过官网有社区免费版,对于绝大多数人社区版足够用了。在校学生还可以申请学校的教育邮箱免费使用JB全家桶

但是Clion也有它的缺点,对于没有接触过JB的小伙伴,编辑器本身上手需要一点的时间。并且还要自行下载配置编译环境,对于新手来说直接用Clion可能会被直接劝退。(今天又是一个劝退小技巧.jpg)

2.3.VS2019

终于说到了VS,怎么说呢,网上很多人都在说VS功能强大,但是这几天我用下来的感觉并不好。

第一:VS2019的占用实在是太大了,一键配置好C++的功能插件有9个G之大,对于很多硬盘空间不够的小伙伴来说这点还是难以接受

第二:它的代码补全真的是让人有点恼火,用惯了Clion之后习惯在代码补全提示出来按回车就可以直接把代码补全,但是VS2019还要按一下上下箭头选中你要补全什么代码,直接按回车不行,就很烦。

第三:也是我主要想说的,它会强制我们使用安全函数,比如gets要用gets_s,fopen要用fopen_s,fscanf要用fscanf_s等,然后我们学校教的都是较为老的C标准,这些以前我都还没接触过,倒是花了我很多时间去了解这些函数,尤其是我接下来说的fscanf_s;

3.fscanf_s与fscanf

在写图书管理系统时遇到结构体的读写文件,但是又不想用二进制的代码块读写,因为这样写进文件的数据在文件中打开会乱码。就想着用fscanf来读写,然后VS让我用fscanf_s,以前都还没接触过这个函数,在网上搜了很多也没看到对他讲解较为详细的教程(可能是我太菜了。。。。。)

3.1.区别

其实二者的区别就是fscanf_s比fscanf多了个域宽检查,会多一个参数

fscanf

FILE* fp;
fopen_s(&fp, "stu.txt", "r");
char str[20];
if(fp)
{   fscanf(fp,"%s",str);fclose(fp);
}

fscanf_s

FILE* fp;
fopen_s(&fp, "stu.txt", "r");
char str[20];
if(fp)
{   fscanf_s(fp,"%s",str,20);fclose(fp);
}

看出区别了吗,我猜聪明的你肯定看出两者有什么区别,fsanf_s会比fscanf多一个说明要读出数据内存大小的数字。现在读单个没有问题,那我们要读多个数据怎么办呢。

3.2.fscanf_s读取多个数据

FILE* fp;
fopen_s(&fp, "stu.txt", "r");
char s1[20];
char s2[20];
char s3[20];
if(fp)
{   fscanf_s(fp,"%s %s %s",s1,s2,s3,20,20,20);fclose(fp);
}

我猜很多小伙伴都认为因该这样读多个数据,我们现在先不说对错,实践出真知,我们先放在VS里面跑一跑再说。

#include<stdio.h>
#include<stdlib.h>
#include<string.h>int main()
{FILE* fp;FILE* fe;fopen_s(&fe, "stu.txt", "w");if (fe){fprintf(fe, "%s %s %s", "hello", "world", "C");fclose(fe);}char s1[20];char s2[20];char s3[20];fopen_s(&fp, "stu.txt", "r");if (fp){fscanf_s(fp, "%s %s %s", s1, s2, s3, 20, 20, 20);fclose(fp);}puts(s1);puts(s2);puts(s3);return 0;

结果是什么呢?

可见,VS在编译时并没有给你报错,但是在运行时会发生异常。如果对异常信息不熟的小伙伴这时候肯定要摸不着头脑了(没错,说的就是我自己,哈哈哈哈),是不是感觉很坑。

那么,正确的写法是怎样的呢?我试着在网上找了很多技术博客,可是并没有找到有对此说明的教程。向身边的小伙伴求助,他让我试试在后面直接写所有的总内存大小:

fscanf_s(fp, "%s %s %s", s1, s2, s3, 60);

可是这样的写法还是是错误的,报错和上面的如出一辙。最后,我终于把正确用法试出来了

#include<stdio.h>
#include<stdlib.h>
#include<string.h>int main()
{FILE* fp;FILE* fe;fopen_s(&fe, "stu.txt", "w");if (fe){fprintf(fe, "%s %s %s", "hello", "world", "C");fclose(fe);}char s1[20];char s2[20];char s3[20];fopen_s(&fp, "stu.txt", "r");if (fp){fscanf_s(fp, "%s %s %s", s1,20, s2,20, s3,20);fclose(fp);}puts(s1);puts(s2);puts(s3);return 0;

运行结果:

可见,这样改了之后就对了,并没报错了。

3.3.踩坑+1

是不是觉得上面那样就完了呢?那我们遇到同时读多个数字和多个字符串的时候怎么办呢?是不是好多小伙伴都是这样想的?

#include<stdio.h>
#include<stdlib.h>
#include<string.h>int main()
{FILE* fp;FILE* fe;fopen_s(&fe, "stu.txt", "w");if (fe){fprintf(fe, "%s %s %s %d %d", "hello", "world", "C",5,6);fclose(fe);}char s1[20];char s2[20];char s3[20];int a = 0, b = 0;fopen_s(&fp, "stu.txt", "r");if (fp){fscanf_s(fp, "%s %s %s %d %d", s1, 20, s2, 20, s3, 20,&a,4,&b,4);fclose(fp);}puts(s1);puts(s2);puts(s3);printf("%d %d", a, b);return 0;

运行结果:

啊?怎么报错了呢?小朋友你是否有很多问号?那么这是怎么回事呢?其实我也不是很清楚,哈哈哈哈。(菜狗+1)

但是我知道怎么改正。

其实方法很简单,只需要这样改就没错了:

fscanf_s(fp, "%s %s %s %d %d", s1, 20, s2, 20, s3, 20,&a,&b);

现在我们运行试试:

成功读出数据并输出!

3.4.小结

我对上面最后出错的理解就是读字符串的时候我们需要给他指定长度,防止内存溢出。但是对于整型我们就不用给他指定了。具体原因我也不是很清楚,如果有大佬知道可以在评论区解释一下。

走到这一步真是不容易,我在这些坑上不知道浪费了多少时间。害,对于我这种菜鸡来说一遇到异常信息就抓瞎,只知道肯定是内存访问冲突了,就是不知道具体哪里错了,只能一点一点试,百度。百度上还搜不出。

好的,今天的分享到这里就结束了,希望能够帮助到大家。如果有哪里写得不对的地方请大佬们指正。敬礼.jpg

你真的会用C语言的fscanf_s吗相关推荐

  1. AI 真的能够理解人类语言吗?

    作者 | Melanie Mitchell 译者 | 弯月 出品 | CSDN(ID:CSDNnews) 2011年,IBM 的人工智能系统沃森参加综艺节目<危险边缘>,并获得了冠军,当时 ...

  2. 学python必须得英语精通吗_Python无用武之地?只能说你是真的没有精通Python语言(附教程)...

    Python的热度一直高居不下,运维,自动化测试,后端开发,机器学习...Python的用武之地真的太多了! "人生苦短,我用Python",对于普通职场人士来说,Python简单 ...

  3. 精通C语言Java怎么样_作为一个优秀的程序员,真的需要精通C语言吗?

    从事嵌入式开发多年,使用C语言开发已经超过十个年头,除了C语言还用C++,java,python做过项目,程序员的优秀编程语言仅仅占据一部分,而且也不会只是针对C语言,现在很多的编程高手也不懂的C语言 ...

  4. R语言实战应用精讲50篇(十八)-R语言实现分词、词频与词云案例解析

    前言 我真的超爱R语言,原因之一就是R有许多已经写好."开箱即用"的程序包可以直接拿来用:要知道,程序包减少了多少工作量.当然,其他语言也有类似的包,但是貌似没那么多.没那么细.这 ...

  5. 俄罗斯游戏软件:C语言应用初步感受

    俄罗斯游戏软件:C语言应用初步感受 C语言课程设以一节课,老师提供了一个C语言的飞俄罗斯方块让我们感受,我们所学的C语言课程,主要是各种语句的练习,这次是用我们所学过的知识来感受一个实际的系统. 首先 ...

  6. 开发语言大爆炸的时代,究竟谁主沉浮?

    开发语言大爆炸的时代,究竟谁主沉浮? 当这个系列本来打算是写人物的,而且是写我们身边那些优秀的开发者,然而当第一篇文章,写的是关于我们长沙.NET社区的优秀开发者邹琼俊,发表在博客园之后,有一位也是昔 ...

  7. 《玩转D语言系列》二、D语言现状、基本规定和相关资源介绍

    这算是本系列文章的一个序吧,主要是为以后的学习做铺垫,文本分为三个部分,第一部分是对于网上一些比较旧的资料的问题的一些更正,当然我也不可能看过所有的资料,难免会有遗漏.第二部分是D语言最基本的规定,第 ...

  8. 为什么会有这么多种程序设计语言?

    传说人类建造通天塔触怒上帝,上帝施法使人类语言混乱彼此之间无法交流.这就是说各种各样的语言其实就是祸乱之源--只会导致交流的不便.可是看看如今的程 序设计语言的数量,你会怀疑人类是否又在造" ...

  9. ruby语言仅仅是昙花一现

    Ruby语言本身存在非常久了,在国内一直没火过.非常多人仅仅是知道有这样的语言,会的人少之又少.不论什么一种语言坚持十来年的发展,变得越来越好,一定有它不平常的地方.不能任意的去比較语言本身的好与坏. ...

最新文章

  1. 核磁共振影像数据处理-3-DTI基础、Li‘s have a solution and plan.
  2. Hibernate——简单的增、删、改、查操作
  3. 助理来也胡一川:用数据驱动打造智能行业助理(技术+业务)
  4. ES6 数值的扩展
  5. struts单例模式 java_Java单例设计模式详细介绍
  6. String类以及String与基本数据类型/char[]/byte[]之间的转换
  7. VGG16与SSD算法Tensorflow代码实现对比
  8. RequestDispatcher对象的应用-请求转发
  9. win11中gpedit.msc找不到文件怎么办 windows11gepdit.msc找不到文件的解决方法
  10. SqlServer保留几位小数的两种做法
  11. HBase基本操作:JAVA API操作
  12. python图书管理实训报告总结_图书管理系统实训报告正文
  13. delphi android 音乐播放器,Mcool音乐播放器
  14. Weka的下载与安装
  15. java分词支持拼音_ik中文分词器及拼音分词器试用
  16. 【年终总结】回顾我平凡且不平凡的 2021
  17. Python 截屏 - lone112 - 博客园
  18. python篮球-python画篮球
  19. 连续分布——正态分布、卡方分布、t分布、F分布
  20. 【Python游戏】基于化学方程式的基础上,用Python实现一个消灭泡泡小游戏 | 附源码

热门文章

  1. 支持HEVC/H265 RTMP接收的FFMPEG/FFPLAY WINDOWS版本
  2. VC常用控件用法(转载)
  3. 人工势场算法 Matlab版源码
  4. 华为杯第一届中国研究生网络安全创新大赛-Bit_QR
  5. systools ssd data recovery怎么用呢
  6. 使用JOL工具计算Java对象的大小
  7. ul(有序列表)可以排序?
  8. 【第01题】A + B | 基础输入输出,开启学习C语言打卡的序章
  9. A算法和A*算法详解
  10. PS创建选区的工具-----快速选择和魔棒