【C++中cin、cin.get()、cin.getline()、getline() 的区别】

news2025/1/16 6:40:50

文章目录

    • 引入
    • cin
      • 基本用法
      • 输入多个变量
      • 换行符存放在缓冲区中
    • cin.get()
      • 基本用法
      • 重载函数
      • 换行符残留在缓冲区中
    • cin.getline()
      • 基本使用
      • 重载函数
      • 换行符不会残留在缓冲区中
    • string 流中的 getline()
    • 总结
      • 用法总结
      • 几个输入实例
        • 输入格式
        • 输入格式
        • 输入格式
        • 输入格式
      • 输出格式
    • 写在最后

引入

在 ACM 模式的题目编程中,我们需要自己解决程序的输入与输出问题。我们自己解决程序的输入其实就是从键盘输入数据,然后将输入的数据传递我们定义的变量,其简要过程如下:

  • 使用输入流 cin 或其他输入函数从键盘读取数据时,程序会向操作系统发出请求以获取输入,就是程序运行后终端(屏幕)上那个一闪一闪输入提示符;
  • 敲击键盘输入几个字符;
  • 当我们想要结束字符的输入时,按下回车键;
  • 操作系统将用户输入的数据一次性放入输入缓冲区中;
  • C++ 程序通过 cin 或其他输入流来读取缓冲区中的数据。

代码运行时需要的变量也许是一个字符,也许是一个整型数字,也许是一个带有空格的字符串等等,这些我们都可以通过键盘输入然后按下回车键放入输入缓冲区,但是不同的 输入流 或者 输入函数 从缓冲区读取的数据效果也是不同的。

  • 如果想在以空格分隔的缓冲区数据中读取多个数据,我们应该使用什么样的 输入流 或者 输入函数
  • 如果想在缓冲区中读取指定字符之前的数据,我们应该使用什么样的 输入流 或者 输入函数
  • 如果想在缓冲区中按行读取数据,我们应该使用什么样的 输入流 或者 输入函数

如果,你可以轻松应对以上三个问题,那么厉害了,你已经基本掌握cpp中的常用的从标准输入流读取数据的操作了,也可以看看这篇博文回顾回顾嘛。如果对以上问题的答案还不太清楚,那么同学一定要好好看看这篇文章啊。

接下来就步入正题,看一下不同的 输入流 或者 输入函数 从缓冲区读取数据具有怎么样的不同效果。

cin

基本用法

我们先来介绍 C++ 中最常用的一个标准输入流对象 cin。

我们常用 cin >> num 来从缓冲区中读取数据到 num 中,num 的变量类型可以是多种类型,最常用的有 intstringchardoublefloat等等。

先看一个小例子:

#include <iostream>
using namespace std;

int main() {

    int n;

    cin >> n;
    cout << "n = " << n << endl;

    return 0;
}

在这个示例中,我们从键盘输入了一个整型字符(比如说 9),按下回车键,整型字符会被存入到缓冲区中,然后使用 cin 来读取缓冲区的数据,最后通过标准输出流 cout"n = 9"输出到终端窗口。

cin 从缓冲区中读数据,读取的是第一个非空白字符开始到第一个结束符之间的字符串。这个结束符可以是空格,也开始是制表符,也可以是换行符。空格、制表符、换行符是内置的 cin 的结束符,如果想用其他的字符来提前结束读取数据,需要自定义。

输入多个变量

cin 是直接从缓冲区读取数据的,如果缓冲区中还有数据,我们就不需要请求键盘输入,直接从缓冲区读取数据。比如下面的例子:我们在输入第一个字符串之后用空格隔开,然后输入了第二个字符串。对应的代码以及输出结果如下所示。

#include <iostream>
using namespace std;

int main() {

    char s[100];
    cout << "请输入字符串:" << endl;
    cin >> s;
    cout << s << endl;

    cin >> s;
    cout << s << endl;
    return 0;
}

由于 cin 在遇到空格或者制表符(/tab)时,会停止读取输入,因此第一个 cin 只会读取第一个字符串(第一个非空白字符开始到下一个空格字符结束之间的字符串)。这时候缓存区中还有残留的数据,因此下一个 cin 会直接从缓冲区中读取数据,而不会请求输入。

利用该原理,我们可以从以空格或者制表符为分隔符的缓冲区数据中读取多个数据。

换行符存放在缓冲区中

按下相应的结束符,才会从缓冲区读取数据到变量中,cin 每次从缓冲区中读取一个字符串,以空格作为字符或者字符串的分隔符。需要注意的是最后一个换行符会放在缓冲区中。比如下面的示例,该示例中我们使用 cin.get() 从缓冲区中读取单个字符。

