你get了吗?— C++中get和getline的区别

6 篇文章 0 订阅
订阅专栏

在日常的编程练习中读写文件是再平常不过的场景了,虽然这算是基础中的基础了,但以前用起来总是不求甚解,有时用get有时用getline,几乎每次都是面向搜索引擎编程+能跑就行+过后就忘。。。这次整理了二者的用法和区别(其实就是抄了一下cppreference),希望加深理解,以后用的时候能信手拈来。

[What] std::basic_istream<CharT,Traits>::get

首先,这里说的get指的是专门用于读取输入流的 std::basic_istream<CharT,Traits>::get函数,具体一点就是
std::istream::getstd::ifstream::getstd::istrstream::getstd::iostream::getstd::fstream::getstd::strstream::get及相应的宽字符输入流类型的成员函数get。

get的作用是从输入流中读取(并释放)一个或多个字符。它有以下6种重载形式:
get_cppreference
其中(3)(5)默认的delim'\n',(4)(6)则可以指定delim

get函数的终止条件如下:

  • 读到eof:以上所有函数当读到流的结尾触发end of file条件时,会执行setstate(eofbit)

  • 读到delim:(3)(4)(5)(6)当将要读取的下一个字符c == delim时,get会将已读取到的字符串存储并从流中释放,但字符c并不会被释放。如果继续读取,第一个读取到的字符就是c

  • 读满s:(3)(4)至多读取count-1个字符存储至字符串s中,因为最后一个字符是\0

  • 没读到:如果没有读出任何字符,会执行setstate(failbit)

注意:由于get默认的delim'\n',使得在读文件时的行为表现出来就是读取一行的内容,但它又不会将'\n'读出并释放,这也是容易与getline造成混淆之处。

[How] std::basic_istream<CharT,Traits>::get

  • 下面演示了get函数的具体用法(基本抄了cppreference):
#include <sstream>
#include <iostream>

static void testGet() {
    std::istringstream s1("Hello, world.\nCannot read");
    std::istringstream s2("123\n|Cannot read");

    // [1]
    char c1 = s1.get(); // reads 'H'
    std::cout << "[1] After reading " << c1 << ", gcount() == " << s1.gcount() << '\n';

    // [2]
    char c2;
    s1.get(c2); // reads 'e'

    // [3]
    char str1[5];
    s1.get(str1, 5); // reads "llo,"
    std::cout << "[3] After reading " << str1 << ", gcount() == " << s1.gcount() << '\n';

    std::cout << c1 << c2 << str1;

    // [5] 读取剩余字符,读到 '\n' 停止
    s1.get(*std::cout.rdbuf()); // reads " world."
    std::cout << "\n[5] After the last get(), gcount() == " << s1.gcount() << '\n';

    // [4] 读到 '|' 停止,'|' 未释放仍保存在流中
    char str2[10];
    s2.get(str2, 10, '|'); // reads "123\n"
    std::cout << "[4]After reading " << str2 << ", gcount() == " << s2.gcount() << '\n';

    // [6] 读到 '|' 停止
    s2.get(*std::cout.rdbuf(), '|'); // reads nothing
    std::cout << "[6]After the last get(), gcount() == " << s2.gcount() << '\n';
}
  • 运行结果:
    get_result

C++中有两种getline函数: 一种是 std::basic_istream<CharT,Traits>::getline,它与上文的get函数都是istream类的成员函数;另一种是 std::getline,定义于头文件<string>中,是std命名空间的全局函数。

下面分别介绍这两种getline函数。

[What] std::basic_istream<CharT,Traits>::getline

getline_istream_cppreference
getline的作用是从流中读取(并释放)字符串,直到遇到指定的delim。常用的就是(1),它默认的delim'\n',等效于getline(s, count, widen('\n'))

getline函数的终止条件如下:

  • 读到流的结尾,会执行setstate(eofbit)

  • 下一个字符c == delim,字符c会被读取并释放,但不会被存储;

  • 已经读取了count-1个字符,会执行setstate(failbit)

  • 如果没有读出任何字符(e.g.count < 1),会执行setstate(failbit)

[How] std::basic_istream<CharT,Traits>::getline

#include <iostream>
#include <sstream>
#include <vector>
#include <array>

