scanf(),getchar(),fgets(),gets(),cin.get()和cin.getline()读入字符串功能的用法详解

2023-05-16

scanf()
scanf()读取字符串直到出现空白符(空格、制表符\t、回车\n等)为止;且不读入空白符。
所在头文件:stdio.h;
语法:scanf("<格式化字符串>", <参量表>),读字符用%c,读字符串用%s。
注意:scanf在读取非空白符之前会忽略回车,读取非空白符之后,如果遇到回车会停止输入,并将该回车留着缓冲区里。

高级用法:
1。捕获规则
在出现一个转换说明符时,scanf函数会忽略前面的所有空白字符(除了%c),然后再捕获相应的数据类型,一直到最大长度或者出现空白字符
scanf("%d,%d", &a, &b);
允许的输入格式为:1,2\n;1, 2\n;1,\n2\n;
不允许的输入格式:1 ,2\n; \n1,2\n; 1,2\n;
2。%[] 字符集合
这个算scanf函数中比较高级一点的用法
[]里面填写需要捕获的字符集合,例如
char buf[20];
scanf("%[abc]", buf);  //输入abcdabcd123, buf内容为abc
scanf函数匹配[]中的所有字符,直到找到一个非[]中的字符
[]中也可以填写字符范围,例如
[a-z] //捕获包括字符从a到z的所有字符,直到找到一个非a-z的字符
[a-zA-Z] //捕获所有字母
[0-9] //捕获所有数字
[a-zA-Z0-9]捕获所有字母和数字
[a-zA-Z0-9!]捕获所有字母和数字并且捕获!(感叹号)
[]中如果第一字符为^符号则表示出现[]中的内容则停止捕获,例如
[^a-zA-Z]捕获非字母
[^0-9]捕获非数字
3。scanf中的空格和\n
scanf中的空格的作用不仅仅是捕获一个空格,它表示捕获所有空白字符(空格,换行,制表符等)直到出现一个非空白字符(\n一样)
例如:

int a,b,c;
scanf("%d\n%d\n%d",&a,&b,&c);/*输入:1 2 3			输入:1回车(或tab)2回车(或tab)3回车(或tab)效果相同*/

4。scanf中的混合输入字符和数字
在scanf当中混合输入字符和数字是一个比较烦人的问题。
如果我们直接编写代码为:

#include <stdio.h> 
int main() {
	char ch;
	int num; 
	while(scanf("%c%d", &ch, &num) == 2) {
	 printf("*%c*, *%d*\n", ch, num);
	}
	 return 0;
}

第一次scanf("%c%d");没有任何问题
第二次scanf("%c%d");字符会将上一次的\n给解析进来,就会出现了问题。
以下有几种解决该问题的办法:
解决方案1:

#include <stdio.h>
int main() {
    char ch;
    int num;
    while(scanf("%c%d", &ch, &num) == 2) {
        printf("*%c*, *%d*\n", ch, num);
		while(getchar() != '\n'); //清除上次输入残留的\n
    }
    return 0;
}

解决方案2:

#include <stdio.h>

int main() {
    char ch;
    int num;

    while(scanf(" %c%d", &ch, &num) == 2) { //前面加一个空格忽略所有空白字符
        printf("*%c*, *%d*\n", ch, num);
    }
    return 0;
}

未定义的方案(官方文档未定义,勿用):

#include <stdio.h>

int main() {
    char ch;
    int num;

    while(scanf("%c%d", &ch, &num) == 2) {
        printf("*%c*, *%d*\n", ch, num);
        fflush(stdin); //flush标准输入流
    }
    return 0;
}

gets()
gets()用于读取字符串,用回车结束输入,可接受回车键之前输入的所有字符,并用’\0’替代 ‘\n’回车键不会留在输入缓冲区中
所在头文件:stdio.h
语法:gets(字符数组名或指针);
gets能够接受空格、制表符Tab;
注意:gets函数由于没有指定输入字符大小(函数形参只有一个,为字符数组名或指针),所以会一直读取,一旦输入的字符大于数组长度,就会发生内存越界,从而造成程序崩溃或其他数据错误,是不安全的。
注意:配合使用的puts(str)函数,在输出字符串的时候自动换行。

scanf()与gets()比较
scanf :遇到回车,空格和tab键会都会认为输入结束并自动在字符串后面添加’\0’,但是回车,空格和tab键仍会留在输入的缓冲区中。scanf()可以读取所有类型的变量 。
gets:可接受回车键之前输入的所有字符,并用’\0’替代 ‘\n’。回车键不会留在输入缓冲区中,gets()用于读取字符串,用回车结束输入。