#include <iostream>
using namespace std;


int main() {

    char s1[100], s2[100], ch;
    cout << "请输入字符串:" << endl;
    cin >> s1 >> s2;
    cout << s1 << endl;
    cout << s2 << endl;

    cin.get(ch);
    cout << (int)ch << endl;
    return 0;
}

我们从键盘输入 "cc ff",然后按下回车键,缓冲区中的数据为 "cc ff\n",我们将缓冲区的字符串 "cc""ff" 分别传给 s1s2,换行符传给 ch。最后的输出结果如下图所示,因为换行符的 ASCII 码为 10,所以最后会输出一个 10

cin.get()

基本用法

cin.get() 是C++标准库中的函数,用于从输入流中获取字符,包括空白字符(如空格、制表符和换行符)。与 cin 不同,cin.get() 不会将制表符、空白字符(空格)视为终止输入的标志,因此您可以使用它来获取包括空白字符在内的整行文本。默认情况下,cin.get() 使用换行符(\n)作为定界符(终止读取数据的结束符),表示读取到换行符时结束。

运行以下代码,然后输入 123 456,再按下回车键,输出结果如图所示:

#include <iostream>
using namespace std;


int main() {

    char s1[100];

    cin.get(s1, 100);
    cout << s1 << endl;

    return 0;
}

类似的代码,如果我们使用 cin 读取缓冲区的数据,那将只会输出 "123"

重载函数

在头文件 中定义的 get() 函数有以下几种重载形式:

// single character (1)	从标准流中读取单个字符;
int get();
istream& get (char& c);

// c-string (2)	从标准流中读取字符串并存储在c标准的s字符串中;
istream& get (char* s, streamsize n);
istream& get (char* s, streamsize n, char delim);

// stream buffer (3)	
istream& get (streambuf& sb);
istream& get (streambuf& sb, char delim);

我们最常用的是使用cin.get() 从标准输入流中读取单个字符以及读取多个字符存储在c标准的字符串中。

换行符残留在缓冲区中

cin.get() 与 cin 都是遇到相应的结束符才会结束从缓冲区读取数据,它们都不对换行符进行处理,换行符都会残留在缓冲区中。如果下次不想从上一次的缓冲区中读取数据,可以使用 cin.ignore() 忽略上一个缓冲区中的数据,或者使用 cin.getlin()。

cin.getline()

基本使用

cin.getline() 是C++标准库中的函数,用于从输入流中读取一行文本,并允许您指定一个定界符字符来结束读取。默认的定界符是换行符 (\n),表示读取到换行符时结束。但您可以通过提供第三个参数来指定自定义的定界符字符。

重载函数

在头文件 中定义的 getline 函数有以下两种重载形式:

istream& getline (char* s, count n);
istream& getline (char* s, count n, char delim);

作用是: 从istream中读取至多 n 个字符(包含结束标记符’\0’)保存在 s 对应的数组中,实际上只从输入流中最多读取 n-1 个字符到数组 s 中,因为最后一个字符必须是结束标志符 '\0',也就是c语言中所有的字符串中的最后一个字符 。

换行符不会残留在缓冲区中

cin.getline() 与 cin >> 、cin.get() 的使用基本一致,唯一的区别就是 cin >> 、cin.get() 遇到结束符终止从缓存区读取数据时,换行符会残留在缓冲区中,而使用 cin.getline() 换行符不会残留在缓冲区中。

现在我们使用getline来从标准输入中读取数据:

#include <iostream>

using namespace std;

int main() {

    char str[100];
    cin.getline(str, 100);
    cout << "str = " << str << endl;
    
    char c = cin.get();
    cout << (int)c << endl;
    
    return 0;
}

我们运行以上代码,输入任意一个字符串,比如 “123 589”,按下回车键,屏幕上会出现 “str = 123 589”(左图)。我们再按下回车键,屏幕上才会出现 10(右图)。

如果,我们执行以下这段代码:

#include <iostream>

using namespace std;

int main() {

    char str[100];
    cin.get(str, 100);
    cout << "str = " << str << endl;
    
    char c = cin.get();
    cout << (int)c << endl;
    
    return 0;
}

输出的结果为:

为什么会有如此差异,因为使用 cin.getline() ,换行符不会残留在缓冲区中。

在第一段代码中,我们还需要从缓冲区读取一个字符,缓冲区中已经没有任何字符了,因此会有提示输入符出现,我们按下回车键(换行符),屏幕上输出了我们按下的回车键(换行符)的 ASCII 码。

