演讲公文网 - 设为首页 - 加入收藏
  • 热门搜索: 演讲稿 发言稿
  • 当前位置 首页 >主题演讲 >

    c,,课件第十三章输入输出流1

    作者:ufijii 浏览数: 关键词: 十三章 输入输出 课件

     第 第 3 13 章

     输入输出流

     13.1 C++ 的输入和输出

     1 13.1.1 输入输出的含义

     (1) 对系统指定的标准设备进行输入和输出。

     (2) 以外存磁盘文件为对象进行输入和输出。

     (3) 对内存指定的空间进行输入和输出。

     13.1.2 C++的 的 O I/O 对 对 C C 的发展 —— 类型安全和可扩展性

     13.1.3 C++ 的输入输出流

     m 1. iostream 类库中有关的类

     图 图 13.1

     图 图 13.2

     图 图 13.3

     2. 与 与 m iostream 类库有关的头文件

     iostream fstream strstream stdiostream ioma nip

     3. 在 在 m iostream 头文件中定义的流对象

     4. 在 在 m iostream 头文件中重载运算符

     ostream operator << (char *);

      // 用于向输出流插入一个字符串

     cout<<" " C++" "; ;

     相当于

     cout.operator<<(" " C++" " );

     对于自己的类,可用 1 11 章的方法进行重载。

     2 13.2 标准输出流

     13.2.1 cout ,r cerr 和 和 g clog 流

     1. t cout 流对象

     (1 1 )

     t cout 流是流向显示器的数据。

     (2 2 )

     输出基本类型数据时,可以不考虑数据的类型是什么。

     (3 3 )

     t cout 流在内存中对应开辟 了一个缓冲区,用来存放流中的数据,当向 t cout 流插入一个 l endl 时,不论缓冲区是否已满,都立即输出流中的所有数据,然后插入一个换行符,并刷新流(清空缓冲区)。

     2. r cerr 流对象

     r cerr 。

     流是标准错误流。r cerr 。

     流被指定与显示器关联。

     cout流通常是传送到显示器输出,但也可以被重定向输出到磁盘文件。

     例 例 13.1

     解一元二次方程 ax2 2 +bx+c=0

     #include <iostream>

     #include <math.h>

     using namespace std;

     void main()

     { {

     float a, b,c,disc;

     cout<<"please input a,b,c:";

     cin>>a>>b>>c;

     if (a==0)

     cerr<<"a is equal to zero,error!"<<endl;

     else

     if ((disc=b*b- - 4*a*c)<0)

     cerr<<"disc=b*b- - 4*a*c<0"<<endl;

     else

     { {

     cout<<"x1="<<(- - b+sqrt(disc))/(2*a)<<endl;

     cout<<"x2="<<(- -b b- - sqrt(disc))/ (2*a)<<endl;

     } }

     } }

     please input a,b,c:0 2 3

     a is equal to zero,error!

     please input a,b,c:5 2 3

     disc=b*b- - 4*a*c<0

     please input a,b,c:1 2.5 1.5

     x1=- -1 1

     x2=- - 1.5

     g 3. clog 流对象

     g clog 流也是标准错误流,也是在显示器上显示出错信息。与 与 r cerr 的微小区别是:r cerr 不经缓冲区,直接向显示器上输出有关信息,而 g clog 中的信息存放在缓冲区中,缓冲区满后或遇到 enl dl 时向显示器输出。

     2 13.2.2 格式输出

     1. 使用控制符控制输出格式

     例 例 2 13.2 用控制符控制输出格式

     #include <iostream>

     #include <iomanip>

     using namespace std;

     int main()

     {int a;

     cout<<"input a:";

     cin>>a;

     cout<<"dec:"<<dec<<a<<endl;

     cout<<"hex:"<<hex<<a<<endl;

     cout<<"oct:"<<setbase(8)<<a<<endl;

     char *pt="China";

     cout<<setw(10)<<pt<<endl;

     cout<<setfill("*")<<setw(10)<<pt<<endl;

     double pi=22.0/7.0;

     cout<<setiosflags( ios::scientific )<<setprecision(8);

     cout<<"pi="<<pi<<endl;

     cout<<"pi="<<setprecision(4)<<pi<<endl;

     cout<<"pi="<<setiosflags(ios ::fixed)<<pi<<endl;

     return 0;

     } }

     input a:34

     dec:34

     hex:22

     oct:42

     China

     *****China

     pi=3.14285714e+000

     pi=3.1429e+000

     pi=3.143

     2. 用流对象的成员函数控制输出格式

      例 例 13.3

     用流控制成员函数输出数据。

     #include <iostream>

     using namespace std;

     void main()

     { {

     int a=21;

     cout.setf(ios::sh owbase);

     cout<<"dec:"<<a<<endl;

     cout.unsetf(ios::dec);

     cout.setf(ios::hex);

     cout<<"hex:"<<a<<endl;

     cout.unsetf(ios::hex);

     cout.setf(ios::oct);

     cout<<"oct:"<<a<<endl;

     char *pt="China";

     cout.width(10);

     cout<<pt<<endl;

     cout.width(10);

     cout.fill("* ");

     cout<<pt<<endl;

     double pi=22.0/7.0;

     cout.setf(ios::scientific);

     cout<<"pi=";

     cout.width(14);

     cout<<pi<<endl;

     cout.unsetf(ios::scientific);

     cout.setf(ios::fixed);

     cout.width(12);

     cout.setf(ios::showpos);

     cout.setf(ios::internal);

     cout.precis ion(6);

     cout<<pi<<endl;

     } }

     dec:21

     hex:0x15

     oct:025

     China

     *****China

     pi=*3.142857e+000

     +***3.142857

     3 13.2.3 用流成员函数 t put 输出字符

     t put 是用于输出单个字符的成员函数。

     cout.put( "a" );

     cout.put(65+32);

     例 例 13.4

     有一个字符串” BASIC”, ,。

     要求把它按相反的顺序输出。

     #include <iostream>

     using namespace std;

     int

     main()

     {char *a="BASIC";

     for(int i=4;i>=0;i --) )

     cout.put(*(a+i));

     cout.put("\ \ n");

     return 0;

     } }

     也可以用 r putchar 函数实现。

     #include <iostream>

     int main()

     {char *a="BASIC";

     for(int i=4;i>=0;i --) )

     putchar(*(a+i));

     putchar("\ \ n");

     return 0;

     } }

     3 13.3 标准输入流

     n 13.3.1 cin 流

     可以通过测试 n cin 的值,判断流对象是否处于正常状态和提取操作是否成功。

     if(!cin)

     cerr<< "error"; ;

     例 例 13.5

     通过测试 n cin 。

     的值,判断流对象是否处于正常状态。

     #include <iostream>

     using namespace std;

     void main()

     { {

     float grade;

     cout<<"enter grade:";

     while(cin>>grade)

     { {

     if(grade>=85) cout<<grade<<" GOOD!"<<endl;

     i i f(grade<60) cout<<grade<<" fail!"<<endl;

     cout<<"enter grade:";

     } }

     cout<<"The end."<<endl;

     } }

     enter grade:67

     enter grade:89

     89 GOOD!

     enter grade:56

     56 fail!

     enter grade:100

     100 GOOD!

     enter grade:w

     The end.

     2 13.3.2 用于字符输入的流成员函数

     1. 用 用 t get 函数读入一个字符

     (1 1 )

     不带参数的 t get 函数

     cin.ge t();

     用来从指定的输入流中提取一个字符(包括空白字符),函数返回值就是读入的字符。若遇到文件结束符 CTRL+Z, ,

     则函数返回文件结束标志 EOF (E E nd Of File ), , 一般以- -1 1代表 EOF 。

     例 例 13.6

     用 用 t get 函数读入字符。

     #include <iostream>

     using namespace std;

     void main()

     { {

     char c;

     cout<<"enter a sentence:"<<endl;

     while((c=cin.get())!=EOF)

     cout.put(c);

     } }

     enter a sentence:

     I study C++ very hard.

     I study C++ very hard.

     (2 2 )

     有一个参数的 t get 函数

     cin.get(ch);

     量 其作用是从输入流中读取一个字符,赋给字符变量 ch 。读取成功返回真,失败(遇到文件结束符等)返回假。

     #include <iostream>

     using namespace std;

     void main()

     { {

     char c;

     cout<<"enter a sentence:"<<endl;

     while(cin.get(c))

     { {

     cout.put(c);

     }

     cout<<"end"<<endl;

     } }

     (3 3 )

     有三个参数的 t get 函数

     cin.get( 字符指针, , 字符个数 n, 终止字符) )

     其作用是从输入流中读取 n n- -1 1 个字符,赋值个指定的字符取 指针指向的地方。如果在读取 n n- -1 1 个字符之前遇到指定的终止字符,则提前结束读取。如果读取成功则函数返回非0(真),如失败(遇到文件结束符)返回 0 0 (假)。

     #include <iostream>

     using namespace std;

     void main()

     { {

     char ch[20];

     cout< <"enter a sentence:"<<endl;

     cin.get(ch,10,"\ \ n");

     cout<<ch<<endl;

     } }

     enter a sentence:

     I study C++ very hard.

     I study C

     t get 函数的第三个参数可以省略,此时默认为’\ \n n’ 。

     2. 用成员函数 e getline 函数读入一行字符

     e getline 成员函数的作用是从输入流中读取一行字符, , 其用法与带三个参数的 t get 函数类似。

     例 例 13.7

     用 用 e getline 函数读入一行字符。

     #include <iostrea m>

     using namespace std;

     void main()

     { {

     char ch[20];

     cout<<"enter a sentence:"<<endl;

     cin>>ch;

     cout<<"The string read with cin is:"<<ch<<endl;

     cin.getline(ch,20,"/");

     cout<<"The second part is:"<<ch<<endl;

     cin.getline(ch,20);

     cout<<"The third part is: "<<ch<<endl;

     } }

     enter a sentence:

     I like C++./I study C++./I am happy.

     The string read with cin is:I

     The second part is: like C++.

     The third part is:I study C++./I am h

     下一个 e getline 。

     函数将从该终止标志的下一个字符开始读入。

     m 13.3.3 istream 类的其他成员函数

     1. eof 函数

     从输入流中读取数据,如果到达文件末尾,f eof 函数值为真 ,否则为假。

     例 例 13.8 逐个读入一行字符,将其中的非空格字符输出。

     #include <iostream>

     using namespace std;

     void main()

     { {

     char c;

     while(!cin.eof())

     if((c=cin.get())!=" ")

     cout.put(c);

     } }

     C++ is very interesting.

     C++isveryinteresting.

     2. k peek 函数

     c=cin.peek();

     函数的返回值是指针指向的当前字符,但它只是观测,指针仍停留在 当前位置,并不后移。

     3. k putback 函数

     cin.putback(ch);

     其作用是将前面用 t get 或 e getline 函数从输入流中读取的字符返回到输入流,插到当前指针位置,以供后面读取。

     例 例 13.9

     k peek 函数和 k putback 函数的用法。

     #include <iostream>

     using namespace std;

     void main()

     { {

     char c[20];

     int ch;

     cout<<"please enter a sentence."<<endl;

     cin.getline(c,15," /");

     cout<<"The first part is:"<<c<<endl;

     ch=cin.peek();

     cout<<"The next character(ASCII code) is:"<<ch<<endl;

     cin.putback(c[0]);

     cin.getline(c,15,"/");

     cout<<"The second part is:"<<c<<endl;

     } }

     please enter a sentence.

     I am a boy./ am a student./

     The first part is:I am a boy.

     The next character(ASCII code) is:32

     The second part is:I am a student

     图 图 13.4

     4. e ignore 函数

     cin.ignore(n, 终止字符) )

     函数的作用是跳过输入流中的 n n 个字符,或遇到指定的终止字符时提前结束。

     ignore(5,’A A’ );

     // 跳过输入流中的 5 5 个字符,遇到‘A A ’后提前结束。

     ignore(); 相当于

     ignore(1,EOF);

     例 例 13 .10

     用 用 e ignore 函数跳过输 入流中的字符。

     不用 e ignore 函数的情况。

     #include <iostream>

     using namespace std;

     void main()

     { {

     char ch[20];

     cin.get(ch,20,"/");

     cout<<"The first part is:"<<ch<<endl;

     cin.get(ch,20,"/");

     cout<<"The second part is:"<<ch<<endl;

     } }

     I like C++./I study C++./I am happy.

     The

     first part is:I like C++.

     The second part is:

     #include <iostream>

     using namespace std;

     void main()

     { {

     char ch[20];

     cin.get(ch,20,"/");

     cout<<"The first part is:"<<ch<<endl;

     cin.ignore();

     cin.get(ch,20,"/");

     cout<<"The second part is:"<<ch<<endl;

     } }

     I l ike C++./I study C++./I am happy.

     The first part is:I like C++.

     The second part is:I study C++.

     4 13.4 文件操作与文件流

     1 13.4.1 文件的概念

     文件:一般是存储在外部介质(硬盘,光盘,U U 盘)上的数据的集合。

     I ASCII 文件:它的每一个字节放一个 I ASCII 代码,代表一个字符,也称文本文件。用于存储字符信息。

     二进制文件:是把内存中的数据按其在内存中的存储形式原样输出到磁盘上存放。例如整数 100000

     图 图 13 .5

     2 13.4.2 文件流类与文件流对象

     文件流是以外存文件为输入输出对象的数据流。输出文件流是从内存流向外存文件的数据,输入文件流是从外存文件流向内存的数据。每一个文件流都有一个内存缓冲区与之对应。

     用于文件操作的文件流类:

     m ifstream 类,是从 m istream 类派生的。用来读磁盘文件 。

     m ofstream 类,是从 m ostream 类派生的。用来写磁盘文件 。

     m fstream 类,是从 m iostream 类派生的。用来读、写磁盘文件。

     。

     t ofstream out 建立一个输出文件流对象。

     3 13.4.3 文件的打开与关闭

     1. 打开磁盘文件

     (1 1 )

     调用文件流成员函数 open 。

     ofstream out

     建立一个输出文件流对象。

     out(" " f1.dat" " ,ios::out);

     使输出文件流 t out 文件建立关联,此时 t f1.dat 是一个输出文件,用于接收从内存输出的数据。

     调用成员函数 n open 的一般格式为: :

     文件流对象 .open( 磁盘文件名,输入输出方式 );

     (2 2 )

     在定义文件流时指定参数

     ofstream outfile(" " f1.dat" " ,ios::out);

     作用与 n open 函数相同。

     说明:

     ( ( 1 1 本 )

     新 版 本 O I/O 供 类 库 中 不 提 供 ios::nocree ate 和ios::noreplace 。

     (2 2 )每一个打开的文件都有一个文件指针,该指针的初始位置由 O I/O 方式决定,每次读写都从文件指针的当前位置开始。每读入一个字节,指针就后移一个字节。当文件指针移到最符 后,就会遇到文件结束符 CTRL+Z回 ,此时一般返回 EOF (值为- -1 1 )。此时流对象的成员函数 f eof 的值为真, ,。

     表示文件结束了。

     (3 3 )可以用“位或”运算符“| | ”对输出方式进行组合。

     ios::in|ios::nocreate

     (4 4 )如果打开操作失败,n open 函数的返回值为 0 0 (假)

     , 如果是调用构造函数的方式打开文 件的,则流对象的值为 0 0 。可以据此判断打开是否成功。

     if(out(" " f1.dat" " ,ios::app)==0)

     cout<<" " open error" "; ;

     if(!out(" " f1.dat" " ,ios::app))

     cout<<" " open error" "; ;

     2. 关闭磁盘文件

     关闭文件的成员函数 close 。

     out();

     所谓的关闭,就是解除该磁盘文件与文件流对象的关联。此时,该文件流对象就可以和其它磁盘文件关联。

     4 13.4.4 对 对 I ASCII 文件的操作

     对 对 I ASCII 文件的读写操作可以用以下两种方法:

     (1 1 )

     用流插入运算 符“ << ”和流提取运算符“ >> ”输入输

     出标准类型的数据。

     (2 2 )

     数 用流的成员函数 e put,get,getline 等进行输入和输出。

     例 例 13.11

     有一个整型数组,含 0 10 个元素,从键盘输入 0 10 个整数给数组,将此数组送到磁盘文件中存放。

     #include <iostream>

     #include <fstream>

     using namespace std;

     void main()

     { {

     int a[10];

     ofstream outfile("f1.dat");

     //ofstream outfile("f1.dat" ,io s::out );

     if(!outfile)

     { {

     cerr<<"open error!"<<endl;

     exit(1);

     } }

     cout<<"enter 10 integer numbers:"<<endl;

     for(int i=0;i<10;i++)

     { {

     cin>>a[i];outfile<<a[i]<<" ";}

     out();

     } }

     enter 10 integer numbers:

     1 3 5 2 4 6 10 8 7 9

     例 例 13.12 从例 1 13.11 建立的数据文件 t f1.dat 中读入 0 10 个 整数放在数组中,找出并输出 0 10 个数中的最大者和它在数组中的序号。

     #include <iostream>

     #include <fstream>

     using namespace std;

     void main()

     { {

     int a[10],max,i,order;

     ifstream infile("f1.dat",ios::in);

      if(!infile)

     {cerr<<"open error!"<<endl;exit(1);}

     for(i=0;i<10;i++)

     {infile>>a[i];cout <<a[i]<<" ";}

     cout<<endl;

     max=a[0];

     order=0;

     for(i=1;i<10;i++)

     if(a[i]>max)

     {max=a[i];order=i;}

     cout<<"max="<<max<<endl<<"order="<<order<<endl;

     in();

     } }

     1 3 5 2 4 6 10 8 7 9

     max=10

     order=6

     例 例 13.13

     从键盘读入一行字符,把其中的字母字符依次存放在磁盘文件 t f2.dat 中。再把它从磁盘文件读入程序,将其中的小写字母改写为大写字母,再存入磁盘文件 f3.dat 。

     #include <iostream>

     #include <fstream>

     using namespace std;

     void save_to_file()

     { {

     ofstream outfile("f2.dat");

     if(!outfile)

     {cerr<<"open f2.dat error!"<<endl;exit(1);}

     char c[80];

     cin.getline(c,80);

     for(int i=0;c[i];i++)

     i i f(c[i]>=65 && c[i]<=90||c[i]>=97 && c[i]<=122)

     {out(c[i]);cout<<c[i];}

     cout<<endl;

     out();

     } }

     void get_from_file()

     { {

     char ch;

     ifstream infile("f2.dat",ios::in);

     if(!infile)

     {cerr<<"open f2.dat error!"<<endl;exit(1);}

     ofstream outfile("f3.dat");

     if(! outfile)

     {cerr<<"open f3.dat error!"<<endl;exit(1);}

     while(in(ch))

     { {

     if(ch>=97 && ch<=122)

     ch=ch- - 32;

     out(ch);

     cout<<ch;

     } }

     cout<<endl;

     in();

     out();

     } }

     void main()

     { {

     save_to_file();

     get_from_file();

     } }

     New Beijing,Great Olympic,2008,China.

     NewBei jingGreatOlympicChina

     NEWBEIJINGGREATOLYMPICCHINA

     #include <iostream>

     #include <fstream>

     using namespace std;

     void display_ *)

     { {

     ifstream in);

     if(!infile)

     {cerr<<"open error!"<<endl;exit(1);}

     char ch;

     while(in(ch))

     cout.put(ch);

     cout<<endl;

     in();

     } }

     void main()

     { {

     display_file("f3.dat");}

     NEWBEIJINGGREATOLYMPICCHINA

     5 13.4.5 对二进制文件的操作

     1. 用成员函数 d read 和 和 e write 读写二进制文件

     istream& read(char *buffer,int len);

     ostream& write(const char *buffer,int len);

     例 例 4 13.14 将一批数据以二进制形式存放在磁盘文件中。

     #include <iostream>

     #include <fstream>

     u u sing namespace std;

     struct student

     { {

     char name[20];

     int num;

     int age;

     char sex;

     };

     void main()

     { {

     student stud[3]={"Li",1001,18,"f","Fun",

     1002,19,"m","Wang",1004,17,"f"};

     ofstream outfile("stud.dat",ios::binary);

     if(!outfile)

     {cerr<<"open error!"<< endl;abort();}

     for(int i=0;i<3;i++)

     out((char*)&stud[i],sizeof(stud[i]));

     // out((char *)&stud[0],sizeof(stud));

     // 可以替代上述 for ,一条语句完成写工作。

     out();

     } }

     例 例 13.15

     将刚才以二进制形式存放在磁盘文件中的数据读入内存并在显示器上显示。

     #include <iostream>

     #include <fstream>

     using namespace std;

     str uct student

     { {

     char name[20];

     int num;

     int age;

     char sex;

     };

     void main()

     { {

     student stud[3];

     int i;

     ifstream infile("stud.dat",ios::binary);

     if(!infile)

     {cerr<<"open error!"<<endl;abort();}

     for(i=0;i<3;i++)

     in((char*)&stud[i],sizeof(stud[i]));

     in( );

     for(i=0;i<3;i++)

     { {

     cout<<"NO."<<i+1<<endl;

     cout<<"name:"<<stud[i].name<<endl;

     cout<<"num:"<<stud[i].num<<endl;;

     cout<<"age:"<<stud[i].age<<endl;

     cout<<"sex:"<<stud[i].sex<<endl<<endl;

     } }

     } }

     NO.1

     name:Li

     num:1001

     age:18

     sex:f

     NO.2

     name:Fun

     num: 1002

     age:19

     sex:m

     NO.3

     name:Wang

     num:1004

     age:17

     sex:f

     2. 与文件指针有关的流成员函数

     函数参数中的“文件中的位置”和“位移量”已被指定为 long型整数,以字节为单位。

     ios::beg 文件开头

     ios::cur

     指针当前位置

     ios::end 文件末尾

     in(100);

     in(- - 50,ios::cur);

     out(- - 75,ios::end);

     2. 随机访问二进制数据文件

     例 例 13.6

     有 有 5 5 个学生的数据,要求:

     (1 1 )

     把它们存到磁盘文件中;

     (2 2 )

     将磁盘文件中的第 第 1 1 、3 3 、5 5 个学生数据读入程序,并显示出来

     (3 3 )

     将第3 3 个学生的数据修改后存回磁盘文件中的原有位置。

     (4 4 )

     的 从磁盘文件读入修改后的 5 5 个学生的数据并显示出来。

     #include <iostream>

     #include <fstream>

     using namespace std;

     struct student

     { {

     int num;

     char name[20];

     float score;

     };

     void main()

     {int i;

     student stud[5]={1001,"Li",85,1002,"Fun",97 .5,

     1004,"Wang",54,1006,"Tan",76.5,1010,"ling",96};

     fstream iofile("stud.dat",ios::in|ios::out|ios::binary);

     if(!iofile)

     {cerr<<"open error!"<<endl;abort();}

     for(i=0;i<5;i++)

     io((char *)&stud[i],sizeof(stud[i]));

     student stud1[5];

     for(i=0;i<5;i= i+2)

     {

     io(i*sizeof(stud[i]),ios::beg);

     io((char *)&stud1[i/2],sizeof(stud1[i]));

     cout<<stud1[i/2].num<<" "<<stud1[i/2].name<<" "<<

     stud1[i/2].score<<endl;

     } }

     cout<<endl;

     stud[2].num=1012;

     strcpy(stud[2].name,"Wu");

     stud[2].score=60;

     io(2* sizeof(stud[0]),ios::beg);

     io((char *)&stud[2],sizeof(stud[2]));

     io(0,ios::beg);

     for(i=0;i<5;i++)

     {

     io((char *)&stud[i],sizeof(stud[i]));

     cout<<stud[i].num<<" "<<stud[i].name<<" "

     <<stud[i].score<<endl;

     } }

     io();

     } }

     1001 Li 85

     1004 Wang 54

     1010 ling 96

     1001 Li 85

     1002 Fun 97.5

     1012 Wu 60

     1006 Tan 76.5

     1010 ling 96

     5 13.5 字符串流

     字符串流是以内存中用户定义的字符数组为输入输出对象。

     1. 建立输出字符串流对象

     ostrstream::ostrstream(char *buffer,int n,int mode=ios::out);

     ostrstream strout(ch,20);

     建立输出字符串流对象 strout ,并使 t strout 与字符数组h ch 关联,流缓冲区大小 20 。

     2. 建立输 入字符串流对象

     istrstream::istrstream(char *buffer);

     istrstream::istrstream(char *buffer,int n);

     istrstream strin(ch2);

     建立输入字符串流对象 strin ,将字符数组 2 ch2 中的全部数据作为输入字符串流的内容。

     istrstream strin(ch2,20);

     将 将 2 ch2 中的前 0 20 个字符作为输入字符串流的内容。

     3. 建立输入输出字符串流对象

     strstream::strstream(char *buff er,int n,int mode);

     strstream strio(ch3,sizeof(ch3),ios::in|ios::out);

     例 例 13.17 将一组数据保存在字符数组中。

     #include <strstream>

     #include <iostream>

     using namespace std;

     struct student

     { {

     int num;

     char name[20];

     float score;

     };

     void main()

     { {

     student stud[3]={1001,"Li" ,78,

     1002,"Wang",89.5,1004,"Fun",90};

     char c[50];

     ostrstream strout(c,30);

     // ostrstream strout(c,10);

     for(int i=0;i<3;i++)

     strout<<stud[i].num<<stud[i].name<<stud[i].score;

     strout<<ends;

     cout<<"array c:"<<endl<<c<<endl;

     } }

     array c:

     1001Li7 81002Wang89.51004Fun90

     例 例 13.18

     在一个字符数组 c c 中存放了 0 10 个整数, , 以空格相间隔,要求将它们放到整型数组中,再按大小排序,然后在存放回字符数组 c c 中。

     #include <strstream>

     #include <iostream>

     using namespace std;

     void main()

     { {

     char c[50]="12 34 65 - - 23 - - 32 33 61 99 321 32";

     int a[10],i,j,t;

     cout<<"array c:"<<c<<endl; ;

     istrstream strin(c,sizeof(c));

     for(i=0;i<10;i++)

     strin>>a[i];

     cout<<"array a:";

     for(i=0;i<10;i++)

     cout<<a[i]<<" ";

     cout<<endl;

     for(i=0;i<9;i++)

     for(j=0;j<9- - i;j++)

     if(a[j]>a[j+1])

     {t=a[j];a[j]=a[j+1];a[j+1]=t;}

     ostrstream strout(c,size of(c));

     for(i=0;i<10;i++)

     strout<<a[i]<<" ";

     strout<<ends;

     cout<<"array c:"<<c<<endl;

     } }

     array c:12 34 65 - - 23 - - 32 33 61 99 321 32

     array a:12 34 65 - - 23 - - 32 33 61 99 321 32

     array c:- - 32 - - 23 12 32 33 34 61 65 99 321

     实验:

     1 1 :实验目的:

     (1) 深入理解 C++ 的输入输出的含义与其实现方法。

     (2) ) 掌握标准输入输出流的应用,包括格式输入输出。

     (3) 掌握对文件的输入和输出操作。

     2 2 :实验内容:

     P458 1

     4

     3 3 :实验结果。

     7.4.4

     创建文件流

     操作系统中另一个常配置的设备是文件设备( ( 磁盘、磁带等) ) ,在文件设备上可建立一个文件,对文件进行操作,在文件处理完之后还应关闭文件。

     系统通过对流类进一步扩展,提供了支持文件的能力,这使得程序员在建立和使用文件时,就像使用 n cin 和 和 t cout 一样图 方便。图 2 7.2 表示扩展处理文件的类型级,新派生的五个类用于文件处理。

     类是 f streambuf , 的派生用类, 它提供了对文件缓冲区管理的能力,我们一般不涉及这个类。e fstreambase 类提供了文件处理所需要的全部成员函数,在它的派生类中没有提供的新的成员函数;m ifstream 类用于文件的输入操作;而 ofstream; 类用于文件的输出操作;m fstream 类允许对文件在两个方向上进行操作,这几个类也同时继承了我们前面介绍的流类的基本类等级中定义的成员函数。

     在使用类时,必须在程序中嵌入文件 fstream.h 。

     1. 文件的打开和关闭

     通过打开一个文件,可以将一个流与一个文件相联结。一个文件在打开时,必须指定文件打开方式。

     在类中定义的一组枚举常量名给出了可允许的文件打开方式如下所示:

     常量名

     含

     义

     in

      打开文件进行读操作

     out

     打开文件进行写操作

     ate

      文件打开时将文件指针定位于文件尾

     app

     把要输出给文件的内容都添加到文件尾

     ios

      istream ifstrea

     iostream

     ostream

      streambuf

      fstream fstreambas ofstrea一个指针成员 指向该类对象

     图 7.2

     文件 I/O 流库类等级

     trunc

      如果文件存在,将其长度截断为零并清除原有内容

     nocreate

     如果文件不存在,则打开操作失败

     noreplace

      如果文件存在,除非设置 e ios :: ate 或ios :: app, 否则打开文件失败

     binary

     指定文件以二进制方式打开,缺省为文本方式

     ios::app

      The function performs a seek to the end of file. When new bytes are written to the file, they are always appended to the end, even if the position is moved with the ost ream::seekp function.

     ios::ate

      The function performs a seek to the end of file. When the first new byte is written to the file, it is appended to the end, but when subsequent bytes are written, they are written to the current position

     除 除 p ios :: app 方式之外,文件 刚打开时,指示当前读写而 位置的文件指针定位于文件的开始位置,而 p ios ::app 使文件当前的写指针定位于文件尾。

     式 在打开一个文件时,若指定方式 ios :: out ,而未指定ios :: ate 或 或 ios :: app ,则隐含方式为 ios ::trunc 。

     也可以将几种方式通过“或”操作结合起来,例如打开一个供读写的文件,其方式可以定义为 ios :: in|ios :: out。

     。

     可以有两种方法以一定方式打开一个文件

     ,一种方式是在建立时使用构造函数将一个文件和这个流对象联结起来。在 在 m ifstream 、 类、 ofstm ream 类和 m fstream 类中定义有一个构造函数,它们是:

     ifstream :: ifstream(char * ,int=ios :: in,int = :: openprot);

     ofstream :: ofstream(char * ,int=ios :: out,int=flebuf :: openprot);

     fstream :; fstream(char * ,int,int= :: operprot);

     在这三个构造函数中,第一参数表示要联结的文件名,第, 二个参数指定该文件打开的方式, ifstm ream 类和 m ofstream 类的构造函数提供了缺省值。如果不使用这个缺省值时,则必须在指定的方式中含有 n ios :: in 或 或 ios :: out 。最后一个参数指定文件的保护方式,这个值和具体的操作系统有关,我们一般只使用缺省指定的

     t ::openprot 值,它是在

     类中定义的一个公有的静态数据成员。

     【例 7.8 】将一个文件的内容拷贝到另一个文件中。

     #include<fstream.h>

     #include<string.h>

     #include<stdlib.h>

     void main()

     { {

     ifstream

     input("c:\ \\ \ xx.cpp");

     if(!input)

     { {

     cout<<"Can"t open file;"<<"c:\ \\ \ xx.cpp"<<endl;

     exit(1);

     } }

     ofstream output("c:\ \\ \ yy.cpp");

     if(!output)

     { {

     cout<<"Can"t open file;"<<"c:\ \\ \ yy.cpp"<<endl;

     exit(1);

     } }

     //input.tie(&output);

     char ch;

     //input.uns etf(ios::skipws);

     while(input>>ch)

     //while(input.read(&ch,1))

     //while(input.get(ch))

     //while((ch=input.get())!=- - 1)

     { {

     output<<ch;

     //output.put(ch);

     //output.write(&ch,1);

     cout<<(int)ch<<" "<<ch<<endl;

     } }

     cout<<"new line "<<(int)ch<<" "<<ch<<en dl;

     cout<<"end";

     input.close();

     output.close();

     } }

     #include<fstream.h>

     #include<string.h>

     #include<stdlib.h>

     void main(int argc,char *argv[])

     { {

     if(argc!=3)

     { {

     cout<<"Error;usage "<<argv[0]<<" file1 file2<CR>"<<endl;

     exit(1);

     } }

     ifstream input(argv[ 1]);

     if(!input)

     { {

     cout<<"Can"t open file;"<<argv[1]<<endl;

     exit(1);

     } }

     ofstream output(argv[2]);

     if(!output)

     { {

     cout<<"Can"t open file;"<<argv[2]<<endl;

     exit(1);

     } }

     //input.tie(&output);

     char ch;

     //input.unsetf(ios::skipws);

     //while(input>>ch)

     / / /while(input.read(&ch,1))

     while(input.get(ch))

     //while((ch=input.get())!=- - 1)

     { {

     //output<<ch;

     //output.put(ch);

     output.write(&ch,1);

     cout<<(int)ch<<" "<<ch<<endl;

     } }

     cout<<"new line "<<(int)ch<<" "<<ch<<endl;

     cout<<"end";

     input.close();

     output.cl ose();

     } }

     除提取符外,m istream 类还定义了几个成员函数进行无格式化的提取操作,其中进行单字符提取操作的是:

     istream& istream::get(unsigned char&);

     istream& istream::get(signed char&);

     int istream::get();

     istream& istream::read(char *,int);//按 按 t int 的数读取字符放入 char * 中

     前两个成员函数其实一样,它们将提取的字符通过参数传回给调用者,当遇到文件结束标志 CTRL LZ +Z 时,这两个函数返回 回 0 0 值,提取的字符的值为 EOF 为- -1 1 。第三个函数通过返回值返回提取的字符,当遇到文件结束标志 CTRLZ +Z 时返回 EOF(在 h iostream.h 中定义,值为- -1 1 )。第四个函数按 t int 的数

     读取字符放入 char * 中,当遇到文件结束标志 CTRLZ +Z 时,这个函数返回 0 0 值,提取的字符的值为 10 ,即 0x0A 。各个函数的返回值,参见最后一节的 ios :: operator void *();

     文本文件和二进制文件最根本的区别是进行 O I/O 操作时,对’\ \n n’ (该字符的 I ASCII 为 为 0x0A 即换行符)字符 的解释方式。当文件以文本方式打开时,流类在向文件缓冲区插入字符时,凡遇到代吗为 A 0x0A 时,都将其扩展为两个字符,即 0x0D( 回车) )和 和 0x0A (换行),这是操作系统(例如 MS- - DOS )对文本文件所要求的格式。当从流中提取一个字符时,当流遇到字符D 0x0D 时,流类都将它和其后的字符 0 0A x0A 合并为一个字符’\ \n n’ 。当文件以二进制方式打开时,所有的字符都按一个二进制字节处理,不在对 A 0x0A 字符作变换处理。

     除插入符外,m ostream 类定义了下面两个进行无格式插入操作的成员函数

     ostream& ostream::pu t(char)

     ostream& ostream::write(char *,int)

     意义与提取操作类似。

     这个程序在遇到文件结束标志时终止。当流对象 t input 和t output 的生命期结束时,它们的析构函数分别关闭和这两个从 对象相联系的文件。可以使用从 e fstreambase 类继承的成员函数:

     void fstreambase : : close():

     来关闭文件流。

     当我们作用成员函数关闭一个文件之后,反映流状态字被清零,并且使一个流对象和文件相脱离。

     可以使用成员函数将一个流对象和一个文件相联结,成 员函数和类中定义,在它的派生类中被重定义为:

     void ifstream :: open(char *,int=ios :: in,int= :: openprot);

     void ofstream :: open(char *,int=ios :: out,int= :: openprot);

     void fstream :: open(char *,int,int= :: openprot);

     成员函数的参数及其意义和前面介绍的相应类的构造函数的参数完全相同。

     有时,我们在建立一个流对象时,并不知道这个流对 象和哪个文件相联系,这时可以使用 m ifstream 类、m ofstream 类和m fstream 类定义的缺省构造函数建立一个流对象,当以后需要将这个流对象和一个文件相联系时,可以再使用函数 open()。

     。

     【例 7.9 】从一个整数组成的文件中读入一个整数,然后将其扩大一倍之后,存入另一个文件中。

     #include<fstream.h>

     #include<stdlib.h>

     void main()

     { {

     char [8];

     ifstream input;

     ofstream output;

     cout<< "Enter the input :";

     cin>>;

     input.open();

     cout<< "enter the output :";

     cin>>;

     output.open();

     int number;

     while(input>>number)

     output<<2*number<<"\ \ n";

     input.close();

     output.close();

     } }

     这个程序预先建立了两个流对象 t input 和 output, 接着提请用户输入相应的文件名,然后将这两个流对象分别和这两个文件名所表示的文件相 联结。

     读者可以像建立程序文件那样,建立一个输入文件,在这个输入文件中输入几个用空白隔开的整数,试着运行一下这个程序。

     1 1. . 在流内随机移动

     类中提供了三成员函数,用于在输入流内随移动文件的当前指针,它们的原型是:

     istream& istream :: seekg(streampos);

     // 字符 g g代表输入

     istream& istream :: seekg(streamoff,seek_dir);

     istream& istream :: tellg();

     中 其中 s streampos 和 和 f streamoff 在 在 iosh tream.h 中使用f typedef 定义为:

     typedef long streampos;

     typedef long streamoff;

     r seek_dir 是一个枚举类型,它在类中定义为:

     enum seek_dir{beg=0;cur=1,end=2};

     我们先解释成员函数:

     istream& istream :: seekg(streamoff,seek_dir);

     其中,r seek_dir 规定了在输入流中移动文件指针的参照位置 ,f streamoff 指定了相对于该参照位置的偏移量。seek_r dir 的值具有下列含义:

     cur

     相对于文件指针的当前位置

     beg

     相对于文件的开始位置

     end 相对于文件的结束位置

     例如,t input 是个输入流对象,则:

     input.seekg(- - 10,ios::cur) 将文件指针移到以当前位置为基准向前偏移(文件头的方向)0 10 个字节。

     input.seekg(10,ios::beg) 将文件指针移到相对于文件开始位置向后偏移 0 10 个字节的位置上。

     input.seekg(- - 10,ios::end) 将文件指针移到相对于文件结束位置向前偏移 0 10 个字节的位置上。

     不能将文件指针 移到文件开始之前,也不能将文件指针移到文件结束标志的后面。

     函 数 ) tellg() 返 回 当 前 文 件 指 针 的 位 置 , 而seekg(streampos) 则依据这个返回值将文件指针重置到这个位置上。

     例如:

     streampos pos=input.tellg();// 这是绝对指针

     input>>number;

      // 读一个整数

     //...

     input.seekg(pos);

     input>>number;

     // 还是读这个数

     一旦设置了文件指针,下一次的提取从这个指针位置开始,根据提取 的字符数 n n ,提取操作完成之后,指针相应地被动 向后移动 n n 个字节 ,以使当前文件指针指向下一次提取操作应提取的内容。m istream 类使用 tellg()和 和 seekg() 所管理的文件指针又称读指针。

     m ostream 类定义三个成员函数用来管理写指针,写指针指明一次插入(写)操作的位置,这个指针根据向流中插入字符数 n, 也是自动地被向后移动 n n 个字节 ,以保证下一次写操。

     作不覆盖这次所写的内容。m ostream 类中给出的这三个成员函数的原形是:

     ostream& ostream :: seekp(streampos);// 字符p p 代 表输入

     ostream& ostream :: seekp(streamoff,seek_dir);

     ostream& ostream :: tellp();

     的 这三个成员函数的含义和对应的 m istream 类中的成员函数的含义相同,只是它们用于管理写指针。

     不能将文件指针移动到文件开始之前,但可将文件指针移动到文件结束标志以后这时,文件结束标志和移动后的文件指针之间的数据是不确定的。

     下面是演示文件随机访问的例子。

     【例 7.10 】演示文件随机访问的例子。

     #include<fstream.h>

     v v oid main()

     { {

     fstream f( "DATA",ios::in|ios::out|ios::binary);

     int i;

     for(i=0;i<20;i++) // 写无格式的 0 20 个二进制整数

     f.write((char *)&i,sizeof(int));

     streampos pos=f.tellp(); // 记录当前写指针

     for(i=20;i<40;i++) // 再写无格式的 20 个二进制整数

     f.write((char *)&i,sizeof(int));

     f.seekg (pos); // 将读指针定位在 s pos 指向的位置上

     f.read((char *)&i,sizeof(int));

     cout<< "The data stored is "<<i<<endl;

     f.seekp(0,ios::beg); // 移到文件开始

     for(i=100;i<140;i++) // 重写文件内容

     f.write((char *)&i,sizeof(int));

     f.seekg(pos); // 仍将读指针定位在 pos 指向的位置上

     f.read((char *)&i,sizeof( int));

     cout<< "The data stored is "<<i<<endl;

     } }

     程序的输出是:

     The data stored is 20

     The data stored is 120

     在这个程序中,我们将文件打开方式指定为二进制方式,并且为输入和输出方式,这样就可以在一个文件内进行读和写操作。当进行文件随机访问时,文件的打开方式最好指定二进制方式,以防止将值为 A 0x0A 的字符( i=10 )转换成 0x0D和 和 A 0x0A 两个字符,影响程序对文件的正确定位。读者试着以文本方式重新运行上面的程序,程序的 输出结果为:

     The data stored is 19

     The data stored is 30976

     其中第二行的输出结果是个任意值。

     除非有把握肯定以文本方式打开的文件不会影响对文件的随机访问,否则就使用二进制方式打开一个文件。

     对于键盘、显示终端以及磁带机这样的设备,是不能进行随机访问的。这也就是为什么我们在介绍流类的基本类等级时,没有介绍随机访问操作的原因。键盘、显示终端、打印机和绘图仪都是字符设备,提取和插入操作的开始位置都只能是当前位置(顺序访问)。磁带机不属于随机设备,也不能进行随机访问( 只能进行顺序访问)。

     3. 将输出流系到输入流上

     仍可以使用 ios 类中定义的成员函数 tie 将一个输出流系到一个输入流上,例如

     ifstream in(“ infile” );

     ofstream out(“ outfile”) )

     in.tie(&out);

     在以后输入流 n in 提取数据之前,系统首先自动刷新输出流 流 t out 的缓冲区,程序员可以使用 m ostream 类中定义的成员函数 flush() 来刷新一个流的缓冲区,例如:

     out.flush();

     或使用操作算子 flush 。例如:

     out<<flush;

     4. 指向 流的指针

     下面这个程序是前面的拷贝程序修订版,它在用户只在命令行给出一个参数的情况下,将这个命令行参数指定的文件的内容拷贝到屏幕上。

     例 【例 7.11 】将一个文件的内容拷贝到另一个文件中的修订版程序实例。

     #include<fstream.h>

     #include<stdlib.h>

     void main(int argc,char * argv[])

     { {

     void copy(istream * ,ostream *);

     ostream * output=&cout;

     if(argc<2)

     { {

     cout << "Error:usage prog filel[file2]<CR>"<<endl;

     exit(1);

     } }

     ifstream input(argv[1]);

     if(argc==3)

     { {

     output=new ofstream(argv[2]);

     if(!input||!output||!*output)

     cerr<< "Error occur when open a file: "<<endl;

     t //!input 和t !*output 是文件打开是否成功即流是否正常t ,!output 是内存分配是否成功

     } }

     //cout<<input.eof()<<endl;

     copy(&input,output);

     //cout<<input.eof()<<endl;

     if(argc==3)

     delete output;

     } }

     void copy(istream *in,ostream * out)

     { {

     char ch;

     while(in- - >get(ch))

     out- - >put(ch);

     } }

     由于在 s ios 类中将赋值和初始化的语句说明为私有的,这就使得两个流对象之间不能进行赋值和初使 化操作,因而流对象不能用作函数的参数或返回值。但将一个流对象的指针或引用作为函数的参数或返回类型是可以的,而且也应这样使用 。

     从 从 m istream 类、m ostream 类和 m iostream 类中公有派生了三个类:

     class istream_withassign:public istream

     class ostream_withassign:public ostream

     class iostream_withassign:public iostream

     在这三个派生的类中分别定义赋值操作如下:

     istream_wit hassign& istream_withassign::operator=(istream&);

     ostream_withassign& ostream_withassign::operator=(ostream&);

     iostream_withassign& iostream_withassign::operator=(ios&);

     n cin 被定义为 istream- -n withassign 类的对象, cout、 、 cerr和 和 g clog 都是 n ostream_withassign 类的对象,所以这四个预定义的流可以用于赋值操 作。

     7.5

     流的错误处理

     在对一个流对象进行...

    相关文章:

    Top