除了scanf()还可以用fgets()

还可以用另一个函数来输入文本数据:fgets()。和scanf()函数一样,fgets()接收char指针,不同的是,你必须给出最大长度:

除了scanf()还可以用fgets() - 图1

也就是说当调用fgets()时不可能一不小心忘记设置长度,因为它就出现在了函数的签名中,所以不得不加这个参数。另外,注意fgets()缓冲区大小把\0字符也算了进去,所以不必像scanf()那样把长度减1。

关于fgets(),还需要知道什么?

fgets()配合sizeof一起使用

上面这段代码用sizeof运算符设置了最大长度,小心,别忘了sizeof返回变量占用空间的大小。在上面这段代码中,food是数组变量,所以sizeof返回了数组的大小;如果food是指针变量,sizeof仅仅会返回指针的大小。

如果你要向fgets()函数传递数组变量,就用sizeof;如果只是传指针,就应该输入你想要的长度。

除了scanf()还可以用fgets() - 图2

除了scanf()还可以用fgets() - 图3古墓谜案

fgets()函数其实是从一个更古老的函数演变而来的,它叫gets()。

尽管我们说fgets()scanf()更加安全,但它的祖先gets()才是最危险的家伙。为什么?因为gets()函数没有任何限制:

除了scanf()还可以用fgets() - 图4

虽然gets()函数已经行走江湖很多年了,但真的不应该用它。

 

除了scanf()还可以用fgets() - 图5拳王争霸赛

醒醒!醒醒!我们期待已久的拳王争霸赛现在开始。身披红色战袍的是身轻如燕、灵活机动但是有一点点危险的数据输入坏小子:scanf()。蓝方朴实无华、安全可靠,你一定想把他介绍给你妈妈:他就是fgets()

除了scanf()还可以用fgets() - 图6

这两个急脾气的函数之间展开了一场干净漂亮的决斗。显然,如果需要输入由多个字段构成的结构化数据,可以使用scanf();而如果想要输入一个非结构化的字符串,fgets()将是你的不二之选。

三猜一

在Head First酒吧的地下室中,有人在玩“三猜一”。某人不停地交换三张牌的位置,你必须屏息凝视,指出Q去了哪儿。当然,在Head First酒吧中,他们并没有用真牌,而是用了代码。下面是他们所使用的程序:

除了scanf()还可以用fgets() - 图7

代码旨在交换字符串“JQK”中的三个字母。别忘了,在C语言中,字符串只是一个字符数组。程序不停交换字符的位置,最后显示字符串。

玩家把钱押到他们认为是Q的那个数组元素上,然后编译并运行代码。

哎呀……存储器故障……

看来老千的代码出了一点问题,当代码在酒吧的笔记本电脑上编译、运行时,发生了:

除了scanf()还可以用fgets() - 图8

而且,当这帮人把同一段代码放到不同计算机和不同操作系统上编译并运行时,得到了一大堆不同的错误:

除了scanf()还可以用fgets() - 图9

代码错在哪里?

除了scanf()还可以用fgets() - 图10

是时候使用你的直觉了,别想太多,但猜无妨。请通读以下候选答案,选出你认为正确的那一个。

你认为问题出在哪里?

除了scanf()还可以用fgets() - 图11

 

除了scanf()还可以用fgets() - 图12

是时候使用你的直觉了。你通读了以下候选答案,选出了你认为正确的那一个。

你认为问题出在哪里?

除了scanf()还可以用fgets() - 图13