C++笔记——输入和输出

一、输入输出的基本概念

1、与输入输出流操作相关的类

  • istream是用于输入的流类,cin就是该类的对象。
  • ostream是用于输出的流类,cout就是该类的对象。
  • ifstream是用于从文件读取数据的类。
  • ofstream是用于向文件写入数据的类。
  • iostream是既能用于输入,又能用于输出的类。
  • fstream 是既能从文件读取数据,又能向文件写入数据的类。

2、标准流对象

(1)输入流对象: cin 与标准输入设备相连
(2)输出流对象:cout 与标准输出设备相连
                               cerr 与标准错误输出设备相连
                               clog 与标准错误输出设备相连
           缺省情况下
             cerr << "Hello,world" << endl;
              clog << "Hello,world" << endl;
             和 cout << “Hello,world” << endl; 一样

(3)流流向

  • cin对应于标准输入流,用于从键盘读取数据,也可以被重定向为从文件中读取数据。
  • cout对应于标准输出流,用于向屏幕输出数据,也可以被重定向为向文件写入数据。
  • cerr对应于标准错误输出流,用于向屏幕输出出错信息,
  • clog对应于标准错误输出流,用于向屏幕输出出错信息,
  • cerr和clog的区别在于cerr不使用缓冲区,直接向显示器输出信息;而输出到clog中的信息先会被存放在缓冲区,缓冲区满或者刷新时才输出到屏幕。

(4)判断输入流结束

//可以用如下方法判输入流结束:
int x;
while( cin>>x ){
    …..
}
return 0;
  • 如果是从文件输入,比如freopen(“some.txt”,”r”,stdin);那么,读到文件尾部,输入流就算结束
  • 如果从键盘输入,则在单独一行输入 Ctrl+Z

3、istream类的成员函数

(1)istream & getline(char * buf, int bufSize);

        从输入流中读取bufSize-1个字符到缓冲区buf,或读到碰到‘\n’为止(哪个先到算哪个)。

(2)istream & getline(char * buf, int bufSize,char delim);
        从输入流中读取bufSize-1个字符到缓冲区buf,或读到碰到delim字符为止(哪个先到算哪个)。

       注:两个函数都会自动在buf中读入数据的结尾添加\0’。,‘\n’或delim都不会被读入buf,但会被从输入流中取走。如果输入流中‘\n’或delim之前的字符个数达到或超过了bufSize个,就导致读入出错,其结果就是:虽然本次读入已经完成,但是之后的读入就都会失败了。可以用 if(!cin.getline(…)) 判断输入是否结束

(3)bool eof();                                                                     判断输入流是否结束
(4)int peek();                                                                     返回下一个字符,但不从流中去掉.
(5)istream & putback(char c);                                            将字符ch放回输入流
(6)istream & ignore( int nCount = 1, int delim = EOF );     从流中删掉最多nCount个字符,遇到EOF时结束。

4、输入输出重定向

//输出重定向
#include <iostream>
using namespace std;
int main() {
    int x,y;
    cin >> x >> y;
    freopen("test.txt","w",stdout);  //将标准输出重定向到 test.txt文件
    if( y == 0 )                     //除数为0则在屏幕上输出错误信息
        cerr << "error." << endl;
    else
        cout << x /y ;              //输出结果到test.txt
    return 0;
}
//输入重定向
#include <iostream >
using namespace std;
int main() {
    double f;  int n;
    freopen(“t.txt”,“r”,stdin);    //cin被改为从 t.txt中读取数据
    cin >> f >> n;
    cout << f << "," <<n << endl;
    return 0;
}

5、流操纵算子

    使用流操纵算子需要 #include <iomanip>

(1) 整数流的基数:流操纵算子dec,oct,hex,setbase

(2)控制浮点数精度的流操纵算子

  • precision是成员函数,其调用方式为:

                cout.precision(n);

  • setprecision 是流操作算子,其调用方式为:

               cout << setprecision(n); // 可以连续输出
    功能相同:
          —指定输出浮点数的有效位数(非定点方式输出时)
          —指定输出浮点数的小数点后的有效位数(定点方式输出时)
    定点方式:小数点必须出现在个位数后面

double x = 1234567.89,y = 12.34567;
int n = 1234567;
int m = 12;    //浮点数输出最多6位有效数字      输出:
cout << setprecision(6) << x << endl          1.23457e+006  12.3457
<< y << endl << n << endl << m;               1234567  12

double x = 1234567.89,y = 12.34567;
int n = 1234567;
int m = 12;     //以小数点位置固定的方式输出    
cout << setiosflags(ios::fixed) <<           //输出:
setprecision(6) << x << endl                   1234567.890000  12.345670
<< y << endl << n << endl << m;                1234567  12

double x = 1234567.89;
cout << setiosflags(ios::fixed) <<           //输出:
setprecision(6) << x << endl <<                1234567.890000
resetiosflags(ios::fixed) << x ;               1.23457e+006
//取消以小数点位置固定的方式输出

(3)设置域宽的流操纵算子

       设置域宽(setw,width)两者功能相同,一个是成员函数,另一个是流操作算子,调用方式不同:
             cin >> setw(4); 或者 cin.width(5);4
             cout << setw(4); 或者 cout.width(5);