在第二段代码中,我们使用 cin.get() 来从标准输入读取数据,按下回车键(换行符),缓冲区中的字符串传给了 str。这时候,换行符会残留在缓冲区中,这个时候又需要从缓冲区中读取一个字符,于是就顺理成章的将换行符传给了 c,屏幕上也就会接着输出换行符的 ASCII 码了。

string 流中的 getline()

头文件中也有 getline() 函数,它们的使用与 中的用法基本一致,只有三点不同:

  • 头文件的不同;
  • getline() 中的多了第一个参数 istream is,通常填上 cin,表示的是从标准输入流中读取数据;
  • getline() 中的接收字符串变量为 string,而不是 char*。在C++代码中,建议使用getline(),因为接收字符串的变量是 string,是可以动态扩展的类型。

除了以上三点不同之外,其他的用法都与 中的 cin.getline() 用法一致,包括 getline() 不会将换行符残留在缓冲区中。

总结

用法总结

cin.get() 和 cin.getline() 是输入流中的,使用之前需要包含头文件 。cin 是输入输出流中的,使用之前需要包含头文件 。getline() 是字符串流的,使用之前需要包含头文件 。

从标准输入读取单个或者是多个变量(以空格、制表符、换行符隔开),尤其是整型变量,或者从多行读取整型变量到数组,使用 cin。

从标准输入读取单个字符,推荐使用输入流中的 cin.get()。

从标准输入读取单行字符串、多行字符串的,推荐使用字符串流中的 getline()。

cin、cin.get() 会将换行符残留在缓冲区中,getline() 和 cin.getline() 不会。

几个输入实例

输入格式

第一行有两个非负整数 mn。他们分别表示数组的长度和宽度。

接下来 m 行,每行有 n 个整数。

在ACM编程下,最常遇到的就是从键盘输入 mn 列数据到数组了,以下是从键盘输入 int 整型数据的代码。

#include <iostream>
#include<vector>

using namespace std;

int main() {

    int m, n;
    cin >> m >> n;
    vector<vector<int>> grids(m, vector<int>(n));
    
    for (int i = 0; i < m; ++i) {
        for (int j = 0; j < n; ++j) {
            cin >> grids[i][j];
        }
    }

    /* 此段代码用来测试输入是否正确
    for (int i = 0; i < m; ++i) {
        for (int j = 0; j < n; ++j) {
            cout << grids[i][j] << " ";
        }
        cout << endl;
    }
    */
    
    return 0;
}

我们在命令行窗口输入数据的方法有两种:

  • 第一种:在一行中输入所有的数据,第一个数是行数m,第二个数是列数n,接下来的是第一行的所有列中的数字,然后是第二行中的所有列的数字,直到输入完所有m行n列的数字(相邻两个数字之间都用空格隔开);
  • 第二种:在第一行输入行数m和列数n(以空格隔开),按下回车键,接下来的m行每一行输入n个数字,每输完一行数字就按一下回车键;
  • 最后按下的那个回车键会存储在缓冲区中。
输入格式

第一行包含两个正整数 m , n m,n m,n,分别表示 A A A 串和 B B B 串的长度。

第二行为一个长度为 m m m 的字符串 A A A

第三行为一个长度为 n n n 的字符串 B B B

两个串均仅由小写字母和 * \texttt * * 组成,其中 * \texttt * * 表示相应位置已经残缺。

#include <iostream>
#include <string>
using namespace std;


int main() {

    int m, n;
    string A, B;
    cin >> m >> n >> A >> B;

    // // 测试输入是否正确
    // cout << m << " " << n << endl;
    // cout << A << " " << B << endl;
    return 0;
}
输入格式

多行字符串。

每一行输入一个含有空格的字符串,输入多行,遇到 “END” 结束输入。

#include <iostream>
#include <string>
#include <vector>
using namespace std;


int main() {

    string str;
    vector<string> strs;
    getline(cin, str);
    while (str != "END" ) {
        strs.push_back(str);
        getline(cin, str);
    }
    
    // for test
    for (auto str : strs) {
        cout << str << endl;
    }

    return 0;
}
输入格式

输入在一行中给出不知道多少个绝对值不超过1000的整数。

输出格式

在一行中输出最后一次出现的 “250” 是第几个数字(计数从1开始)。如果没有出现 “250” 这个数,输出为 0。

// #include <iostream>

// using namespace std;

