一文看懂C语言I/O
一文看懂 C 语言 I/O
再会吧,这宝贵的片刻和短暂的时机限制了我在情义上的真挚表示,也不能容我们畅叙衷曲,这本来是亲友重逢所应有的机缘;愿上帝赐给我们美好的未来,好让我们开怀畅谈!再一次告别;勇敢作战吧,祝你胜利!——威廉•莎士比亚《查理三世》
0 说在前面
当你看到这篇文章时,不妨回想一下你当初第一次用 C 语言“Hello World!”时是什么样的心情。那是你第一次成功使用神秘代码完成了和计算机的交流。尽管展示信息的黑框框让你可能不大习惯这样一种沟通方式,但这难道不也有点电影里黑客那感觉了~?
不知不觉半年过去了,你为了数据结构作业绞尽脑汁,敲下最后一个分号,鼠标轻点”编译运行“。黑色高级框框跳出来,尴尬而不失礼貌地对你说:
1 |
|
你质问:
“你怎么了,为什么要这样对我……呜呜~”
是啊,你认识了这个框框那么久,它早已熟悉你写 bug 的习惯,而你却摸不清它的性情。你是时候应该了解一下它了。
1 标准输入输出
“你好,我叫终端,也叫控制台,英文名是 Terminal,也叫 Console,很高兴成为你的朋友。”
“你不记得我啦?我就是你每次运行程序的时候跳出来跟你聊天的那位。请看——”
“其实我并不是你的程序本体,你的程序躲在电脑里面,是它派我来跟你说话的,”
“当你在键盘上敲敲的时候,我会帮你把你输入的字符显示出来,这样你就知道你输入的对不对了,”
“然后你一行输完,按下回车,我帮你把整行字符串都传给你的程序,你的程序就会对一行字符串进行解析,如果有 scanf 函数的话还会逐个解析出里面的数字、字符等等,”
“当你的程序算完之后,会把输出的信息告诉我,我来显示到屏幕上。”
所谓 I/O,就是 Input/Output,即输入输出。通过终端读入和显示的就是“标准输入输出”,由于终端也是从键盘获取信息,并把信息显示在屏幕上。所以:
- 标准输入也叫键盘输入
- 标准输出也叫屏幕输出
标准输入输出的英文是 Standard Input and Output,缩写就是“stdio”,觉不觉得眼熟hhh~
——“你用的 scanf、gets、getchar 函数都是解析标准输入的,printf、puts、putchar 都是标准输出。现在知道我是干什么的了吧”
——“哦,原来是这样。但是你好丑。”
——“???那我走”
2 输出输出重定向
终端走了——你万念俱灰,把你的代码提交给希冀的评测姬。她说:
1 |
|
——“求求你在本地测好再交给我 OK?我每天判那么多代码很累了啦!”
——“emm……我好奇你怎么知道我们的代码对不对的,也是用终端吗?”
——“终端?那不是低级的 PC 才会用的东西?我们服务器不需要这个。I/O 重定向一下就行了”
现在你可以试试这样一个操作,写好一份 C 语言代码,里面有标准输入输出函数,然后添加两行这样的语句:
1 |
|
然后在你的 C 程序的同一文件夹下新建文本文档,命名为 “a.in”(注意这一步之前要确保你的电脑显示了文件后缀1)。然后在 “a.in” 里面写上你要输入的数据,Ctrl+S 保存。
编译运行你的代码,你会发现程序直接结束,黑框框没有其它输出了。
然后你在代码所在的文件夹里发现了一个名为 “a.out” 的文本文档,里面正是你要的答案。
当然 “a.in” 和 “a.out” 可以改成你喜欢的任何名字,文本文档对后缀不敏感,跟 “.txt” 是一样的。
当然你可以像我一样玩(用编辑器打开输入文件分屏出去,调试的时候不用每次在控制台输入,多是一件美事):
回过头来我们看看这两句是什么意思:
1 |
|
翻译成人话就是:
- 我要用“只读方式”打开文件 “a.in”,并用其替换标准输入;
- 我要以“只写方式”打开文件 “a.out”,并用其替换标准输出。
- 顺便说一句,只写模式 “w” 下,如果找不到文件,程序会帮你创建一个~
评测姬说:
“现在你懂了?在我拿到你的程序时,会自动帮你加上 freopen 将标准 I/O 重定向为文件 I/O,再在我的 CPU 里跑程序,跑完再对比一下你的输出和标准答案一不一样就行了。”
3 文件 I/O
此时晏老师:“多出点文件 I/O 的题,难死这帮小崽子~”
理论上来说,你会 I/O 重定向之后就可以做所有文件 I/O 的题了,大不了都用 scanf 和 gets 呗。
但是有时候让你既从标准输入读入又从文件读入~文件 I/O 也不能不会是吧。
废话了这么多,终于可以讲讲你们不大清楚的 I/O 函数的用法了:
3.1 文件指针
要熟练使用文件 I/O,要过的第一关就是文件指针,它相当于给你的文件贴一个标签,让后当你需要调用函数的时候要把文件指针作为输入变量传进去,这样才能对你的文件进行操作:
1 |
|
3.2 I/O 函数
3.2.1 输入函数:
1 |
|
在以下两个条件下,这两个函数是我最推荐大家使用的。
- 需要从输入中获取数字(直接 %d 或 %lf)
- 需要逐词对字符串处理(不含空格)
如果题不是要求类似于“读入若干行,行内有空格,对每行输出一个balabala……”这种,真心不建议用 gets 和fgets。因为 gets 很可能会产生莫名其妙的 bug(我曾解释过),fgets 不好记也不好用。
所以比如“单词统计”等等这类题,只要不怕空格,还请选择 scanf/fscanf
1 |
|
这俩大家应该挺熟了,后面那个 fprintf 就是把输出目标换成 “w” 模式的文件指针就行了。
介绍两个新朋友:
1 |
|
文件加密一题中,需要读取一整段文本,这种情况下,用这两个函数是最好的选择。
剩下的不太常用我大概说一下。
1 |
|
上面这俩函数如果想用的话还是建议好好研究一下特性小心一点使用,挺容易出 bug 的。
1 |
|
1 |
|
打开“此电脑”,在上面一栏找到“查看”按钮,点进去,找到“文件后缀名”,看是否打勾,如果没有请务必打上。↩