(4)用户自定义流操纵算子

ostream &tab(ostream &output){
    return output << '\t';
}
cout << “aa” << tab << “bb” << endl;
//输出:aa bb

   这是因为 iostream 里对 << 进行了重载(成员函数)
       ostream & operator<<( ostream & ( * p ) ( ostream & ) ) ;
   该函数内部会调用p所指向的函数,且以 *this 作为参数,例如:hex 、dec 、oct 都是函数

二、文件读写

1、创建文件

#include <fstream>     // 包含头文件
ofstream outFile(“clients.dat”, ios::out|ios::binary); //创建文件
– clients.dat”  要创建的文件的名字
– ios::out      文件打开方式
  • ios:out     输出到文件, 删除原有内容
  • ios::app    输出到文件, 保留原有内容,总是在尾部添加
– ios::binary   以二进制文件格式打开文件
也可以先创建ofstream对象,再用 open函数打开
ofstream fout;
fout.open("test.out",ios::out|ios::binary);
判断打开是否成功:
if(!fout){
    cout << “File open error!”<<endl;
}
文件名可以给出绝对路径,也可以给相对路径。没有交代路径信息,就是在当前文件夹下找文件

2、文件的读写指针

  • 对于输入文件,有一个读指针;
  • 对于输出文件,有一个写指针;
  • 对于输入输出文件,有一个读写指针;
  • 标识文件操作的当前位置, 该指针在哪里,读写操作就在哪里进行。
ofstream fout("a1.out",ios::app); //以添加方式打开
long location = fout.tellp();     //取得写指针的位置
location = 10;
fout.seekp(location);             // 将写指针移动到第10个字节处
fout.seekp(location,ios::beg);    //从头数location,location 可以为负值
fout.seekp(location,ios::cur);    //从当前位置数location
fout.seekp(location,ios::end);    //从尾部数location

ifstream fin(“a1.in”,ios::ate);   //打开文件,定位文件指针到文件尾
long location = fin.tellg();      //取得读指针的位置
location = 10L;
fin.seekg(location);              // 将读指针移动到第10个字节处
fin.seekg(location,ios::beg);     //从头数location
fin.seekg(location,ios::cur);     //从当前位置数location
fin.seekg(location,ios::end);     //从尾部数location

3、二进制文件读写

(1)二进制读文件: ifstream 和 fstream的成员函数
             istream& read (char* s, long n);
       将文件读指针指向的地方的n个字节内容,读入到内存地址s,然后将文件读指针向后移动n字节 (以ios::in方式打开文件时,文件读指针开始指向文件开头) 。

(2)二进制写文件:ofstream 和 fstream的成员函数
             istream& write (const char* s, long n);
        将内存地址s处的n个字节内容,写入到文件中写指针指向的位置,然后将文件写指针向后移动n字节(以ios::out方式打开文件时,文件写指针开始指向文件开头, 以ios::app方式打开文件时,文件写指针开始指向文件尾部 ) 。

//在文件中写入和读取一个整数
#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;
}
//从键盘输入几个学生的姓名的成绩,并以二进制文件形式保存
#include <iostream>
#include <fstream>
using namespace std;
struct Student {
    char name[20];
    int score;
};
int main() {
    Student s;
    ofstream OutFile( "c:\\tmp\\students.dat",ios::out|ios::binary);
    while( cin >> s.name >> s.score )
        OutFile.write( (char * ) & s, sizeof( s) );
    OutFile.close();
    return 0;
}
//将 students.dat 文件的内容读出并显示
int main() {
    Student s;
    ifstream inFile("students.dat",ios::in | ios::binary );
    if(!inFile) {
        cout << "error" <<endl;
        return 0;
    }
    while( inFile.read( (char* ) & s, sizeof(s) ) ) {
        int readedBytes = inFile.gcount(); // 看刚才读了多少字节
        cout << s.name << " " << s.score << endl;
    }
    inFile.close();
    return 0;
}
//将 students.dat 文件的Jane的名字改成Mike
int main(){
    ......
    iofile.seekp( 2 * sizeof(s),ios::beg); // 定位写指针到第三个记录
    iofile.write("Mike",strlen("Mike")+1);
}

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

(1)Linux,Unix下的换行符号:‘\n’ (ASCII码: 0x0a)

(2)Windows 下的换行符号:‘\r\n’ (ASCII码: 0x0d0a) endl 就是 '\n'

(3)Mac OS下的换行符号: ‘\r’ (ASCII码:0x0d)

         导致 Linux, Mac OS 文本文件在Windows 记事本中打开时不换行

(4)Unix/Linux下打开文件,用不用 ios::binary 没区别
(5)Windows下打开文件,如果不用 ios::binary,则:

  • 读取文件时,所有的 '\r\n’会被当做一个字符'\n'处理,即少读了一个字符'\r'。
  • 写入文件时,写入单独的'\n'时,系统自动在前面加一个'\r',即多写了一个'\r'

猜你喜欢

转载自blog.csdn.net/wys7541/article/details/81530440