例如:输入为"\nhello\n",也就是说,先输入一个空行,然后在第二行输入"hello"并回车。scanf按照它的读取原理,把第一个’\n’作为空白符忽略掉,然后读取字符串"hello",遇到第二个’\n’时输入结束,但是第二个’\n’会被scanf残留在缓冲区里。scanf的输入结果是读入字符串"hello"。当用gets进行读取时,它遇到第一个’\n’,就找到了它的输入分隔符,停止继续输入,第一个’\n’被从缓冲区中读走了,缓冲区里剩下"。

gets从标准输入设备读字符串函数。可以无限读取,不会判断上限,以回车结束读取,所以程序员应该确保buffer的空间足够大,以便在执行读操作时不发生溢出。
gets(s) 函数中的变量s为一字符串指针。如果为单个字符指针,编译连接不会有错误,但运行后内存溢出错误。
gets()在C11标准中被删除,可用C标准库中的fgets代替。

fgets()
所在头文件:stdio.h
语法:fgets(str, N, stdin) //str为数组名,N为读取容量(特别注意,包括\n和自动添加的\0两个)
fgets只能读取N-1个字符,包括最后的’\n’,读完结束后系统将自动在最后加’\0’(gets读完结束后系统自动会将’\n’置换成’\0’)。
说到这里就有俩种情况了:
一:当你从键盘上输入<=N-1个字符(包括’\n’)时,那么字符串str会以‘\n\0’结尾。这就造成了strlen(str)比你想象的大 1 ,
当然你可以通过下面代码将’\n’去掉:

if(str[strlen(str) - 1] == '\n') {      // 去掉换行符
    str[strlen(str) - 1] = '\0';   
}

二:当你从键盘上输入>N-1个字符(包括’\n’)时,那么字符串str会以’\0’结尾,此时仅读入N-1个字符,超过N-1的那些字符(包括’\n’被留在了缓冲区)。

getchar()
getchar()是C语言中的函数,C++中也包含了该函数。getchar()函数的作用是从标准的输入stdin中读取字符。也就是说,getchar()函数以字符为单位对输入的数据进行读取。
所在头文件:stdio.h
语法:ch=getchar(); //ch为字符变量
在控制台中通过键盘输入数据时,以回车键作为结束标志。当输入结束后,键盘输入的数据连同回车键一起被输入到输入缓冲区中。在程序中第一次调用getchar()函数从输入缓冲区中读取一个字节的数据。需要注意的是,如果此时在程序中第二次调用getchar()函数,因为此时输入缓冲区中还有回车键的数据没有被读出,第二个getchar()函数读出的是回车符。

getchar()的两个小用处:
(1)在程序末尾加getchar(),用来让程序不会立即退出,跟system(“pause”);是一样的功能.可能你在写完代码后用ctrl + F5运行时,不加getchar();程序也不会立即退出,这是当然的,编译器有这个功能.不过如果你从debug文件夹下用.exe文件打开代码,没有getchar()或system(“pause”);程序会闪一下就消失,可能就零点几秒.getchar();让程序停留在这一步,直到它从键盘接收到消息.
(2)在两次连续从键盘输入语句中间,用于吸收缓冲区多余的那个’\n’。

以下为C++中的函数
cin.get和cin.getline在#include头文件中声明
cin.get()
用法1: cin.get(字符变量名)可以用来接收字符

#include <iostream> 
using namespace std; 
main () 
{ 
char ch; 
ch=cin.get();               //或者cin.get(ch); 
cout<<ch<<endl; 
}

输入:jljkljkl
输出:j

用法2:cin.get(字符数组名,接收字符数目)用来接收一行字符串,可以接收空格

#include <iostream> 
using namespace std; 
main () 
{ 
char a[20]; 
cin.get(a,20); 
cout<<a<<endl; 
}

输入:jkl jkl jkl
输出:jkl jkl jkl
输入:abcdeabcdeabcdeabcdeabcde (输入25个字符)
输出:abcdeabcdeabcdeabcd (接收19个字符+1个’\0’)

用法3:cin.get(无参数)没有参数主要是用于舍弃输入流中的不需要的字符,或者舍弃回车,弥补cin.get(字符数组名,接收字符数目)的不足.

cin.getline() // 接受一个字符串,可以接收空格并输出

#include <iostream> 
using namespace std; 
main () 
{ 
char m[20]; 
cin.getline(m,5); 
cout<<m<<endl; 
}

