C语言中输入函数(scanf()、fgets()和gets())的区别详解

前言

大家都知道在C语言中,有三种主要的输入函数:scanf(),fgets()以及gets()。他们的使用方法及注意事项如下:

1.scanf()

它是一种格式化的输入方式,可一次性按照规定的格式输入多个数据域。

scanf函数是一个标准库函数,它的函数原型在头文件“stdio.h”中。与printf函数相同,C语言也允许在使用scanf函数之前不必包含stdio.h文件。

scanf函数的一般形式为:

scanf(“格式控制字符串”, 地址表列);

其中,格式控制字符串的作用与printf函数相同,但不能显示非格式字符串,也就是不能显示提示字符串。地址表列中给出各变量的地址。地址是由地址运算符“&”后跟变量名组成的。

例如:&a、&b分别表示变量a和变量b的地址。

下面以输入规定的长度的字符串为例,来说说它的使用方法和容易产生的bug。

要求:定义一个长度为10的个字符数组,由用户通过键盘为其赋值。

Code:

  char name[10];

  scanf("%9s",name);

说明:之所以使用%9s是因为我们还需要预留一个位置给字符串结束标志'\0',所以用户输入的名字最长只能为9,且其中不能包含空格类字符(空格,回车,首行缩进符),因为scanf函数认为它们是字符串的结尾。

危险:当用户输入的名字超过9个衣服时,系统将会产生段错误(segment fault),如果运气好程序可能不会提示错误,如果不好,可能内存中重要的数据被覆盖!

2.fgets(char *name, int length, fd)

头文件:include<stdio.h>

该函数从文件描述符fd指定的文件获得length个字符存入从name开始的length个内存单元中。由于其形参中规定了最大接受字符数,故不会发生像scanf函数那样的缓存溢出的问题。

要求:定义一个长度为10的个字符数组,由用户通过键盘为其赋值。

Code:

  char name[10];

  fget(name,sizeof(name),stdin);

说明:因为此处name是一个数组名,虽然它本质上是一个指针,但聪明的sizeof函数会把他区别于一般的指针变量,从而根据之前的定义求出数组的长度。但若是一般的指针变量,sizeof函数求出的值就是4或是8了。

3.gets()

它通过键盘获得字符串输入,并且没有任何字符串长度上的限制和检测,建议应该避免在我们的代码中使用该函数!

要求:定义一个长度为10的个字符数组,由用户通过键盘为其赋值。

Code:

  char name[10];

  gets(name);

注意:本函数可以无限读取,不会判断上限,所以程序员应该确保buffer的空间足够大,以便在执行读操作时不发生溢出。为了避免这种情况,我们可以用fgets()来替换gets()。

危险:任何时候均要避免使用该函数,虽然它存在已经有很长一段时间了。

区别:

1.是否对用户输入的字符个数有所限制?

两者均有所限制,但scanf函数需要你在格式化说明符中显示注明,若不注明则无限制,可能会导致溢出事故;fgets函数则将其作为一个形参予以强制规定。

2.用户是否可以同时输入多个域的数据?

scanf函数可以通过添加多个格式化输入说明符来实现多域输入,而fgets函数每次仅能对一个域赋值。

3.用户输入的字符串中可以包含空格类字符吗?

scanf函数会把空格符当做字符串的结束符,故不可以在一个字符串中含有空格。而否则可以。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对我们的支持。

(0)

