输出一个pen,输出一个apple,啊♂

总结

标准流对象

  • 输入流:cin 标准输入
  • 输出流:cout 标准输出
  • 输出流:cerr 标准错误输出
  • 输出流:clog 标准错误输出

缺省的情况,coutcerrclog效果相同

  • cin 是标准输入流,用于从键盘读取数据,但是也可以重定向为从文件读取数据
  • cout是标准输出流,用于向屏幕输出数据,也可以向文件写入数据
  • cerr和clog对应标准错误输出,用于向屏幕输出信息

    cerr不适用缓冲区,直接输出

    clog先被放到缓存区

重定向

直接freopen

getline

  • istream& getline(char* buf, int bufSize)

    从输入流读取bufSize-1个字符到缓冲区buf,或者碰到\n字符为之

  • istream& getline(char* buf, int bufSize, char delim)

    从输入流中读取bufSize-1个字符到buf,或者碰到delim字符为止

两个函数都会在读入的数据末尾添加\0,并且\ndelim不会被读入buf

如果把缓冲区写爆了,之后的读入都会失败

我们可以用if(!cin.getlin(...))来判断输入是否结束

其他函数

  • bool eof(); 判断输入是否结束
  • int peek();返回下一个字符,但是不从流中去掉
  • iostream& putback(char c);把字符c放回输入流
  • istream& ignore(int nCount = 1, int delim=EOF)从流中删掉最多nCount个字符,遇到EOF结束

流操纵算子

可以用来操作io的格式

  • 整数流的基数:流操纵算子dec,oct,hec,setbase
  • 浮点数的精度(setprecision)
  • 设置宽度(setw)
  • 其它的流操纵算子

想要实现,需要引入头文件#include <iomanip>

整数

看代码

int n=10;
cout << n << endl;
cout << hex << n << '\n'
     << dec << n << '\n'
     << oct << n << endl;

输出:

10
a
10
12

注意

这个操纵符是持久操作符,除非遇见新的操作算子,它会一直保持这样的输出方法

浮点数

cout << setprecision(5); 

这个也是持久性的流操作算子。

请注意,这个是四舍五入算法!

默认情况下是非定点方法,也就是超出精度会使用科学计数法。

如果想用顶点输入(也就是一定输出固定的小数),用下面的方法

cout << setiosflags(ios::fixed) << setprecision(6);
//或者
cout << fixed << setprecision(6);

如果想要关闭,那么用下面的

cout << resetiosflags(ios::fixed) << x;
//或者
cout << scientific << x;

就好了

宽度

cin >> setw(4);
cou << setw(4);

注意:

这个设置不是持久的,只对于下次输入/输出有效。

如果cin一次没有读完,那么直到读完为止才会结束定义

填充

cout << setw(5) <<setfill('*') 

不够五位自动填充

对齐

//左对齐
cout << left << x << end;
//右对齐
cout << right << x << endl;
//中间对齐
cout << internal << x << endl;

注意的是internal模式下,如果数字是复数,则负号输出最左边,数字输出在中间。

自定义流操作算子

ostream& tab(ostream& o){
    return o<<'t';
}

cout << "aa" << tab << "bb" << endl;

文件读写

概念

头文件#include <fstream>

输出的话使用如下定义:

ofstream fout("1.txt", ios::out|ios::binary)
//或者
ofstream fout;
fout.open("1.txt",ios::out|ios::binary);

其中:

  • "1.txt"文件的名字
  • “ios::out”文件打开的方式

    • ios::out, 输出到文件,删除原有内容
    • ios::app 输出到文件,保留原有内容,默认在尾部添加
  • ios::binary 以二进制文件格式打开文件

判断是否打开成功

if(!fout){
    cout << "File open error!" << endl;
}

文件的读写指针

  • 输入文件,有一个读指针fin.seekg
  • 对于输出文件,有一个写指针fout.seekp
  • 对于输入输出文件,有一个读写指针

这些指针用于标记在哪里完成读写操作

输出

ofstream fout("1.txt", ios::app);
long location = fout.tellp();    //写指针的位置
location = 10;
fout.seekp(location);    //把写指针移动到第10个字节处

fout.seekp(location,ios::beg);    //从头数往后数
fout.seekp(location,ios::cur);    //从当前位置往后数
fout.seekp(location,ios::end);    //从文件尾数

输入:

ifstream fin("1.txt",ios::ate);    //读取模式打开

lang location = fin.tellg();    //读取指针的位置
location = 10L;
fin.seekg(location);    //移动到第十个字节处
fin.seekg(location,ios::beg);    //从头数
fin.seekg(location,ios::cur);    //当前位置
fin.seekg(location,ios::end);    //从尾部数
可以直接获得文件的长度