static void testGetline_istream() {
    std::istringstream input1("abc\ndef\ngh");
    std::istringstream input2("123|456|\n78");
    std::vector<std::array<char, 4>> v;

    // [1]
    for (std::array<char, 4> a; input1.getline(&a[0], 4);) {
        v.push_back(a);
    }
    for (auto& a : v) {
        std::cout << &a[0] << '\n';
    }

    v.clear();

    // [2]
    for (std::array<char, 4> a; input2.getline(&a[0], 4, '|'); ) {
        v.push_back(a);
    }
    for (auto& a : v) {
        std::cout << &a[0] << '\n';
    }
}
  • 运行结果:
    getline_istream_result

    可以看出,getline函数并不只局限于读取一行的数据,只是默认delim'\n'使得它的行为表现出来为读取一行而已。

[What] std::getline

getline_string_cppreference
std::getline的功能是从一个输入流中读取字符串,然后存储到一个string中。常用(2)默认的delim也是'\n',等效于getline(input, str, input.widen('\n'))

std::getline的终止条件如下:

  • 读到流结尾,会设置eofbit并返回;

  • 下一个字符c == delim,字符c会被读取并释放,但不会被添加到str中;

  • 已经读取了str.max_size()个字符,会设置failbit并返回;

  • 如果没有读出任何字符,会设置failbit并返回。

注意:其实std::getlinestd::basic_istream<CharT,Traits>::getline大同小异,可以看作是一个功能的两种接口形式:一个针对C++的string类型,另一个针对C类型字符串char *

[How] std::getline

static void testGetline_string() {
    // [2]
    std::string name;
    std::cout << "What is your name? ";
    std::getline(std::cin, name);
    std::cout << "Hello " << name << ", nice to meet you.\n";

    // [1]
    std::istringstream input;
    input.str("1|2|3|4|5|6|7|");
    int sum = 0;
    for (std::string line; std::getline(input, line, '|'); ) {
        sum += std::stoi(line);
    }
    std::cout << "\nThe sum is: " << sum << "\n";
}
  • 运行结果:
    getline_string_result

[Warning] 坑点

坑点1:使用getline(s, count)时字符数组s必须要预留足够的空间!!!

上文多次提到eofbitfailbit这两种指定流状态的标志,详情可见 std::ios_base::iostate。

下面使用一个例子验证已经读取了count-1个字符时,会执行setstate(failbit)

static void testGetline_failbit() {
    std::istringstream input("123|4567|89");

    // note: the following loop terminates when std::ios_base::operator bool()
    // on the stream returned from getline() returns false
    std::array<char, 4> a;
    while (input.getline(&a[0], 4, '|')) {
        // 读取 "123" 同时 '|' 也被读出
        std::cout << "After reading " << &a[0] << ", gcount() == " << input.gcount() << '\n'; // 4
        std::cout << "After reading " << &a[0] << ", tellg() == " << input.tellg() << '\n'; // 4
    }

    // 读取 "456" 时字符数组读满导致 setstate(failbit) 执行,跳出循环
    std::cout << "After reading " << &a[0] << ", gcount() == " << input.gcount() << '\n'; // 3
    std::cout << "After reading " << &a[0] << ", tellg() == " << input.tellg() << '\n'; // -1
    std::cout << "After reading " << &a[0] << ", rdstate() == " << input.rdstate() << '\n'; // 2 == failbit

    // 设置状态为 goodbit 可找到循环退出时文件流指针的确切位置
    input.clear();
    std::cout << "After clear(), tellg() == " << input.tellg() << '\n'; // 7

    // 移到指针到文件开头
    input.seekg(0, std::ios::beg);
    std::cout << "After seekg(), tellg() == " << input.tellg() << '\n'; // 0
}
  • 运行结果(具体的原因分析都已经在注释中标明):
    getline_failbit_result

坑点2:当使用流处理的方式读数据时,读到行尾并不会跳行!!!

get和getline读取的结果都是C/C++类型的字符串,有时为了读取其他类型的数据(e.g. int, double),我们通常会结合流处理的方式完成类型转换(流处理可以看作是C++类型转换的通杀法:万物转stream,stream转万物)。

但是,当使用流处理读到行尾时,它并不会主动跳转到下一行!如下面的代码示例:当读出123后,流指针还是在第一行,需要调用两次getline函数使指针跳到456所在的行。

static void testGetlineAndIstream() {
    std::istringstream input("123\n***\n456");
    int a, b;
    std::string str;

    input >> a;
    std::cout << "First reading from stream: " << a << '\n';
    std::getline(input, str);
    std::getline(input, str);
    input >> b;
    std::cout << "Second reading from stream: " << b << '\n';
}
  • 运行结果:
    getline_and_istream

