第17章-输入、输出和文件
来源:互联网 发布:月下的妖樱阿波罗数据 编辑:程序博客网 时间:2024/05/16 14:39
使用cout进行输出:
最简单的情况,输出基本类型:
int a = 10;cout<<a;
输出进本类型,其实本质上是<<
运算符的重载为插入运算符。将右方的变量类型进行处理,最后以字符的形式输出至控制台。也即上方的输出基本是对应这个重载原型:ostream& operator<< (int);
右方的类型包括:
unsigned char、signed char、char、short、unsigned short、int、unsigned int、long、unsigned long、unsigned long long、float、double、long double。
可以说基本上所有整型和浮点型都包括了。
另外一种常见的情况就是输出字符串,操作上就是输出指针,因为字符串用首字符的指针表示,原型有四个:
const signed char*;const unsigned char*;const char*;void*;
简单栗子:
char name[10] = "james";char* pr = "kobe";//这三个对应前三种,基本就是输出字符串cout<<"i like play basketball";cout<<name;cout<<pr;//第四种比较特殊。对于其他类型的指针,都对应于void*,打印地址! int egg = 12; char* amount = "dozen"; cout << &egg; //输出egg的地址 cout << amount; //输出字符串"dozen" cout << (void*)amount; //输出字符串"dozen"的地址,也就是amount指针的值。
拼接输出就不说了:cout<<a<<b<<c;
cout.put()用于显示字符、cout.write()用于显示字符串。没看出来有啥大用处。先写在这里,有用后面再补。
刷新输出缓冲区:
cout<<"im robin";cout<<"im kobe";cout<<"im james";
看上面三句,流程上其实是将这三句依次推入输出缓冲区,也就是在执行第二句输出时,第一句的”im robin”是在输出缓冲区,并没有输出到屏幕上。但运行完还是能看到输出,是因为程序结束时,输出缓冲区被刷新,所以在屏幕上输出了。整个过程屏幕并不是依次显示这三条信息,而是在执行完后,存留在输出缓冲区,程序接受缓冲区被刷新 ,一次性全部显示在屏幕。
此时,问题来了,如果想手动控制刷新输出缓冲区呢?!flush和endl。
flush强制刷新缓冲区,endl强制刷新缓冲区,并插入一个换行符(原来endl还有这么多用处,之前只是简单认为它可以换行。。。)。
用法上:
cout<<flush;cout<<endl;//基本全是用endl,flush基本没见过。。。
格式化输出:
书上关于格式化输出写的比较多,也比较全,例如有:
修改计数系统:cout<< hex;
长期有效
调整字段宽度:cout.width(12);
一次性有效
填充字符:cout.fill('*');
长期有效
设置浮点数精度:cout.precision(2);长期有效
打印末尾的0和小数点:cout.setf(ios_base::showpoint);长期有效
由setf()函数扩展出来的开关设置和选项设置:
ios_base::boolalpha //输入输出bool值,可以为true或falseios_base::showbase //显示基数前缀ios_base::showpoint //显示末尾的小数点ios_base::uppercase //对于16进制输出,就是大写字母E表示法ios_base::showpos //正数前加+ios_base::basefield对应的基数设置: - ios_base::dec //10进制 - ios_base::oct //8进制 - ios_base::hex //16进制ios_base::folatfield对应的浮点数计数法设置: - ios_base::fixed //定点计数法 - ios_base::scientific //科学计数法ios_base::adjustfield对应的对齐方式设置: - ios_base::left //左对齐 - ios_base::right //右对齐 - ios_base::internal //符号或基数前缀左对齐,值右对齐用法:cout.setf(ios_base::showpos); //显示正数前的正号。其余类似cout.setf(ios_base::left, ios_base::adjustfield);//左对齐
说几个点:
- 精度的意义在计数法不同时意义不同。默认计数法时,精度指的是显示总位数、定点和科学计数法时指的是小数位数。所以在设置精度时一定先设置好计数法,在固定计数法的基础上再设置精度。
- 定点和科学计数法显示末尾的0。
- 计数法并没有对应的设置回默认模式的参数符。若要恢复使用
cout.unsetf(ios_base::floatfield);
其实unsetf()函数就是用于各项设置的清除,回归默认的方法。不再举例。
OK!说了这么一大堆是不是感觉天昏地暗,没啥规律不好记但是瞅着还挺常用。好了,这时候C++告诉你,其实前面的东西都被革新掉了,我们有新货。。。。。。
那特么你还说这么多?!
那必须说啊,不然怎么体现C++牛逼(当然最大的用处就是可以看懂别人写的代码)。。。。。
先列一个表:
- boolalpha
- noboolalpha
- showbase
- noshowbase
- showpoint
- nooshowpoint
- showpos
- noshowpos
- uppercase
- nouppercase
- internal
- left
- right
- dec
- hex
- oct
- fixed
- scientific
- setprecision()
- setfill()
- setw()
好了,这个表怎么用呢?
cout<<showbase;cout<<left;cout<<hex;cout<<fixed;cout<<setprecision(8);cout<<setfill('*');cout<<setw(10);还可以穿串。。。。cout<<showbase<<left<<hex<<fixed<<setprecision(8)<<setfill('*')<<setw(10)<<10;
总结一下:你特么倒是早说啊!!!
使用cin输入:
cin基本就是cout的反向过程,将输入的字符转换成对应的目标变量类型,存入其中。字符串的话就是指针,跟cout道理相同。
检查输入:
int elevation;cin >> elevation;
假如输入 -1223z(注意最开头有个空格)。将跳过空格,直到z不满足条件结束,并且会返回false!
也就是可以用while(cin>>elevation){...}
这种形式来控制循环输入。
流状态:
流状态的成员和方法如下表:
clear()将清除3个状态位(eofbit,badbit,failbit)。
clear(eofbit)将状态设置为eofbit,另外两个被清除。
setstate(eofbit)将设置状态为eofbit,另外两个无影响。
重新设置流状态是为了在输入不匹配或到达文件尾部时,用clear()重新打开输入(不然会关闭,不好用)。setstate()主要是提供手动设置途径。
IO和异常:
先说一下,假设某个输入把流状态设置为了eofbit或是failbit或是badbit。但是,并不会引发异常!
要想让其被设置时引发异常,需要用到exceptions()。
#include<iostream>#include<exception> //exception()函数需要引进此头文件 int main(){ using namespace std; cin.exception(ios_base::failbit);//这里将failbit设置为可以引发异常。 int sum = 0; int input; try { while(cin>>input) sun += input; } catch(ios_base::failure & bf)//这里捕获异常 { cout<<bf.what()<<endl;//输出异常内容 } cout<<"last value entered = "<<input<<endl; return 0;}
异常的触发和捕获看情况使用。
流状态的影响:
只有在流状态良好(所有位都被清除)的情况下,cin >> input;
才会返回true。
在触发了一些状态位时,相应的函数会返回bool判断值:if(cin.eof()){cout<<"error";}
。可以用于判断输出信息。
当流状态位被设置后,有一个很严重的后果,就是流会将后续的输入(或输出)关闭,直到位被清除。若不清除,后面的输入(或输出)是不工作的!!!此时就要用到重置流状态位,cin.clear()。
还有一个经常用到的就是,将空白或这整行直接略除掉;
while(cin.get() != ' ') continue;//略除空格,一般就是直到有效信息处。不管跳不跳行!while(cin.get() != '\n') continue;//略除当前行剩下的东西,到换行处!
其他istream方法:
对象方法 get(char&)和get(void)
,不跳过空白的单字符输入。
对象方法 get(char*,int,char)和getline(char*,int, char)
读取整行。
首先,对象方法意味着调用方式都是cin.get()或者cin.getline()这种形式。
重载的>>
运算符是会跳过空白符的!
首先看一下单字符读取:
附表17.5
//cin.get(ch)简单用法:char ch1;while(cin.get(ch1)) //由于到达文件尾部时会返回false,所以可以用于到达尾部判断。{...}//cin.get()简单用法:char ch2ch2 = cin.get();while(ch2 != '\n') //由于返回字符编码值,所以跟具体字符对比会让读取在中间停下。{ ... ch = cin.get();}//cin.get()在到达文件末尾时,可以这样用:while(ch2 = cin.get() != EOF)(多一嘴,是不是中间具体字符停止也能这样用?)while(ch2 = cin.get() != '\n') //换行停下?
cin.get()和cout.put()其实就是为了进化C语言中getchar()和putchar()所设计。所以还是尽量的用cin.get(char*)这种。
(再啰嗦一嘴,C++真的无底洞,只要确切的掌握一种方法,而且满足使用需求即可,千万不要作死想知道所有特性。。。)
字符串输入:
char line[50];cin.get(line, 50, 'z');cin.getline(line, 50, 'z');
说明:
- 第二个参数最大字符数、第三个参数分界符、换行符,这三个先遇到哪个都停止输入。
- get将停止后的换行符和分界符留在输入流中。
- getline将停止后的换行符和分界符从流中读出并丢弃。
还有个ignore方法:cin.ignore(255, '\n');
读取并丢弃接下来的255个字符,或者丢弃到下一个换行处。。。感觉又是坑,之前不还有while continue法丢弃字符麽?!怎瞅着功能这么像。。。
文件输入输出
简单的文件IO:
说明一下,
写入文件对程序来说,是输出,用fout之类。
读取文件对程序来说,是输入,用fin之类。
简单介绍:
#include<fstream> //必须包含头文件fstreamofstream fout; //创建文件输出(对于程序而言)流对象,用于文件写入。fout.open("jar.txt"); //调用open()链接打开文档fout<<"robin"; //将数据输出写入到文档中fout.close(); //关闭链接的文档,可以理解为关闭文档ifstream fin; //创建文件输入流(对于程序而言)对象,用于文件读取。fin.open("her.txt"); //链接打开文档fin>>ch; //从文档中输入数据至ch变量fin.close(); //关闭文档
关闭文档链接时,就可以重新再用open()和close()来链接另外一个文件了。不用重新创建文件IO流对象。
文件打开时有打开模式,后面再说。
is_open()返回文件是否成功打开。
if(!fin.is_open()){ cout<<"file failed to open!"<<endl;}
这是最新的用法,之前的还有一些:
if(fin.fail());if(!fin.good());if(!fin);
知道啥意思就可以了。。。
对于fout基本不存在这个问题,因为没有文件的话会自动创建一个。。。一般就是用于打开输入文件,读取数据时,检查一下是否打开了。
命令行处理:
在终端中:run.exe robin kobe
程序中:int main(int argc, char* argv[])
argc:argument count,命令行参数个数。包括命令(run.exe)。
argv:argument value,命令行值。
所有的命令行参数都解析为字符串。也就说上面的程序和命令行:
argc = 3 //因为三个命令。
argv = {run.exe,robin,kobe} //命令行字符串数组。
调用时,argv[0]即为”run.exe”,argv[1]即为”robin”,argv[2]即为”kobe”。
文件模式:
将流与文件关联时,可以提供第二个参数,指定文件模式:读、写、追加等。
ifstream fin("haha.txt", ios_base::in); //创建流时直接链接并设置。ofstream fout;fout.open("hehe.txt", ios_base::out); //在open方法中设置也可以。
ios_base::trunc的截断会删除之前文件夹内容,若要是追加,用ios_base::app。用|运算符开启多模式。
//典型的打开已存在文件,并且追加写入信息。ofstream fout("haha.txt", ios_base::out|ios_base::app);
各种组合如下图:
ios_base::ate和ios_base::app都将文件指针指向打开文件的末尾,区别在于:
ios_base::app只允许在文件尾部添加数据。
ios_base::ate将指针指向文件尾后,可以进行其他的任何操作。
二进制文件用到再说吧(主要是懒)。。。
随机存取:简单说就是定位到文件的任何一个位置。
seekg()将输入指针移动到指定位置。
seekp()将输出指针移动到指定位置。
seekg()和seekp()都是模板函数,一般使用char类型模板具体化:
istream& seekg(streamoff, ios_base::seekdir); //定位位置后指定偏移量istream& seekg(streampos); //直接指定从开头算起的位置。
栗子:
//原型1对应使用:fin.seekg(30, ios_base::beg); //文件开始位置往后30位fin.seekg(-1, ios_base::cur); //文件当前位置后退一位fin.seekg(0, ios_base::end); //定位到文件末尾//原型2对应使用:fin.seekg(112); //直接将文件指针指向第112个字节,因为从0开始计数,所以,指向的是文件的第113个字节(跟数组定位差不多。。。)fin.seekg(0); //同理,这就是指向文件开头了
如何知道文件指针的当前位置呢?
tellg()返回输入流文件指针当前位置。
tellp()返回输出流文件指针当前位置。
它们都返回一个表示当前位置的streampos值(以字节为单位,从文件开始处算起)。
内核格式化
iostream族支持程序与终端之间的IO。
fstream族支持程序与文件之间的IO。
sstream族支持程序与string对象之间的IO。此就是内核格式话。
这个后续用到再说吧。
- 第17章-输入、输出和文件
- 第17章——输入、输出和文件
- C++ Primer Plus 第17章 输入,输出和文件
- 【读书笔记:C++ primer plus 第六版 中文版】第17章 输入、输出和文件
- 【C++ primer】第十七章 输入、输出和文件
- 输入/输出流和文件操作
- C++——输入、输出和文件
- 第17章 输入输出和文件
- 第17章 输入输出和文件
- 《C++ primer plus》第十七章 输入、输出和文件(一):输入和输出 学习笔记
- 《C++ primer plus》第十七章 输入、输出和文件(二):文件的输入和输出 学习笔记
- 2012/2/11 《C++ Primer Plus》第十七章:输入、输出和文件 学习笔记
- c++primer plus第十七章-cin输入、cout输出和文件I/O
- 标准输入、输出和错误和文件重定向
- 标准输入、输出和错误和文件重定向
- 标准输入、输出和错误和文件重定向
- 【c++笔记十三】c++中的输入、输出和文件操作
- 【c++笔记十三】c++中的输入、输出和文件操作
- svn命令
- HTML之head元素
- 渗透测试之邮件获取对方真实地址
- iOS 学习视频 资料集合 (视频 +博客)
- D3D11 MD5骨骼动画模型的加载
- 第17章-输入、输出和文件
- 2017湖湘杯网络安全大赛Writeup
- YOUNG DAY!
- linux 进程 线程通信
- jq,ajax,表单提交简单的请求方式
- 常用依赖&权限
- 【传智播客郑州校区分享】HTTP/2技术整理
- 干货|如何做有效的代码走查
- 23种模式java