IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> c++中输入输出 cin,cout,ifstream ofstream getline等IO接口详解 -> 正文阅读

[C++知识库]c++中输入输出 cin,cout,ifstream ofstream getline等IO接口详解

c++中的输入输出都是用“类”来进行,无论是 cin,和cout都是类的一个对象。
c++中负责IO的有3中类型
1: istream、ostream 从流读写数据(i表示in也就是读,o表示out也就是写),你可以认为流就是控制台输入输出的数据,cin和cout就分别是他们俩的对象。
2: ifstream、ofstream f 表示file,也就是从文件读写数据
3: istringstream, ostringstream 从string读写数据。

其中2,3是继承的1。那么有了这些类之后读写过程是怎样的呢?
?我们以cin为例,首先你在控制台输入字符敲下回车键以后数据就到了到缓冲区,你可以认为cin与缓冲区之间已经建立好了一层通道可以直接读数据,所以我们直接用cin读数据就可以了是不是很简单。
? 那如何从文件读写数据?和cin一样,我们创建一个文件流对象,然后需要我们自己用open函数建立通道,然后就可以通过对象进行写读数据操作。第三种string也是一样的。

/*cod.cpp文件*/
#include <iostream>
#include "my_lib.h"
using namespace std;
int main(){
    string s;
    cin >>s;  //[空格][空格]abc[空格]cd[回车]
    cout <<s;//abc
    ifstream ifs;//cin是 istream类的对象,我自己创建了一个ifstream类的对象
    ofstream ofs;
    ifs.open("./a.txt");//建立通道
    ofs.open("./b.txt");//建立通道
    ifs >> s;//和cin效果一样,只不过是从文件读数据
    ofs << s;
    //程序开始之前  a.txt内容为 hello hi      b.txt为空白文件
    //程序结束之后 b.txt的内容变为了 hello 
}

分析上面的代码我们发现无论是ifs还是cin都只读取了一串字符,遇到空格就不读取了,而且一开始的自动忽略了,那剩下的内容呢?读写规则是怎样的,还有如果想读取一行又该如何解决?

cin cout 具体读写规则
首先cin是从标准输入(缓冲区)读数据的。当开始读数据时,如果一开始遇到的是分隔符比如tab 换行,空格等,它会自动忽略这些字符接着读,如果读入数据之后再遇到分隔符则本次读入结束(进入下一行代码),注意此时分隔符仍留在缓冲区未清理。举个栗子

#include <iostream>
#include "my_lib.h"
using namespace std;
int main(){
    string s1,s2;
    int a1,a2;
    //用键盘敲下 [空格][空格]abc[空格]12[回车]
    cin >> s1;//首先忽略前两个空格,将abc读入了s1,然后遇到了空格表示本次读入结束,空格留在缓冲区
    cin >> a1;//注意在开始这一句之前缓冲区里的数据为[空格]12[回车],然后忽略第一个空格将12读入a1,遇到换行符结束,换行符留在缓冲区
    //假设这里我又用键盘敲下  def[空格]34[回车]
    cin >> s2;//注意!!在这句开始之前缓冲区里的数据不是def[空格]34[回车] 而是[回车]def[空格]34[回车],因为你上次键入的回车还留在缓冲区!!所以这一句是先忽略回车,再将def读入!
    cin >> a2;//忽略空格 将34读入遇到回车结束,回车留在缓冲区不处理!
}

一定要弄懂对分隔符的处理方式,这很重要!!
cin.get()函数
cin 是istream类的一个对象,所以他有类成员函数也并不奇怪,常用的cin.get()方式如下

int get();
istream& get(char& var);
istream& get( char* s, streamsize n );
istream& get( char* s,  streamsize  n, char delim);

先看前两个,读取一个字符,
需要注意的是,和cin不一样,如果一开始有分隔符这种操作是会读取分隔符然后结束的,举个栗子。

#include <iostream>
#include "my_lib.h"
using namespace std;
int main(){
    char c;
    char d;
    //敲入 a[回车]
    cin.get(c);//读入a
    cin.get(d);//读入回车,此时d的ascii码为10,也就是'\n'回车字符!

}

再看第三个读取字符串操作,注意,这里参数为char* 不能为string。s是你要输入的char数组的地址,streamsize是扫描的字符数
get函数会从缓冲区第一个字符开始扫描直到遇到’\n’换行符,或者扫描的字符大于等于streamsize了(也就是最多扫描streamsize-1个),然后将扫描的字符串加上’\0’送入数组(没错,最后会自动给他加一个结束符标识结束)。举个栗子