输入:jkljkljkl
输出:jklj
接受5个字符到m中,其中最后一个为’\0’,所以只看到4个字符输出;
如果把5改成20:
输入:jkljkljkl
输出:jkljkljkl
输入:jklf fjlsjf fjsdklf
输出:jklf fjlsjf fjsdklf

//延伸:
//cin.getline()实际上有三个参数,cin.getline(接受字符串的数组名或指针,接受个数5,结束标志字符)
//当第三个参数省略时,系统默认为’\0’
//如果将例子中cin.getline()改为cin.getline(m,5,‘a’);当输入jlkjkljkl时输出jklj,输入jkaljkljkl时,输出jk

当用在多维数组中的时候,也可以用cin.getline(m[i],20)之类的用法

get( )与getline( )区别
get与getline区别不是很大,但一个明显的区别是get遇到 '\n '字符后便返回,这是 '\n '还在缓冲区中,所以下次读出来的将是 '\n ',而getline遇到 '\n '也返回,但它会把 '\n '从缓冲区里移除掉 所以很多时候用getline方便些。

#include <iostream>
using std::cin;
using std::cout;
const int SIZE = 15;
int main( ){
cout << "Enter your name:";
char name[SIZE];
cin.get(name,SIZE);
cout << "name:" << name;
cout << "\nEnter your address:";
char address[SIZE];
cin.get(address,SIZE);
cout << "address:" << address;
}

在这个例子中,cin.get()将输入的名字读取到了name中,并将由Enter生成的换行符’\n’留在了输入队列(即输入缓冲区)中,因此下一次的cin.get()便在缓冲区中发现了’\n’并把它读取了,最后造成第二次的无法对地址的输入并读取。解决之道是在第一次调用完cin.get()以后再调用一次cin.get()把’\n’符给读取了,可以组合式地写为cin.get(name,SIZE).get();

cin.getline()每次读取一整行并把由Enter键生成的换行符抛弃,如:

#include <iostream>
using std::cin;
using std::cout;
const int SIZE = 15;
int main( ){
cout << "Enter your name:";
char name[SIZE];
cin.getline(name,SIZE);
cout << "name:" << name;
cout << "\nEnter your address:";
char address[SIZE];
cin.get(address,SIZE);
cout << "address:" << address;
}

getline()
读入 string类
为重载函数,最多有三个输入。
getline函数位于命名空间std中
需要添加头文件#include

cin
cin遇到空格,tab键就会结束输入,后续的输入会留在缓冲区(特别地空格被忽略),遇到回车将输入。。。

太多了getline()和cin下次再研究。。。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

scanf(),getchar(),fgets(),gets(),cin.get()和cin.getline()读入字符串功能的用法详解 的相关文章