location可以是负数!

读写字符文件

可以这么写

ifstream fin("in.txt",ios::in);
ifstream fout("out.txt",ios::out);

fin >> a;
fout << a;

记得最后关闭

fin.close();
fout.close();

二进制文件读写

istream& read(char* s, long n);

将文件读指针向目前为止开始,读取n个字节,到内存s,然后将文件指针向后移动n字节

ios::in打开时,默认指向文件开头
ofstream& write(const char* s, long n);

同上

ios:out,默认指针在开头,ios::app指针指向末尾

在文件中写入和读取一个整数

Code

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

int main(){
    ofstream fout("some.dat",ios::out|ios::binary);
    int x = 120;
    fout.write( (const char*)(&x), sizeof(int));
    fout.close();
    ifstream fin("some.dat",ios::in|ios::binary);
    int y;
    fin.read((char*)(&y), sizeof(int));
    fin.close();
    cout << y << endl;
    return 0;
}

文件中写一个structure

Code

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

struct student{
    //总共24字节的内容
    char name[20];
    int score;
};

int main(){
    student s;
    ofstream out("1.dat",ios::out|ios::binary);
    while(cin >> s.name >> s.score)
      out.write((char*)&s,sizeof(s));
    return 0;
}

读取structure

Code

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

struct Student{
    //总共24字节的内容
    char name[20];
    int score;
};

int main(){
  Student s;
  ifstream fin("1.dat",ios::in|ios::binary);
  if(!fin){
    cerr<<"error"<< endl;
    return 0;
  }
  while(fin.read( (char*)&s, sizeof(s) )){
    int readedBytes = fin.gcount(); //刚才读了多少字节
    cout << readedBytes << endl;
    cout << s.name << " " << s.score << endl;
  }
  fin.close();
  return 0;
}

修改structure

Code

#include <cstring>
#include <iostream>
#include <fstream>
using namespace std;

struct student{
   //总共24字节的内容
   char name[20];
   int score;
};

int main(){
 student s;
 fstream iofile("1.dat",ios::in|ios::out|ios::binary);
 if(!iofile){
   cerr << "error";
   return 0;
 }
 iofile.seekp(2*sizeof(s),ios::beg); //跳转到第三个记录
 iofile.write("Mike",strlen("Mike")+1); 
 iofile.seekg(0,ios::beg); //指针到开头
 while(iofile.read((char*)&s, sizeof(s)))
   cout << s.name << " " << s.score << endl;
 iofile.close();
 return 0;
}

为什么要用二进制呢?

  1. 节省空间

    • 空格和换行
    • int型是4字节,但是4个ASCII是32字节
  2. 便于查找

    • 存储前先排序,然后就可以用二分查找了,通过控制指针跳跃即可

文件的拷贝

Code

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

int 
main(int argc, char* argv[])
  {
    if(argc!=3)
      {
        cerr << "File name missing!" << endl;
        return 0;
      }
    
    ifstream fin(argv[1],ios::binary|ios::in);  //打开文件
    
    if(!fin)
      {
        cerr << "Source file open error" << endl;
        return 0;
      }
    
    ofstream fout(argv[2],ios::binary|ios::out);

    if(!fout)
      {
        cerr << "New file open error" << endl;
        return 0;
      }

    char c;
    while(fin.get(c)) //每次读入一个(非常的低效)
        fout.put(c);  //每次输出一个
    
    fin.close();
    fout.close();

    return 0;
  }

  • 为什么上面的效率很低?

    因为每次为了读取一个字节就调用一次硬盘,调用硬盘速度非常慢,所以效率低。

  • 如何解决?

    使用内存缓冲区。C++默认会读取当前扇区,或相连扇区的所有数据到内存中。

    可以通过加大缓冲区来提速。

二进制文件和文本文件的区别

  • Unix换行号:\n (ASCII码:0x0a)
  • Windows下:\r\n (ASCII码:0x0d0a)
  • MacOS下:\r (ASCII码:0x0d)

导致Linux,MacOS在Windows默认记事本上不换行。

在Unix和MacOS下,用不用ios::binary没区别

在Windows下,如果不用ios::binary,则:

  • 读取文件时,所有的\r\n会被当成一个字符\n处理,少读取了\r
  • 写入文件时,写入单独的\n时,系统自动添加\r,即多写了\r
Last modification:April 5th, 2020 at 09:13 pm
Compared with money, your comment could inspire me more.
相较于钱财,你的留言更能激发我创作的灵感