资源描述
第第1111章章 流类库与输入流类库与输入/ /输出输出C+语言程序设计 前一页 休息2 of 78本章主要内容本章主要内容lI/O流的概念流的概念l输出流输出流l输入流输入流l输入输入/输出流输出流 前一页 休息3 of 78I/O流的概念流的概念l当程序与外界环境进行信息交换时,存在着两个当程序与外界环境进行信息交换时,存在着两个对象,一个是对象,一个是程序中的对象程序中的对象,另一个是,另一个是文件对象文件对象。l流是一种抽象,它负责在数据的流是一种抽象,它负责在数据的生产者生产者和数据的和数据的消费者消费者之间建立联系,并管理数据的流动。之间建立联系,并管理数据的流动。l程序建立一个程序建立一个流对象流对象,并指定这个流对象与某个,并指定这个流对象与某个文件对象建立连接,程序操作流对象,流对象通文件对象建立连接,程序操作流对象,流对象通过文件系统对所连接的文件对象产生作用。过文件系统对所连接的文件对象产生作用。l读操作在流数据抽象中被称为(从流中)读操作在流数据抽象中被称为(从流中)提取提取,写操作被称为(向流中)写操作被称为(向流中)插入插入。 前一页 休息4 of 78I/O流的概念流的概念l参见教材参见教材P371图图11-1 I/O流类层次图流类层次图l中的流由相应的类创建,并通中的流由相应的类创建,并通过相应的方法操作。过相应的方法操作。lios类是虚基类,派生出类是虚基类,派生出istream类和类和ostream类。类。 前一页 休息5 of 78I/O流的概念流的概念listream类是通用输入流类和其它输类是通用输入流类和其它输入流的基类,负责创建输入流,其中入流的基类,负责创建输入流,其中定义了输入运算符定义了输入运算符“”的各种重载的各种重载形式,它还包括一些更传统的语句如形式,它还包括一些更传统的语句如get( )和和read( )。listream的派生类的派生类ifstream类负责处理类负责处理文件的输入,文件的输入,istrstream类负责处理类负责处理字符串,字符串,istream_withassign类创建类创建了标准输入对象了标准输入对象cin。 前一页 休息6 of 78I/O流的概念流的概念l相对应地,相对应地,ostream类是通用输出流类是通用输出流类和其它输出流类的基类,定义了输类和其它输出流类的基类,定义了输出运算符出运算符“open(filename,iosmodepmyFile-open(filename,iosmode); ); / /打开文件,使流对象与文件建立联系打开文件,使流对象与文件建立联系输出流 前一页 休息14 of 78输出流对象输出流对象l在一个由文件指示符标识的打开文在一个由文件指示符标识的打开文件基础上构造一个件基础上构造一个ofstream对象。对象。int fd = open(filename,dosmode);int fd = open(filename,dosmode);ofstream myFile1(fd);ofstream myFile1(fd); / Buffered mode(default) / Buffered mode(default)ofstream myFile2(fd,NULL,0);ofstream myFile2(fd,NULL,0); / Unbuffered / Unbuffered mode mode输出流 前一页 休息15 of 78插入运算符(插入运算符()l插入插入()运算符是所有标准运算符是所有标准C+数据数据类型预先设计的。类型预先设计的。l用于传送字节到一个输出流对象。用于传送字节到一个输出流对象。输出流 前一页 休息16 of 78控制输出格式控制输出格式l控制输出宽度控制输出宽度 为了调整输出,可以通过在流中放入setw操纵符或调用width成员函数为每个项指定输出宽度。输出流l转换基控制算子转换基控制算子名名 称称解解 释释dec将转换基设为十进制将转换基设为十进制hex将转换基设为十六进制将转换基设为十六进制oct将转换基设为八进制将转换基设为八进制l流格式带参数操作算子(流格式带参数操作算子(1)名名 称称解解 释释showbase输出整数值时,表明数字的基数(十进制输出整数值时,表明数字的基数(十进制、八、八进制或十六进制进制或十六进制)noshowbase取消取消showbase的设置的设置showpoint表明浮点数的小数点和后面的零表明浮点数的小数点和后面的零noshowpoint取消取消showpoint的设置的设置uppercase显示代表十六进制的大写字母显示代表十六进制的大写字母AF和科学记数和科学记数法中的法中的Enouppercase取消取消uppercase的设置的设置showpos对于正数显示正值符号(对于正数显示正值符号(+)noshowpos取消取消showpos的设置的设置skipws跳过输入中的空白字符跳过输入中的空白字符noskipws取消取消skipws的设置的设置l流格式带参数操作算子(流格式带参数操作算子(2)名名 称称解解 释释left左对齐,右填充字符左对齐,右填充字符right右对齐,左填充字符右对齐,左填充字符internal在引导符或基数指示符和数值之间填充字符在引导符或基数指示符和数值之间填充字符scientific以科学记数法表示浮点值,精度域指小数点后以科学记数法表示浮点值,精度域指小数点后面的数字位数面的数字位数fixed以定点格式表示浮点值,精度域指小数点后面以定点格式表示浮点值,精度域指小数点后面的数字位数的数字位数l流格式带参数操作算子流格式带参数操作算子名名 称称解解 释释setw(int wide)设置流的宽度为设置流的宽度为wide的值的值setprecision (int prec)设置小数点后位数为设置小数点后位数为prec的值(包括小数点)的值(包括小数点)setfill(int fillch)使用使用fillch的值而不是默认的字符填充的值而不是默认的字符填充setbase(base n) 基数设为基数设为n,n这里取这里取10、8和和16setiosflags (fmtflags n)设置设置ios标志标志resetiosflags (fmtflags n)消除消除ios标志的设置标志的设置lios流格式操作函数流格式操作函数名名 称称解解 释释int ios:width()读取当前宽度(默认值为读取当前宽度(默认值为0)int ios:width(int n)设置宽度,返回以前的宽度设置宽度,返回以前的宽度int ios:fill()读当前的填充字符(默认值为空格)读当前的填充字符(默认值为空格)int ios:fill(int n)设置填充字符,返回以前的填充字符设置填充字符,返回以前的填充字符int ios:precision()读取当前的浮点数精度(默认值为读取当前的浮点数精度(默认值为6)int ios:precision(int n) 设置浮点数进度,返回以前的精度值设置浮点数进度,返回以前的精度值 前一页 休息22 of 78ios类中几个重要的格式控制函数类中几个重要的格式控制函数lfmtflags ios:flags(fmtflags newflags);lfmtflags ios:setf(fmtflags ored_flag);lfmtflags ios:unsetf(fmtflags clear_flag);lfmtflags ios:setf(fmtflags bits, fmtflags field);输出流 前一页 休息23 of 78ios类中几个重要的格式控制函数类中几个重要的格式控制函数lios:setf有两个版本,分别对应着不同的标有两个版本,分别对应着不同的标志。如果想知道应该使用哪个重载版本,就志。如果想知道应该使用哪个重载版本,就应该知道正要改变的是哪一类标志。应该知道正要改变的是哪一类标志。l这里的格式化标志分为两类:这里的格式化标志分为两类:l第一类是简单的第一类是简单的on/off,对于它们,使用,对于它们,使用setf()则打开,使用则打开,使用unsetf()则关闭。则关闭。输出流lon/off类型标志类型标志名名 称称解解 释释ios:skipws跳过空白字符(对于输入这是默认的)跳过空白字符(对于输入这是默认的)ios:showbase显示一个整数值时,标明数值基数(十显示一个整数值时,标明数值基数(十进制、八进制或十六进制)进制、八进制或十六进制)ios:showpoint表明浮点数的小数点和后面的零表明浮点数的小数点和后面的零ios:uppercase显示十六进制数值的大写字母显示十六进制数值的大写字母AF和科和科学记数法中的大写字母学记数法中的大写字母Eios:showpos显示加号(显示加号(+),代表正值),代表正值 前一页 休息25 of 78ios类中几个重要的格式控制函数类中几个重要的格式控制函数l第二类格式化标志分为不同的组。一组中,第二类格式化标志分为不同的组。一组中,一次只能一个标志起作用,就如同单选题一一次只能一个标志起作用,就如同单选题一样。样。输出流lios:basefield组标志组标志名名 称称解解 释释ios:dec将基数设为十进制(默认)将基数设为十进制(默认)ios:hex将基数设为十六进制将基数设为十六进制ios:oct将基数设为八进制将基数设为八进制lios:floatfield组标志组标志名名 称称解解 释释ios:scientific科学记数法表示浮点值,精度域指小数科学记数法表示浮点值,精度域指小数点后面的数字位数点后面的数字位数ios:fixed定点格式表示浮点数,精度由定点格式表示浮点数,精度由setprecision或或ios:precision设置设置0精度域为整个有效数字的数目精度域为整个有效数字的数目lios:adjustfield组标志组标志名名 称称解解 释释ios:left左对齐,右填充字符左对齐,右填充字符ios:right右对齐,左填充字符右对齐,左填充字符ios:internal在任何引导符或基数指示符之后但在数在任何引导符或基数指示符之后但在数值之前填充字符值之前填充字符 前一页 休息29 of 78ios类中几个重要的格式控制函数类中几个重要的格式控制函数l使用使用ios操作函数一般都需要单独一行,不操作函数一般都需要单独一行,不能嵌入流中,这使其灵活性受到了一定的影能嵌入流中,这使其灵活性受到了一定的影响。为了摆脱这种笨拙的控制方式,可以使响。为了摆脱这种笨拙的控制方式,可以使用用setiosflags()算子和算子和resetiosflags()算子。算子。l见程序:见程序:C11_7.cpp输出流 前一页 休息30 of 78基本输入操作基本输入操作l见程序:见程序:C11_9.cppl见程序:见程序:C11_10.cppl见程序:见程序:C11_11.cppl见程序:见程序:C11_12.cpp输入流 前一页 休息31 of 78输入控制格式输入控制格式l见程序:见程序:C11_13.cpp输入流l存取模式标志位(存取模式标志位(iosmode)iosmode含含 义义ios:in以只读方式打开文件(用以只读方式打开文件(用ifstream创建对象时默认)创建对象时默认)ios: out以只写方式打开文件(当用于一个没有以只写方式打开文件(当用于一个没有ios:app、ios:ate或或ios:in的的ofstream时,时,ios:trunc是默认设置)是默认设置)ios: app以追加方式打开文件,即写在文件尾部以追加方式打开文件,即写在文件尾部ios:ate打开一个现成的文件(无论输入还是输出)并寻找末尾打开一个现成的文件(无论输入还是输出)并寻找末尾ios:binary以二进制方式打开文件默认时为文本方式以二进制方式打开文件默认时为文本方式ios:nocreate如果文件不存在,打开操作失败(仅打开存在的文件)如果文件不存在,打开操作失败(仅打开存在的文件)ios:noreplace如果文件存在,打开操作失败(仅打开不存在的文件)如果文件存在,打开操作失败(仅打开不存在的文件)ios:trunc如果文件已存在,则将其长度截为如果文件已存在,则将其长度截为0,并清除原来的内容,并清除原来的内容 前一页 休息33 of 78文件的读写文件的读写l见程序:见程序:C11_14.cppl见程序:见程序:C11_15.cppl见程序:见程序:C11_16.cpp 前一页 休息34 of 78文件的随机读写文件的随机读写l在一般情况下,以读方式打开文件时,文件指针在一般情况下,以读方式打开文件时,文件指针总是指向文件的开头;以写方式打开文件时,文总是指向文件的开头;以写方式打开文件时,文件指针总是指向文件的结尾。当读文件时,每读件指针总是指向文件的结尾。当读文件时,每读一个字节,文件指针就向后移动一个字符的位置;一个字节,文件指针就向后移动一个字符的位置;写文件时,每写一个字符后,文件指针就移动到写文件时,每写一个字符后,文件指针就移动到文件的尾部。这种文件指针的移动方式显得非常文件的尾部。这种文件指针的移动方式显得非常被动。为了增加对文件访问的灵活性,被动。为了增加对文件访问的灵活性,C+的的istream类和类和ostream类中定义了一些在输入输出类中定义了一些在输入输出流中操作文件指针的成员函数,使编程者可以方流中操作文件指针的成员函数,使编程者可以方便地操纵文件指针。便地操纵文件指针。 前一页 休息35 of 78文件的随机读写文件的随机读写l一个文件实际上有两个指针,一个用于读,一个文件实际上有两个指针,一个用于读,一个用于写。因此,函数分为对应于一个用于写。因此,函数分为对应于istream类和类和ostream类的两套版本。类的两套版本。l这些操纵指针的函数可以分为这些操纵指针的函数可以分为3类:类: 文件指针相对移动函数 文件指针定位函数 文件指针绝对移动函数 前一页 休息36 of 78文件的随机读写文件的随机读写l在在istream类和类和ostream类中分别定义类中分别定义了不同的相对指针移动函数了不同的相对指针移动函数seekg()和和seekp()。它们的定义如下:。它们的定义如下: istream& istream:seekg(streamof off, ios:seek_dir dir); ostream& ostream:seekp(streamof off, ios:seek_dir dir);文件指针相对移动函数 前一页 休息37 of 78文件的随机读写文件的随机读写l参数参数dir是文件指针相对移动的参照位是文件指针相对移动的参照位置,如下表所列,共有置,如下表所列,共有3种情况,在种情况,在ios中被定义为一个枚举类型中被定义为一个枚举类型seek_dir。文件指针相对移动函数名称名称含含 义义ios:beg文件头部文件头部ios:end文件尾部文件尾部ios:cur当前文件指针的位置当前文件指针的位置 前一页 休息38 of 78文件的随机读写文件的随机读写l参数参数off是相对于参照位置的偏移量,是相对于参照位置的偏移量,其值为正就是往文件尾部移动,为负其值为正就是往文件尾部移动,为负就是往文件头部移动。就是往文件头部移动。Off被定义为被定义为streamoff类型,实际上就是类型,实际上就是long类型。类型。文件指针相对移动函数 前一页 休息39 of 78文件的随机读写文件的随机读写l例如:例如: infile.seekg(3, ios:cur) / 文件指针从当文件指针从当前位置向文件尾部移动前位置向文件尾部移动3个字节个字节 infile.seekg(-5, ios:end) / 文件指针从文件指针从文件尾部向文件头部移动文件尾部向文件头部移动3个字节个字节 outfile.seekp(0, ios:beg) / 文件指针移文件指针移到文件头部到文件头部文件指针相对移动函数 前一页 休息40 of 78文件的随机读写文件的随机读写l对应于对应于istream类和类和ostream类的指针类的指针定位函数分别是定位函数分别是tellg()和和tellp()。其定。其定义如下:义如下: streampos istream:tellg(); streampos ostream:tellp();l它们返回文件指针的当前位置,返回它们返回文件指针的当前位置,返回类型为类型为streampos。同。同streamoff一样,一样,streampos等同于等同于long类型。类型。文件指针定位函数 前一页 休息41 of 78文件的随机读写文件的随机读写 streampos inpos, outpos; inpos = infile.tellg(); / 返回文件返回文件infile的当前文件指针位置的当前文件指针位置 outpos = outfile.tellp(); / 返回文件返回文件outfile的当前文件指针位置的当前文件指针位置文件指针定位函数 前一页 休息42 of 78文件的随机读写文件的随机读写l文件指针的绝对移动函数将指针移动文件指针的绝对移动函数将指针移动到指定的绝对地址上。对应于到指定的绝对地址上。对应于istream类和类和ostream类的成员函数也是类的成员函数也是seekg()和和seekp()。但是它们只有一个。但是它们只有一个参数:参数: istream& istream:seekg(streampos pos); ostream& ostream:seekp(streampos pos);文件指针绝对移动函数 前一页 休息43 of 78文件的随机读写文件的随机读写l参数参数pos通常由文件指针定位函数通常由文件指针定位函数tellg()或或tellp()指定。例如:指定。例如: streampos inpos; inpos = infile.tellg(); Infile.seekg(inpos);文件指针绝对移动函数 前一页 休息44 of 78文件的随机读写文件的随机读写l见程序:见程序:C11_17.cpp 前一页 休息45 of 78例例11-1 使用使用width控制输出宽度控制输出宽度#include void main( ) double values = 1.23,35.36,653.7,4358.24; for(int i=0;i4;i+) cout.width(10); cout valuesi n; 输出流输出结果是输出结果是: : 1.23 1.23 35.36 35.36 653.7 653.7 4358.24 4358.24#include void main( ) double values = 1.23,35.36,653.7,4358.24; for(int i=0; i4; i+) cout.width(10); cout.fill(*); cout valuesi n; 输出结果如下:输出结果如下:* * * * * * *1.231.23* * * * * *35.3635.36* * * * * *653.7653.7* * * *4358.244358.24 前一页 休息49 of 78例例11-2 使用使用setw指定宽度指定宽度#include #include void main( ) double values = 1.23,35.36,653.7,4358.24; char *names = Zoot, Jimmy, Al, Stan; for (int i=0;i4;i+) cout setw(6) namesi setw(10) valuesi endl; 输出流运行结果如下:运行结果如下: Zoot Zoot 1.231.23 Jimmy 35.36 Jimmy 35.36 Al 653.7 Al 653.7 Stan 4358.24 Stan 4358.24 前一页 休息51 of 78例例11-3 设置对齐方式设置对齐方式#include #include void main( ) double values = 1.23,35.36,653.7,4358.24; char *names = Zoot, Jimmy, Al, Stan;输出流for (int i=0;i4;i+) cout setiosflags(ios:left) setw(6) namesi resetiosflags(ios:left) setw(10) valuesi endl;输出结果如下输出结果如下: :Zoot Zoot 1.231.23Jimmy 35.36Jimmy 35.36Al 653.7Al 653.7Stan 4358.24Stan 4358.24 前一页 休息53 of 78例例11-4 控制输出精度控制输出精度#include #include void main( ) double values = 1.23,35.36,653.7,4358.24; char *names = Zoot, Jimmy, Al, Stan; cout setiosflags(ios:scientific);输出流 for (int i=0;i4;i+) cout setiosflags(ios:left) setw(6) namesi resetiosflags(ios:left) setw(10) setprecision(1) valuesi endl;该程序的输出结果如下:该程序的输出结果如下:Zoot Zoot 1 1Jimmy 4e+001Jimmy 4e+001Al 7e+002Al 7e+002Stan 4e+003Stan 4e+003 前一页 休息55 of 78进制进制dec、oct和和hex操纵符设置输入和输出操纵符设置输入和输出的缺省进制。的缺省进制。输出流 前一页 休息56 of 78输出文件流成员函数输出文件流成员函数l输出流成员函数有三种类型:输出流成员函数有三种类型: 与操纵符等价的成员函数。 执行非格式化写操作的成员函数。 其它修改流状态且不同于操纵符或插入运算符的成员函数。输出流 前一页 休息57 of 78输出文件流成员函数输出文件流成员函数lopen函数函数把流与一个特定的磁盘文件关联起来。需要指定打开模式。lput函数函数把一个字符写到输出流中。lwrite函数函数把内存中的一块内容写到一个输出文件流中lseekp和和tellp函数函数操作文件流的内部指针lclose函数函数关闭与一个输出文件流关联的磁盘文件l错误处理函数错误处理函数在写到一个流时进行错误处理输出流 前一页 休息58 of 78例例11-5 向文件输出向文件输出#include struct Date int mo,da,yr; ;void main( ) Date dt = 6,10,92; ofstream tfile(date.dat,ios:binary); tfile.write(char *) &dt,sizeof dt);输出流 前一页 休息59 of 78二进制输出文件二进制输出文件l以通常方式构造一个流,然后使用以通常方式构造一个流,然后使用setmode成员函数,在文件打开后改成员函数,在文件打开后改变模式。变模式。l使用使用ofstream构造函数中的模式参量构造函数中的模式参量指定二进制输出模式指定二进制输出模式l使用二进制操作符代替使用二进制操作符代替setmode成员成员函数:函数:ofs )l提取运算符提取运算符()对于所有标准对于所有标准C+数数据类型都是预先设计好的。据类型都是预先设计好的。l是从一个输入流对象获取字节最容易是从一个输入流对象获取字节最容易的方法。的方法。lios类中的很多操纵符都可以应用于输类中的很多操纵符都可以应用于输入流。但是只有少数几个对输入流对入流。但是只有少数几个对输入流对象具有实际影响,其中最重要的是进象具有实际影响,其中最重要的是进制操纵符制操纵符dec、oct和和hex。输入流 前一页 休息63 of 78输入流成员函数输入流成员函数lopen函数把该流与一个特定磁盘文件相关联。函数把该流与一个特定磁盘文件相关联。lget函数的功能与提取运算符(函数的功能与提取运算符()很相像,)很相像,主要的不同点是主要的不同点是get函数在读入数据时包括空函数在读入数据时包括空白字符。白字符。lgetline的功能是从输入流中读取多个字符,的功能是从输入流中读取多个字符,并且允许指定输入终止字符,读取完成后,从并且允许指定输入终止字符,读取完成后,从读取的内容中删除终止字符。读取的内容中删除终止字符。输入流 前一页 休息64 of 78例例11-6 get函数应用举例函数应用举例#include void main() char ch; while (ch=cin.get()!=EOF) cout.put(ch);输入流 前一页 休息65 of 78例例11-7 为输入流指定一个终止字符为输入流指定一个终止字符#include void main() char line100; cout Type a line terminated by t endl; cin.getline(line,100,t); cout line;输入流 前一页 休息66 of 78输入流成员函数输入流成员函数lread成员函数从一个文件读字节到一成员函数从一个文件读字节到一个指定的内存区域,由长度参数确定个指定的内存区域,由长度参数确定要读的字节数。要读的字节数。如果给出长度参数,当遇到文件结束如果给出长度参数,当遇到文件结束或者在文本模式文件中遇到文件结束或者在文本模式文件中遇到文件结束标记字符时结束读取。标记字符时结束读取。输入流 前一页 休息67 of 78例例11-8 从文件读二进制记录从文件读二进制记录#include #include #include void main( ) struct double salary; char name23; employee;输入流 ifstream is(payroll,ios:binary |ios:nocreate); if (is) is.read(char *) &employee,sizeof(employee); cout employee.name employee.salary endl; else cout ERROR: Cannot open file payroll. endl; 前一页 休息69 of 78输入流成员函数输入流成员函数lseekg函数用来设置输入文件流中读函数用来设置输入文件流中读取数据位置的指针。取数据位置的指针。ltellg函数返回当前文件读指针的位置。函数返回当前文件读指针的位置。lclose函数关闭与一个输入文件流关函数关闭与一个输入文件流关联的磁盘文件。联的磁盘文件。输入流 前一页 休息70 of 78例例11-9 设置位置指针设置位置指针#include void main( ) char ch; ifstream tfile(payroll,ios:binary | ios:nocreate); if(tfile) tfile.seekg(8);输入流 while (tfile.good( )) tfile.get(ch); if (!ch) break; cout ch; else cout ERROR: Cannot open file payroll. endl; 前一页 休息72 of 78例例11-10 读文件并显示其中空读文件并显示其中空格的位置格的位置#include void main( ) char ch; ifstream tfile(payroll,ios:binary | ios:nocreate); if (tfile) 输入流 while (tfile.good( )) streampos here = tfile.tellg( ); tfile.get(ch); if (ch= ) cout nPosition here is a space; else cout ERROR: Cannot open file payroll. endl; 前一页 休息74 of 78小结小结l第第13讲讲 流类库与输入流类库与输入/输出输出l本讲内容:本讲内容: 流类库lC+语言没有输入/输出语句,但是C+编译系统带有一个面向对象的I/O软件包,即:I/O流类库。 最重要的三个输出流类lostream、ofstream 和 ostrstream 最重要的三个输入流类listream、ifstream 和 istrstream 前一页 休息75 of 78小结(续)小结(续)l第第13讲讲 流类库与输入流类库与输入/输出输出l本讲内容:本讲内容:参见:参见:第第13讲要点讲要点 两个从iostream类派生出来的重要的I/O流类lfstream 和 strstream 前一页 休息76 of 78自修作业(不用交)自修作业(不用交)l复习第复习第11章,预习第章,预习第12章章l思考:思考: 11-1 11-6l自检作业:自检作业: 11-7 11-9l实验十一实验十一l自检作业就是:自己先做一遍,然后对照自检作业就是:自己先做一遍,然后对照C+语言程序设计(第语言程序设计(第3版)学生用书版)学生用书一书中给出的答案,找出自己学习中的薄一书中给出的答案,找出自己学习中的薄弱环节。这个作业不用交。弱环节。这个作业不用交。 前一页 休息77 of 78作业(一周之内必须交)作业(一周之内必须交)l1、第第11章书面作业章书面作业l2、第第11章编程作业章编程作业l将书面作业(将书面作业(*.doc)文件和编程作业)文件和编程作业(*.cpp)文件以附件形式通过电子邮件发)文件以附件形式通过电子邮件发给温老师。注意:在电子邮件主题上要写给温老师。注意:在电子邮件主题上要写明你的姓名和学号以及第几章的作业。明你的姓名和学号以及第几章的作业。
展开阅读全文