/*cod.cpp文件*/
#include <iostream>
#include "my_lib.h"
using namespace std;
int main(){
    char s[7] = "hellh";//  初始化字符串,不够的会自动补'\0',s字符串为 h e l l h '\0' '\0'
    //键入[空格]ab[回车]
    cin.get(s,5);//读取空格加ab,遇到回车结束,将回车留在缓冲区此时 s为 [空格] a b '\0' h '\0' '\0'
    char c;
    cin.get(c);//读取缓冲区的回车

}

第四个get()函数把换行符变为了特殊的字符,遇到换行符不再结束,而是遇到该字符结束,不再细讲。
需要注意的是,如果一开始就是一个回车,这时候最好不要用第三四种读入(没什么意义),而且好像之后cin就不起作用了。
cin.getline()函数

istream& getline(char* s, streamsize count); //默认以换行符结束
istream& getline(char* s, streamsize count, char delim);

cin.getline()和第三四种cin.get不同的是,遇到换行符会结束,并清空缓冲区中的换行符
但如果一开始就是一个回车,这种方法不会出错,他会将一个’\0’写入到s中,然后清空这个回车。
getline()函数
cin.get()或者cin.getline()向char*中输入毕竟不太方便,所以c++定义了一个全局函数getline(),可以直接向string中输入.

istream& getline (istream& is, string& str);	// 默认以换行符\n分隔行
istream& getline (istream& is, string& str, char delim);

这个没啥好说的,遇到换行符或者你自定义的delim结束,会自动加上一个’\0’写入string, 然后把换行符清空。
但如果一开始就是一个回车,这种方法不会出错,他会将一个’\0’写入到s中,然后清空这个回车。
因为可以向string输入用法也简单,所以一般都是用这种吧,而且这种还可以和stringstream搭配(刷题必备)。
istringstream ostringtream
和上面的两种一样,只不过是绑定到string上。

/*cod.cpp文件*/
#include <iostream>
#include "my_lib.h"
using namespace std;
int main(){
    string s1="ffrewe";
    string s2;
    istringstream ssin(s1);//s1的内容已经转换成流写入ssin啦
    ostringstream ssout;
    ssout << "fefre fr";//向ssout写入string类型的东西
    s2 = ssout.str();//将ssout的内容输出到s2.
    cout << s2;
}

总结
1、首先要搞清楚各个函数是如何处理分隔符的!!
2、比如刷题的时候,如果告诉你数据的行数n, 每行数据量m,那就直接建一个vectorvector> 然后用for(int i;…) cin>> 就可以了。

/*cod.cpp文件*/
#include <iostream>
#include "my_lib.h"
using namespace std;
//题目:标准输入如下:首先数字n表示有n行,然后是数据m表示每行有m个数据,
//请你将这n*m个数据存储到vector中并输出
int main(){
    int n;
    int m;
    cin >>n>>m;
    vector<vector<int>> v(n,vector<int>(m));
    for(int i=0;i<n;i++){
        for(int j=0;j<m;j++){
            cin >> v[i][j];
        }
    }
}

3、如果只告诉你数据的行数,但不告诉你每行数据有多少呢?

/*cod.cpp文件*/
#include <iostream>
#include "my_lib.h"
using namespace std;
//题目:标准输入如下:首先数字n表示有n行,然后是n行数字每行以换行符结束,请你将这n行数字存储到vector中
int main(){
    int n ;
    cin>> n;
    getchar();//请分析getchar的作用,如果没有会怎样
    vector<vector<int>> v(n);
    for(int i=0;i<n;i++){
        string temp;
        getline(cin, temp);
        istringstream ssin(temp);
        int a;
        while(ssin >> a){
            v[i].emplace_back(a);
        }
    }
    printMatrix(v);
}

需要注意之所以可以用while(ssin>>a)是因为把temp转化为ssin的过程中,它自动在temp的后面加了一个结束符,当ssin遇到结束符时会返回一个非1的值,此时while结束了。你直接用while(cin >> a)读取控制台的内容,那永远不会结束,因为cin >> 遇到换行符会自动过滤掉但并不会结束,就一直阻塞在那了!!所以我们一般看不到也不知道行数也不知道个数的控制台输入,那时候可能要判断缓冲区还有没有数据。。以后在写吧
还有就是各种出错码改状态之类的,有空再写吧。
全文完。。。。如果有用点个赞吧。

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-03-30 18:05:26  更:2022-03-30 18:07:23 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 3:13:26-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码