[Summary] 三者的比较

#std::basic_istream<CharT,Traits>::getstd::basic_istream<CharT,Traits>::getlinestd::getline
头文件<iostream>/<sstream>/<fstream><iostream>/<sstream>/<fstream><string>
输出对象C类型字符串C类型字符串C++string对象
释放delim✔️

[Github] 代码

项目实例均在vs2017上测试,并上传至 GitHub,将GetAndGetline设为启动项目即可复现实验结果。

[Reference] 参考

std::basic_istream<CharT,Traits>::get

std::basic_istream<CharT,Traits>::getline

std::getline

std::ios_base::iostate

get和getline函数差别
Roman的博客
05-27 786
//get(char*array,int count,char delim)与getline(char*array,int count,char delim)的不同点: //1.当输入的字符数小于count时遇到字符delim,get函数不会读取delim这个字符,而getline函数将读取这个字符但是不存进array当去,而是将其丢弃,当然,两者都会在读取的字符串后面自动加上'\0'(t
C++ getline() 和 get()
Tyler_Zx的博客
01-28 2万+
字符串输入问题 #include <iostream> using namespace std; int main() { const int Asize = 20; char name[Asize]; char dessert[Asize]; cout << "Enter your name:" <<endl; ...
std::getlineifstream类的getline函数、get函数区别
最新发布
m0_54901781的博客
07-24 226
首先,这里说的get指的是专门用于读取输入std::basic_istream<CharT,Traits>::get函数,具体一点就是std::istream::get、std::ifstream::get、std::istrstream::get、std::iostream::get、std::fstream::get、std::strstream::get及相应的宽字符输入类型的成员函数get。get的作用是从输入读取(并释放)一个或多个字符。
get( )与getline( )区别
AC__GO的博客
05-27 441
get( )与getline( )区别 get与getline区别不是很大,但一个明显的区别是get遇到 '\n '字符后便返回,这是 '\n '还在缓冲区,所以下次读出来的将是 '\n ',而getline遇到 '\n '也返回,但它会把 '\n '从缓冲区里移除掉 所以很多时候用getline方便些 一、cin.get()每次读取一整行并把由...
getlin与get的区别
sinat_35008396的博客
05-16 272
getlin(A,len)与get(A,len)都是读取一串字符串,遇到回车即停 但是getlin会跳过回车,下一次读取的时候直接从输入队列跳过回车,读取下一个字符 而get不会跳过回车,而是把回车留在输入队列,下一次读取的时候依然会读取到回车,所以很多时候用一个get()把回车读到,接着读取下一个字符 再用数组存放字符串的时候要注意: 长度是底线,回车是断。 即:数组只能存放数组
C++ get 和getline
weixin_43963453的博客
04-17 186
https://www.jb51.net/article/158128.htm
浅谈C++字符串输入get与getline区别
08-26
C++字符串输入get与getline是两种最常用的输入函数,但是它们之间的区别却经常被忽视和混淆。作为一名程序员,了解它们之间的区别是非常重要的。本篇文章将通过详细的示例代码,介绍C++字符串输入get与getline...
C++getline()和get()的方法浅析
09-01
C++编程语言,获取用户输入是程序交互的基础,其`getline()`和`get()`函数是常用的两个方法,尤其适合处理包含空格或其他分隔符的字符串输入。本文将详细解析这两个函数的使用和差异。 首先,让我们回顾一下...
C++的get()函数getline()函数使用详解
09-03
C++编程语言,`get()`和`getline()`函数都是用于从输入读取数据的,但它们之间有着显著的区别,适用于不同的场景。在本文,我们将深入探讨这两个函数的使用方法和特点。 首先,`get()`函数是`std::...
学习笔记 C++getline()和get()
weiyuanzhang123的博客
05-29 429
istream的类(如cin)提供了一些面向杭的类成员函数getline()和get()。这两个函数都读取一行输入,知道到达换行符。然而,随后getline()将丢弃换行符,而get()将换行符保留在输入序列。 首先 ...
get和getLine区别
fulima007的专栏
05-15 1099
<br />当遇到输入的界定符的时候(默认是'/n'),get就会停止执行,但是并不从输入提取界定符,这是如果再次调用get函数,会遇到同一个界定符,函数会立刻返回而不从输入提取输入。(为了解决这个问题可以在下次输入的时候用不同的函数,或者利用get()函数剔提取界定符)实例代码如下 <br />#include <iostream> #include <string> using namespace std; const int SIZE=50; int main() { cou
gets和getline区别
m0_71808911的博客
07-23 445
gets和getline是两个在C和C++用于读取输入的函数,它们之间存在显著的区别
c/c++gets、getline区别
sudyingishappy的博客
02-14 1069
get和getline不同点
Rogers
06-13 362
get(char*array,int count,char delim)与getline(char*array,int count,char delim)的不同点: 1.当输入的字符数小于count时遇到字符delim,get函数不会读取delim这个字符,而getline函数将读取这个字符但是不存进array当去,而是将其丢弃,当然,两者都会在读取的字符串后面自动加上'\0'(temin
C++ get()和getline()的区别
菜鸡工坊
04-22 663
getling():每次读取一行输入的字符串时,它通过换行符(\n)来确定行尾,之后丢弃Enter生成的换行符,取而代之的是空字符。 get():每次读取一行输入的字符串时,它通过换行符(\n)来确定行尾,之后丢弃Enter生成的换行符,并保留换行符到队列。 如果连续两次调用get(): #include <iostream> using namespace std; const i...
C++ get() 和 getline()的区别
热门推荐
Timplan的博客
08-17 2万+
1,方法get(char &amp;)和get(void)提供不跳过空白的单字符输入功能; 2,函数get(char * , int , char)和getline(char * , int , char)在默认情况下读取整行而不是一个单词; 它们被称为非格式转化输入函数,因为它们只是读取字符输入,而不会跳过空白,也不进行数据转换。   在使用char参数或没有参数的情况下,get()方法...
getline()和get()的使用区别
weixin_30662849的博客
07-22 1650
一、getline和get()的使用区别: 首先这两个函数都读取下一行输入,直到到达换行符;但是getline()函数会丢弃换行符,而get()将换行符保留在输入序列 二、getline()函数的使用方法: getline()函数读取整行,它使用通过回车输入的换行符来确定输入结尾。要调用这种方法,可以使用cin.getline()。该函数有两个参数,第一个参数是用来存储输入行的数组的名称,...
c++cin.get和cin.getline区别
07-13
C++,`cin.get()` 和 `cin.getline()` 是用于从标准输入读取字符序列的两个函数区别如下: 1. 参数不同:`cin.get()` 函数接受一个字符作为参数,而 `cin.getline()` 函数接受一个字符数组作为参数。 2. 输入结束的判定:`cin.get()` 在读取字符时,遇到换行符或者文件结束符(EOF)时会结束读取,但不会将换行符或EOF从输入移除。而 `cin.getline()` 会读取到换行符(包括换行符)为止,并将换行符从输入移除。 3. 字符串长度限制:`cin.get()` 读取字符时,不限制字符的数量。而 `cin.getline()` 读取字符序列时,默认情况下会在遇到换行符之前读取 n-1 个字符,其 n 是传递给函数的字符数组的大小。这是为了确保读取到的字符序列不会超出数组的边界。如果输入的字符序列长度大于等于 n-1,多余的字符将被丢弃。 4. 字符串结尾:`cin.get()` 读取的字符序列不会自动添加字符串结束符 '\0'。而 `cin.getline()` 在读取完字符序列后会自动添加字符串结束符 '\0'。 综上所述,`cin.get()` 适用于读取单个字符,而 `cin.getline()` 适用于读取一行字符序列。
写文章

热门文章

  • WordPress 用户注册和发送邮件 24429
  • 图划分软件Metis的使用 4881
  • Linux学习笔记(一)— 硬盘分区和分区工具(上) 4855
  • 实习一月记——美团点评云计算部 2429
  • 春招总结(作业帮、华为、腾讯、美团、京东面经) 2273

分类专栏

  • C++ 6篇
  • Operational Research 1篇
  • Algorithm 1篇
  • 2篇
  • Python 3篇
  • Linux 5篇
  • 找工作 3篇

最新评论

  • 图划分软件Metis的使用

    2301_80523641: 兄弟解决了吗 我也是这个问题

  • 2022届暑期实习小结(腾讯&字节&美团offer)

    CSDN-Ada助手: 非常感谢您分享这篇关于暑期实习的小结,让我们看到了您的成果和收获。我觉得接下来你可以结合自己的实习经验,分享一些关于<技术主题>的经验和思考,比如如何应对<技术难题>,或者分享一些<实际应用案例>等等。这样的技术文章对其他用户也会很有帮助,相信会有更多读者受益于你的分享。期待你的下一篇博客! 为了方便博主创作,提高生产力,CSDN上线了AI写作助手功能,就在创作编辑器右侧哦~(https://mp.csdn.net/edit?utm_source=blog_comment_recall )诚邀您来加入测评,到此(https://activity.csdn.net/creatActivity?id=10450&utm_source=blog_comment_recall)发布测评文章即可获得「话题勋章」,同时还有机会拿定制奖牌。

  • 图划分软件Metis的使用

    m0_58405622: 请问你实现了吗?我也想知道这种情况怎么设置

  • 图划分软件Metis的使用

    NICEMOONYTB: 请问,没有边权重,只有点权重,单纯想根据点权重分个类,那个xadj和adjncy要怎么设置?

  • 图划分软件Metis的使用

    艾尔普兰: 请问两种方法都参考1995年ICPP的论文A fast and high quality multilevel scheme for partitioning irregular graphs吗?

最新文章

  • 2022届暑期实习小结(腾讯&字节&美团offer)
  • 优先队列101
  • 智能指针shared_ptr踩坑笔记
2021年2篇
2020年5篇
2018年12篇

目录

目录

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值

玻璃钢生产厂家东莞玻璃钢字母座椅雕塑黄山欧式玻璃钢雕塑优势上海玻璃钢动物雕塑厂家供货广州儿童玻璃钢雕塑制作多少钱建邺元旦商场美陈巫溪卡通玻璃钢雕塑商场美陈吊旗网萍乡景区玻璃钢雕塑定做价格玻璃钢雕塑成本费用商场美陈类别伊春玻璃钢动物雕塑温州淄博玻璃钢人物雕塑瑞金玻璃钢雕塑廊坊广东园林玻璃钢花盆通道商场美陈现价黄冈玻璃钢花盆花器商场美陈布置多少钱一米邯郸户外玻璃钢雕塑仿古玻璃钢仿铜雕塑报价玻璃钢鹿马赛克雕塑西安玻璃钢智能雕塑温州特色玻璃钢雕塑销售电话北京玻璃钢山羊雕塑商场玻璃钢雕塑摆件采购连云港玻璃钢雕塑商家玻璃钢卡通雕塑哪家有佛山能透光玻璃钢雕塑厂家电话珠海透光玻璃钢雕塑制作江油玻璃钢牌匾雕塑萍乡多彩玻璃钢雕塑设计香港通过《维护国家安全条例》两大学生合买彩票中奖一人不认账让美丽中国“从细节出发”19岁小伙救下5人后溺亡 多方发声单亲妈妈陷入热恋 14岁儿子报警汪小菲曝离婚始末遭遇山火的松茸之乡雅江山火三名扑火人员牺牲系谣言何赛飞追着代拍打萧美琴窜访捷克 外交部回应卫健委通报少年有偿捐血浆16次猝死手机成瘾是影响睡眠质量重要因素高校汽车撞人致3死16伤 司机系学生315晚会后胖东来又人满为患了小米汽车超级工厂正式揭幕中国拥有亿元资产的家庭达13.3万户周杰伦一审败诉网易男孩8年未见母亲被告知被遗忘许家印被限制高消费饲养员用铁锨驱打大熊猫被辞退男子被猫抓伤后确诊“猫抓病”特朗普无法缴纳4.54亿美元罚金倪萍分享减重40斤方法联合利华开始重组张家界的山上“长”满了韩国人?张立群任西安交通大学校长杨倩无缘巴黎奥运“重生之我在北大当嫡校长”黑马情侣提车了专访95后高颜值猪保姆考生莫言也上北大硕士复试名单了网友洛杉矶偶遇贾玲专家建议不必谈骨泥色变沉迷短剧的人就像掉进了杀猪盘奥巴马现身唐宁街 黑色着装引猜测七年后宇文玥被薅头发捞上岸事业单位女子向同事水杯投不明物质凯特王妃现身!外出购物视频曝光河南驻马店通报西平中学跳楼事件王树国卸任西安交大校长 师生送别恒大被罚41.75亿到底怎么缴男子被流浪猫绊倒 投喂者赔24万房客欠租失踪 房东直发愁西双版纳热带植物园回应蜉蝣大爆发钱人豪晒法院裁定实锤抄袭外国人感慨凌晨的中国很安全胖东来员工每周单休无小长假白宫:哈马斯三号人物被杀测试车高速逃费 小米:已补缴老人退休金被冒领16年 金额超20万

玻璃钢生产厂家 XML地图 TXT地图 虚拟主机 SEO 网站制作 网站优化