// int main()
// {
//   int ct = 0;
//   int a, pos = 0;
//   do
//     {
//       ct++;
//       cin >> a;
//       if (a == 250)
//         pos = ct;
//     }
//   while (cin.get() != '\n');
//   cout << pos;
//   return 0;
// }
 

#include <iostream>

using namespace std;

int main() {
  int cnt = 0;
  int a, pos = 0;
  while (cin.get() != '\n') {
    ++cnt;
    cin >> a;
    if (a == 250) {
        pos = cnt;
    }
  }
  
  cout << pos;
  return 0;
}

写在最后

如果文章内容有任何错误或者您对文章有任何疑问,欢迎私信博主或者在评论区指出 💬💬💬。

如果大家有更优的时间、空间复杂度方法,欢迎评论区交流。

最后,感谢您的阅读,如果感到有所收获的话可以给博主点一个 👍 哦。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1111527.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【毕业设计】基于SSM的商城系统

前言 &#x1f525;本系统可以选作为毕业设计&#xff0c;运用了现在主流的SSM框架&#xff0c;采用Maven来帮助我们管理依赖&#xff0c;所选结构非常合适大学生所学的技术&#xff0c;本系统结构简单&#xff0c;容易理解&#xff01;本系统功能结构完整&#xff0c;非常高适…

发展新能源汽车加快充换电基础设施建设实施方案-安科瑞黄安南

摘要&#xff1a;为深入贯彻落实《国务院办公厅关于印发新能源汽车产业发展规划&#xff08;2021—2035年&#xff09;的通知》&#xff08;国办发 ﹝2020﹞39号&#xff09;、《国家发展改革委等部门关于进一步提升电动汽车充电基础设施服务保障能力的实施意见》&#xff08;发…

【疯狂Java讲义】Java学习记录(使用jar命令打包)

jar命令 把多个文件打包成一个压缩包——这个压缩包和WinZip的压缩格式是一样的。 区别在于jar压缩的文件默认多一个META-INF的文件夹&#xff0c;该文件夹里包含一个MANIFEST.MF的文件&#xff08;清单&#xff09;。 通常来说&#xff0c;得到的压缩包有3种&#xff08;压缩格…

机器学习tip:sklearn中的pipeline

文章目录 1 加载数据集2 构思算法的流程3 Pipeline执行流程的分析ReferenceStatement 一个典型的机器学习构建包含若干个过程 源数据ETL数据预处理特征选取模型训练与验证 一个典型的机器学习构建包含若干个过程 以上四个步骤可以抽象为一个包括多个步骤的流水线式工作&…

Ubuntu安装和配置ssh

一般Ubuntu都会默认安装openssh-client,但是没有安装openssh-server。 一、安装ssh服务器 sudo apt install openssh-server 二、安装ssh客户端 sudo apt install openssh-client 三、 配置ssh客户端,去掉PasswordAuthentication yes前面的#号,保存退出 sudo vi /etc/ssh…

mysql按照日期分组统计数据(date_formatstr_to_date)

学习链接 mysql按照日期分组统计数据 博主-山茶花开时的 【Mysql专栏学习】 mysql按照日期分组统计数据 Mysql的date_format函数想必大家都使用过吧&#xff0c;一般用于日期时间转化&#xff0c;如下所示 # 可以得出 2023-01-01 08:30:50 select DATE_FORMAT(2023-01-01…

NodeMCU ESP8266 的PWM波形输出教程(图文并茂)

NodeMCU ESP8266 基于 Arduino 的 PWM波形输出 文章目录 NodeMCU ESP8266 基于 Arduino 的 PWM波形输出什么是PWM?常用接口pinModeanalogWrite 示例总结 什么是PWM? PWM是脉冲宽度调制&#xff08;Pulse Width Modulation&#xff09;的缩写&#xff0c;是一种用于控制电子设…

百度的新想象力在哪?

理解中国大模型&#xff0c;百度是一个窗口。这个窗口的特殊性不仅在于变化本身&#xff0c;而是在于百度本身就是那个窗口。 作者|皮爷 出品|产业家 沿着首钢园北区向西北步行10分钟&#xff0c;就能看到一个高约90米的大跳台&#xff0c;在工业园钢铁痕迹的印衬下&#…

9.构造器与垃圾收集器 对象的前世今生

9.1 对象与变量的生存空间 栈与堆&#xff1a;生存空间 在Java中&#xff0c;程序员会在乎内存中的两种区域&#xff1a;对象的生存空间堆&#xff08;heap&#xff09;和方法调用及变量的生存空间&#xff08;stack&#xff09;。当Java虚拟机启动时&#xff0c;它会从底层的…