随机推荐

  • HDOJ 1106 排序

    题目地址 xff1a http acm hdu edu cn showproblem php pid 61 1106 Problem xff1a 输入一行数字 xff0c 如果我们把这行数字中的 5 都看成空格 xff0c 那么就得到一行用
  • ftp创建文件权限问题

    一 问题 有一个这样的需求 xff0c admin为一个Linux为其FTP应用创建的一个有权限限制的用户 xff0c 通过admin用户可以进行登录FTP服务 xff0c 登录FTP服务后 xff0c 创建文件夹 xff0c 该文件夹的用
  • lottie加载动画,第一次有延迟问题

    lottie是airbnb推出的一个直接将AE工程转化为动画的工具 ae project gt data json gt LottieComposition gt Lottie动画 之前做一个比较复杂的动画 xff0c 花了两天时间都在画各
  • CentOS 7防火墙快速开放端口配置方法

    CentOS 7防火墙快速开放端口配置方法 这篇文章主要为大家详细介绍了CentOS 7防火墙开放端口的快速方法 xff0c 感兴趣的小伙伴们可以参考一下 一 CentOS 7快速开放端口 xff1a CentOS升级到7之后 xff0c
  • C语言unsigned char、char与int之间的转换

    C语言unsigned char char与int之间的转换 2016年10月23日 18 40 50 bladeandmaster88 阅读数 xff1a 11347更多 个人分类 xff1a c语言基础 先来看一道题 xff1a cha
  • Android 内存分析(java/native heap内存、虚拟内存、处理器内存 )

    1 jvm 堆内存 dalvik 堆内存 不同手机中app进程的 jvm 堆内存是不同的 xff0c 因厂商在出厂设备时会自定义设置其峰值 比如 在Android Studio 创建模拟器时 xff0c 会设置jvm heap 默认384m
  • RabbitMq(一) RabbitMq工作模型

    RabbitMq工作模型 Mq基础RbbitMq工作模型RabbitMq基本使用原生apiSpring集成Springboot集成 RabbitMq进阶知识订单延迟关闭队列满了 总结 Mq基础 message queue 消息队列 特点 x
  • SSM整合_实现增删改查_基础环境搭建

    写在前面 SSM整合 年轻人的第一个增删改查 基础环境搭建 SSM整合 年轻人的第一个增删改查 查找 SSM整合 年轻人的第一个增删改查 新增 SSM整合 年轻人的第一个增删改查 修改 SSM整合 年轻人的第一个增删改查 删除 GitHub
  • SSM整合_实现增删改查_查找

    写在前面 SSM整合 年轻人的第一个增删改查 基础环境搭建 SSM整合 年轻人的第一个增删改查 查找 SSM整合 年轻人的第一个增删改查 新增 SSM整合 年轻人的第一个增删改查 修改 SSM整合 年轻人的第一个增删改查 删除 GitHub
  • SSM整合_实现增删改查_新增

    写在前面 SSM整合 年轻人的第一个增删改查 基础环境搭建 SSM整合 年轻人的第一个增删改查 查找 SSM整合 年轻人的第一个增删改查 新增 SSM整合 年轻人的第一个增删改查 修改 SSM整合 年轻人的第一个增删改查 删除 GitHub
  • 解决关机蓝屏 | MULTIPLE_IRP_COMPLETE_REQUESTS | klflt.sys

    已经解决蓝屏问题 xff0c 原因是卡巴斯基安全软件驱动导致 xff0c 需要卸载卡巴斯基安全软件 xff0c 详细过程如下 一 关机时蓝屏 Win10系统 xff0c 在关机动画快结束时突然蓝屏 xff0c 提示 xff1a 你的设备遇到
  • Spring注解开发_自定义注册组件、属性赋值、自动装配

    Spring注解开发 浅尝Spring注解开发 xff0c 基于Spring 4 3 12 包含自定义扫描组件 自定义导入组件 手动注册组件 自动注入方法和参数 使用Spring容器底层组件等 Spring注解开发 自定义注册组件 属性赋值
  • Spring注解开发_AOP原理及完整过程分析(源码)

    Spring注解开发 AOP原理及完整过程分析 xff08 源码 xff09 浅尝Spring注解开发 xff0c 基于Spring 4 3 12 分析AOP执行过程及源码 xff0c 包含AOP注解使用 AOP原理 分析Annotatio
  • 解决Windows中mfc110u.dll文件丢失问题

    其实很多用户玩单机游戏或者安装软件的时候就出现过这种问题 xff0c 如果是新手第一时间会认为是软件或游戏出错了 xff0c 其实并不是这样 xff0c 其主要原因就是你电脑系统的该dll文件丢失了或者损坏了 xff0c 这时你只需下载这个
  • Spring注解开发_声明式事务及原理

    Spring注解开发 声明式事务及原理 Spring注解开发 xff0c 基于Spring 4 3 12 包含声明式事务使用 基本原理分析 Spring注解开发 自定义注册组件 属性赋值 自动装配 Spring注解开发 Bean生命周期及执
  • Spring注解开发_简单理解BeanFactoryPostProcessor、BeanDefinitionRegistryPostProcessor、ApplicationListener

    Spring注解开发 简单理解BeanFactoryPostProcessor BeanDefinitionRegistryPostProcessor ApplicationListener 浅尝Spring注解开发 xff0c 基于Spr
  • Spring注解开发_Spring容器创建概述

    Spring注解开发 Spring容器创建概述 Spring注解开发 xff0c 基于Spring 4 3 12 概述Spring容器创建的过程 xff0c 包括12个方法的执行 Spring注解开发 自定义注册组件 属性赋值 自动装配 S
  • Spring注解开发_Servlet 3.0 与 SpringMVC

    Spring注解开发 Servlet 3 0 与 SpringMVC Spring注解开发 xff0c 基于Spring 4 3 12 Servlet3 0新增了注解支持 异步处理 xff0c 可以省去web xml文件 xff0c 异步处
  • nodejs nvm 环境安装踩坑记录

    nvm win10 nvm Node Version Manager 解决版本匹配问题 nvm windows 安装nvm windows 安装完nvm setup exe后 xff0c 以管理员权限重新开一个powershell窗口执行以
  • scanf(),getchar(),fgets(),gets(),cin.get()和cin.getline()读入字符串功能的用法详解

    scanf scanf 读取字符串直到出现空白符 xff08 空格 制表符 t 回车 n等 xff09 为止 xff1b 且不读入空白符 所在头文件 xff1a stdio h xff1b 语法 xff1a scanf 34 lt 格式化字