相关推荐

  • 利用C语言玩转魔方阵实例教程

    魔方阵 魔方阵,古代又称"纵横图",是指组成元素为自然数1.2-n的平方的n×n的方阵,其中每个元素值都不相等,且每行.每列以及主.副对角线上各n个元素之和都相等. 如3×3的魔方阵: 8 1 6 3 5 7 4 9 2 魔方阵的排列规律如下: (1)将1放在第一行中间一列: (2)从2开始直到n×n止各数依次按下列规则存放:每一个数存放的行比前一个数的行数减1,列数加1(例如上面的三阶魔方阵,5在4的上一行后一列): (3)如果上一个数的行数为1,则下一个数的行数为n(指最下一行);

  • 利用C语言实现“百马百担”问题方法示例

    前言 百马百担问题,有100匹马,驮100担货,大马驮3担,中马驮2担,两匹小马驮1担,问共有多少种驮法?且各种驮法中大.中.小马各多少匹? [分析] 1.定义整型变量m.n.k分别存放大马匹数.中马匹数.小马匹数: 2.定义整型变量sum存放共有几种驮法,且sum赋初值为0: 3.根据题意,大马.中马.小马共100匹:大马.中马.小马驮100担货满足如下关系: m+n+k=100(匹) 3*m+2*n+1/2*k=100(担) 4.三个未知数,两个方程,此题有若干组解: 5.计算机求解此类问题

  • C语言结构体定义的方法汇总

    什么是结构体? 在C语言中,结构体(struct)指的是一种数据结构,是C语言中聚合数据类型(aggregate data type)的一类.结构体可以被声明为变量.指针或数组等,用以实现较复杂的数据结构.结构体同时也是一些元素的集合,这些元素称为结构体的成员(member),且这些成员可以为不同的类型,成员一般用名字访问. 结构体与数组的比较 (1) 都由多个元素组成 (2) 各个元素在内存中的存储空间是连续的 (3) 数组中各个元素的数据类型相同,而结构体中的各个元素的数据类型可以不相同 结

  • C语言实现二叉树的基本操作

    二叉树是一种非常重要的数据结构.本文总结了二叉树的常见操作:二叉树的构建,查找,删除,二叉树的遍历(包括前序遍历.中序遍历.后序遍历.层次遍历),二叉搜索树的构造等. 1. 二叉树的构建 二叉树的基本构建方式为:添加一个节点,如果这是一棵空树,则将该节点作为根节点:否则按照从左到右.先左子树后右子树的顺序逐个添加节点.比如依次添加节点:1,6,10,2,7,11,则得到的二叉树为: 在这里,我们需要借助一个链表来保存节点,以实现二叉树的顺序插入,具体做法如下: 1.0 初始化一个用来保存二叉树节

  • c语言通过opencv实现轮廓处理与切割

    注意在寻找轮廓时要选择中寻找外层轮廓 RETR_EXTERNAL #include "opencv/cv.h" #include "opencv/highgui.h" using namespace std; using namespace cv; int main() { Mat srcimg=imread("./22.jpg"); Mat dst; cvtColor(srcimg,dst,CV_BGR2GRAY); threshold(dst

  • c语言实现基数排序解析及代码示例

    1. 基数排序(radixsort)属于"分配式排序"(distributionsort),又称"桶子法"(bucketsort)或binsort,顾名思义,它是透过键值的部份资讯,将要排序的元素分配至某些"桶"中,藉以达到排序的作用. 2.基数排序的实现方法分为两种: 最高位优先(MostSignificantDigitfirst)法,简称MSD法:先按k1排序分组,同一组中记录,关键码k1相等,再对各组按k2排序分成子组,之后,对后面的关键码

  • C语言创建动态dll和调用dll(visual studio 2013环境下)

    第一部分:创建动态dll库. 1.打开visual studio 创建一个控制台应用程序. 2.选择DLL,空项目. 3.点击源文件,创建一个main.c文件 4.在main.c中写入一个简单的函数,内容如下: __declspec(dllexport) int mymax(int a,int b){ return a + b; } 5.编译生成. 6.在项目的目录有dll和lib两个生成好的文件. 第二部分:在新建项目中使用dll. 7.新建一个c的控制台应用程序UseDll,把Dll.dll

  • C语言数据结构之学生信息管理系统课程设计

    本文实例为大家分享了学生信息管理系统设计的具体代码,供大家参考,具体内容如下 建立一个动态链表,链表中每一结点包括:学号.姓名.性别.年龄.成绩.程序能实现以下功能: 建立链表      显示链表      查找链表中是否存在某个元素,并显示这个元素的所有信息,若没有这个元素则显示"无此记录!"的信息.      删除链表中指定学号的结点.      在链表中指定的位置插入一个新结点(学号不能和其他结点重复). 要求:程序运行中,先显示实现以上功能所构成的菜单,然后根据选项调用相应程序

  • C语言中回调函数和qsort函数的用法详解

    目录 回调函数 指向函数指针数组的指针 qsort(qulick sort)-库函数 回调函数 通过函数指针调用的函数,如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数. 回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应. 举例: #include<stdio.h> void menu() { printf("*************************

  • Go中的nil切片和空切片区别详解

    Go语言在声明变量的时候,会自动对变量对应的内存区域进行初始化操作.每个变量会被初始化成其类型的默认值,例如: 整型和浮点型变量的默认值为0. 字符串变量的默认值为空字符串. 布尔型变量默认为false. 切片.函数.指针变量的默认为nil. func main() { var s1 []int // nil切片 s2 := make([]int,0) // 空切片 s4 := make([]int,0) // 空切片 s5 := []int{} // 空切片 } 直接看代码,不同声明方式:使用

  • MySQL中Decimal类型和Float Double的区别(详解)

    MySQL中存在float,double等非标准数据类型,也有decimal这种标准数据类型. 其区别在于,float,double等非标准类型,在DB中保存的是近似值,而Decimal则以字符串的形式保存数值. float,double类型是可以存浮点数(即小数类型),但是float有个坏处,当你给定的数据是整数的时候,那么它就以整数给你处理.这样我们在存取货币值的时候自然遇到问题,我的default值为:0.00而实际存储是0,同样我存取货币为12.00,实际存储是12. 幸好mysql提供

  • java 中同步方法和同步代码块的区别详解

    java 中同步方法和同步代码块的区别详解 在Java语言中,每一个对象有一把锁.线程可以使用synchronized关键字来获取对象上的锁.synchronized关键字可应用在方法级别(粗粒度锁)或者是代码块级别(细粒度锁). 问题的由来: 看到这样一个面试题: //下列两个方法有什么区别 public synchronized void method1(){} public void method2(){ synchronized (obj){} } synchronized用于解决同步问

  • include包含头文件的语句中,双引号和尖括号的区别(详解)

    #include <>格式:引用标准库头文件,编译器从标准库目录开始搜索 #incluce ""格式:引用非标准库的头文件,编译器从用户的工作目录开始搜索 预处理器发现 #include 指令后,就会寻找后跟的文件名并把这个文件的内容包含到当前文件中.被包含文件中的文本将替换源代码文件中的#include指令,就像你把被包含文件中的全部内容键入到源文件中的这个位置一样. #include 指令有两种使用形式 #include <stdio.h> 文件名放在尖括号

  • js删除数组中的元素delete和splice的区别详解

    例如有一个数组是 :var textArr = ['a','b','c','d']; 这时我想删除这个数组中的b元素: 方法一:delete 删除数组 delete textArr[1]  结果为: ["a",undefined,"c","d"] 只是被删除的元素变成了 undefined 其他的元素的键值还是不变. 方法二:aplice 删除数组 splice(index,len,[item]) 注释:该方法会改变原始数组. index:数组开

  • 对Django 中request.get和request.post的区别详解

    Django 中request.get和request.post的区别 POST和GET差异: POST和GET是HTTP协议定义的与服务器交互的方法.GET一般用于获取/查询资源信息,而POST一般用于更新资源信息.另外,还有PUT和DELETE方法. POST和GET都可以与服务器完成查,改,增,删操作. GET提交,请求的数据会附在URL之后,以?分割URL和传输数据,多个参数用&连接: POST提交,把提交的数据放置在HTTP包的包体中:因此,GET提交的数据会在地址栏中显示出来,而PO

  • python中的数组赋值与拷贝的区别详解

    具体的注解我已经写在了程序里面:通俗的解释了python里面的浅拷贝与深拷贝的不同,请看程序. # -*- coding: utf-8 -*- import numpy as np import copy as cp import matplotlib.pyplot as plt import time import math fig = plt.figure() ax = fig.add_subplot(241) # 定义一个多维数组 x = np.array([[1, 2, 3], [4,

  • PyTorch中 tensor.detach() 和 tensor.data 的区别详解

    PyTorch0.4中,.data 仍保留,但建议使用 .detach(), 区别在于 .data 返回和 x 的相同数据 tensor, 但不会加入到x的计算历史里,且require s_grad = False, 这样有些时候是不安全的, 因为 x.data 不能被 autograd 追踪求微分 . .detach() 返回相同数据的 tensor ,且 requires_grad=False ,但能通过 in-place 操作报告给 autograd 在进行反向传播的时候. 举例: ten

  • PyTorch中torch.tensor与torch.Tensor的区别详解

    PyTorch最近几年可谓大火.相比于TensorFlow,PyTorch对于Python初学者更为友好,更易上手. 众所周知,numpy作为Python中数据分析的专业第三方库,比Python自带的Math库速度更快.同样的,在PyTorch中,有一个类似于numpy的库,称为Tensor.Tensor自称为神经网络界的numpy. 一.numpy和Tensor二者对比 对比项 numpy Tensor 相同点 可以定义多维数组,进行切片.改变维度.数学运算等 可以定义多维数组,进行切片.改变

随机推荐