CSS之Flex布局的详细解析

Flex布局 目标&#xff1a;熟练使用 Flex 完成结构化布局 01-标准流 标准流也叫文档流&#xff0c;指的是标签在页面中默认的排布规则&#xff0c;例如&#xff1a;块元素独占一行&#xff0c;行内元素可以一行显示多个。 02-浮动 基本使用 作用&#xff1a;让块元素水平排列…

【生成模型】DDPM概率扩散模型(原理+代码)

--- 前言一、常见生成模型二、直观理解Diffusion model三、形式化解析Diffusion model*四、详解 Diffusion Model&#xff08;数学推导&#xff09;1.前向过程(扩散过程)2.逆扩散过程3.逆扩散条件概率推导4.训练损失 五、训练、测试伪代码1. 训练2.测试 六、代码解析1.train_ci…

进程的描述、控制与通信

一、概念 进程的状态 进程的最基本状态 就绪态执行态阻塞态 为保证完整性&#xff0c;再引入两种状态 创建态终止态 引入挂起操作后&#xff0c;引入的状态 活动就绪静止就绪活动阻塞静止阻塞 挂起&#xff1a;当挂起操作作用于某个进程时&#xff0c;该进程将被挂起&…

基于LSTM时间序列预测(简单又好用)无脑代码

# 基于LSTM时间序列预测&#xff08;简单又好用&#xff09;无脑代码&#xff0c; 这里是列表文本使用很简单&#xff0c;跟着注释和使用手册用就行. 简介&#xff1a; 1、单变量&#xff0c;多变量输入&#xff0c;自由切换 2、单步预测&#xff0c;多步预测&#xff0c;自动…

1.集合框架

一、JDK版本之间的关系 1.1、Oracle JDK与OpenJDK的区别 1.Oracle JDK是基于OpenJDK源代码构建的&#xff0c;因此Oracle JDK和OpenJDK之间没有重大的技术差异。 2.Oracle JDK将更多地关注稳定性&#xff0c;它重视更多的企业级用户&#xff0c;而OpenJDK经常发布以支持其他性能…

电子技术基础(三)__第7章 时序逻辑电路_第6篇__时序逻辑电路的分类

时序逻辑电路的分类&#xff0c; 通常按两种来分类&#xff1a; 按逻辑功能&#xff0c; 按触发器状态的变化规律。 一. 同步、异步的定义 同步时序逻辑电路 是 所有触发器有一个共同的时钟控制信号CP, 在CP脉冲信号的作用下&#xff0c;触发器状态的变化同时发生&#xff0c;…

40G光模块的兼容性与协议标准

40G光模块的兼容性与标准化是确保光通信系统稳定运行的关键因素。在下文中&#xff0c;易天光通信将对40G光模块的兼容性和标准化进行分析和讨论。 一、关于40G光模块的兼容性方面 40G光模块的兼容性主要涉及两个方面&#xff1a;光接口的兼容性和协议的兼容性。 光接口兼容…

零基础如何自学C#?

前言 本文来源于知乎的一个提问&#xff0c;提问的是一个大一软件工程专业的学生&#xff0c;他想要自学C#但是不知道该怎么去学&#xff0c;这让他感到很迷茫&#xff0c;希望有人能给他一些建议和提供一些学习方向。 个人建议 确认目标&#xff1a;自学C#首先你需要大概了解…

“第四十四天”

这道题也不是难&#xff0c;但可能会忽略一种情况&#xff0c;当最大小出现在首位的时候&#xff0c;那个时候如果进行交换的话&#xff0c;大小值可能出现覆盖的情况&#xff0c;最终导致丢失最大值或者最小值&#xff0c;比如最大值 10 在第一位&#xff0c;最小值 0 随意&am…

对电动汽车的高压互锁的理解

什么是高压互锁系统 什么是高压互锁系统&#xff1f;高压互锁系统(HighVoltageInter-lock&#xff0c;简称HVIL)&#xff0c;也叫高压互锁回路系统(HazardousVoltageInterlockLoop) 高压互锁的原理 高压互锁是利用低压回路的检测信号来判断高压回路每个高压接插件各自是否连…

文件管理系统的基本认识

1.文件的属性 文件的定义:一组有意义的信息的集合。 1.文件名: 由创建文件的用户决定文件名&#xff0c;主要是为了方便用户找到文件&#xff0c;同一目录下不允许有重名文件。 2.标识符: 一个系统内的各文件标识符唯一&#xff0c;对用户来说毫无可读性&#xff0c; 因此…