目录
(3)【例7.1】编写程序,从键盘输入a,b,c的值求解一元二次方程。如果a=0或判别式的值<0,输出出错信息
(2)【例7.8】从键盘输入字符串,以文件结束符作为结束标志,逐个输出非空格字符
(1)【例7.11】定义一个有十个元素的整形数组,从键盘输入十个整数,将他们放入数组,同时用插入运算符将他们写入当前目录下的f1.txt文件。
(2)【例7.12】从【例7.11】建立的f1.txt文件中读取10个整数放入数组中,找出并输出最大数和它的下标值
(3)【例7.13】从键盘读入一行字符,把其中的个字母字符存放到磁盘文件f2.txt中。再从f2.txt读入数据,把其中的小写字母改写为大写字母并存入磁盘文件f3.txt。
(3)【例7.15】从【例7.14】产生的文件中读数据并显示到屏幕上
4.【例7.18】在一个字符数组c中存放10个整数,以空格为分隔符,要求将它们放到整形数组中排升序,然后再写入原来的字符数组中。
一、前言
在C++中,输入输出是通过流完成的。C++的输出操作将一个对象的状态转化成一个字符序列,输出到某个地方。输入操作则是从某个地方接收一个字符序列,然后将其转换车一个对象的状态所要求的格式。
把接收存放输出数据的地方叫做目标,把输入数据来自的地方叫做源,输入和输出操作可以看成字符序列在源、目标和对象之间的流动。C++把与输入和输出有关的操作定义为一个类体系,放在一个系统库里,供用户调用。
这个执行输入和输出操作的类体系叫做流类,提供流类实现的系统叫做流类库。
此图是简化的流类库的基本类等级图,而不是直接的继承关系图。其实它们都是模板类,箭头表示的是类等级关系。
这个等级关系在头文件iostream.h中说明。在图中,ios类中一个指针成员指向streambuf类的对象。Streambuf类管理流的缓冲区。由于数据隐蔽和封装的需要,普通用户只使用ios、istream和ostream类提供的公有接口,完成流的提取和插入操作。ios类是istream类和ostream类的虚基类,提供对流的格式化I/O操作和错误处理的成员处理的成员函数。从ios类共有派生istream类和ostream类分别提供对流进行提取和插入操作的成员函数,而iostream类通过组合istream类和ostream类支持对一个流进行双向操作,他并没有提供新成员函数。
iostream中预定义四个流对象,它们分别是cin、cout、cerr、clog。事实上可以将cin视为istream的一个对象,而cout视为ostream的一个对象。流是一个抽象的概念,当实际进行I/O操作时,必须将流和一个具体的物理设备连接起来。
C++的流类库预定义的四个流所连接的设备如表所示:
与iostream类库有关的头文件:
iostream类库中不同的类的声明被放在不同的头文件中,用户在程序中用#include命令包含所需的头文件就相当于在程序中声明了所需的类。
iostream 输入输出流操作
fstream 管理文件的I/O操作
strstream 字符流的I/O操作
stdiostream 混合使用C和C++
iomanip 使用格式化I/O操作
在iostream头文件中重载了>>和<<运算符。用于标准类型数据的输入和输出。
二、标准输出流
1.流对象
标准输出流是流向标准输出设备的数据。
ostream类定义了cout、cerr和clog三个流对象。
(1)cout流对象
cout流在内存开辟一个缓冲区存放流中的数据,当遇到endl时,立即输出流中的所有数据,然后插入一个换行符并清空缓冲区。
(2)cerr流对象
cerr流对象是标准出错流。它向标准出错设备输出有关出错的信息。
(3)【例7.1】编写程序,从键盘输入a,b,c的值求解一元二次方程。如果a=0或判别式的值<0,输出出错信息
-
NS流程图
-
代码
#include <iostream>
#include <math.h>
using namespace std;
int main()
{
float a, b, c, disc;
cout << "请输入 a,b,c:";
cin >> a >> b >> c;
if (a == 0)
cerr << "a 等于0,错误!" << endl;
else if ((disc = b * b - 4 * a * c) < 0)
cerr << "判别式b*b-4*a*c<0" << endl;
else
{
cout << "x1=" << (-b + sqrt(disc)) / (2 * a) << endl;
cout << "x2=" << (-b - sqrt(disc)) / (2 * a) << endl;
}
return 0;
}
-
结果
(4)clog流对象
clog流对象也是标准出错流,它与cerr的区别是,cerr不经过缓冲区直接向显示器输出出错信息,clog把出错信息存放在缓冲区,当缓冲区满或遇到endl时向显示器输出出错的信息。
2.格式输出
在输出数据时,如不指定格式,则采用系统给定的默认格式。可以通过控制符或流的成员函数设置输出格式。
(1)用控制符设置输出格式
下表列出了输出格式的控制符。这些控制符在头文件iomanip中定义。
(2)【例7.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;
}
- 结果
(3)用流对象的成员函数控制输出格式
用于控制输出格式的常用成员函数如下。
流成员函数setf和控制符setiosflags括号中参数是格式标志,在类ios中定义它是枚举值。所以在引用这些格式标志时要以ios::开始,格式标志列于表7.5。
(4)用流控制成员函数输出数据
#include <iostream>
using namespace std;
int main()
{
int a = 21;
cout.setf(ios::showbase);
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.precision(6);
cout << pi << endl;
return 0;
}
前面的【例7.2】和【例7.3】分别用控制符和流成员函数设置输出流中的数据基数,虽然它们的功能相似,但是还是有区别的:
- 用控制符设置输出流的数据基数后,这个设置会一直保留到下一次的设置
- 用成员函数srtf()设置的格式,必须用函数unsetf()终止后才能重新设置,并且函数setf()设置的基数仅仅在本次输出流中生效,之后无论是否用函数unsetf()终止,下次输出流数据又以默认的十进制基数显示
3.用流成员函数put输出字符
(1)介绍
格式:
cout.put(字符/数字)[.put(…) ……]
如果是字符,直接输出该字符;如果是数字,可以用八进制、十进制或十六进制表示整数,用该数字对256取模,输出对应的ASCII码字符。
(2)【例7.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;
}
三、标准输入流
1.cin流
cin是istream类的对象,从标准输入设备读取数据。利用提取运算符>>在流中提取数据时通常跳过流中的空格、tab键、换行符等字符。只有输入回车键时输入的数据才进入键盘缓冲区,形成输入流,提取运算符才能从其中提取数据。
当遇到无效字符(与变量数据类型不一致)或文件结束符时,输入流cin就处于出错状态,此时对cin流的所有操作都被终止。当输入流出错时,cin的值是false,所以可以根据cin的值判断流对象是否处于正常状态。
2.【例7.5】测试cin的值,判断流对象的状态
#include <iostream>
using namespace std;
int main()
{
float grade;
cout << "enter grade:";
while (cin >> grade)
{
if (grade >= 85)
cout << grade << " GOOD!" << endl;
if (grade < 60)
cout << grade << " fail!" << endl;
cout << "enter grade:";
}
cout << "The end." << endl;
return 0;
}
3.输入字符的流成员函数
(1)用get函数读入一个字符
格式:cin.get()
函数的类型是字符,函数的功能是从输入流中提去一个字符作为函数值返回。如在流中遇到文件结束符EOF时,返回-1。
(2)【例7.6】用get函数读入字符
#include <iostream>
using namespace std;
int main()
{
char c;
cout << "enter a sentence:" << endl;
while ((c = cin.get()) != EOF)
cout.put(c);
return 0;
}
(3)带一个参数的get函数
格式:cin.get(字符变量)
功能:从输入流中提取一个字符赋予字符变量。如遇到文件结束符就结束提取。输入回车后再输入文件结束符。
(4)【例7.6.2】把【例7.6】改写如下
#include <iostream>
using namespace std;
int main()
{
char c;
cout << "enter a sentence:" << endl;
while (cin.get(c))
{
cout.put(c);
}
cout << "end" << endl;
return 0;
}
(5)带三个参数的get函数
格式:cin.get(字符指针,n,终止字符)
n与提取的字符个数相关。函数从键盘缓冲区最多顺序提起n-1个字符,顺序放入字符指针所指的字符数组。如果在提取过程中遇到终止字符,无论是否满足指定的字符个数都要终止提取。
(6)【例7.6.3】
#include <iostream>
using namespace std;
int main()
{
char ch[20];
cout << "enter a sentence:" << endl;
cin.get(ch, 10, '\n');
cout << ch << endl;
return 0;
}
cin.get()中不带参数和只带一个参数的函数,都是以文件结束符作为终止提取的控制符。如提取一个字符结束时会把指针移到下一个字符。
cin.get()中带三个参数的函数,以字符个数或指定终止提取字符为终止提取的控制符。如提取字符结束不会把指针移到下一个字符。
cin.get()函数族不忽略提取的空白字符。
(7)用成员函数getline读入一行字符
格式:cin.getline(字符指针,n,终止字符)
函数功能与带三个参数的get函数类似。
带三个参数的cin.get和cin.getline相同的是它们都不忽略提取过程中遇到的空白字符,当遇到终止字符时就停止提取。
带三个参数的cin.get和cin.getline不同的是停止提取时,cin.getline会把指针移到终止字符后相邻的字节,而带三个参数的cin.get函数不会。
#include <iostream>
using namespace std;
int main(int argc, char *argv[])
{
char ch[20];
char c1;
cout << "输入一句话:" << endl;
cin >> ch;
cout << "第一次 cin 提取的字符串是:" << ch << endl;
c1 = cin.get();
cout << "第二次 cin.get() 提取的字符串是:" << c1 << endl;
cin.get(c1);
cout << "第三次 cin.get(c1) 提取的字符串是:" << c1 << endl;
cin.get( ch, 20, '/');
cout << "第四次 cin.get( ch, 20, '/') 提取的字符串是:" << ch << endl;
cin.getline(ch, 20, '/');
cout << "第五次 cin.getline (ch,20,'/')提取的字符串是:" << ch << endl;
cin.getline(ch, 20, '/');
cout << "第六次 cin.getline (ch,20,'/')提取的字符串是:" << ch << endl;
return 0;
}
cin和cin.getline都具有从键盘缓冲区按指针所指提取字符串的功能。它们有以下区别:
- cin忽略起始的空白字符;而cin.getline不忽略起始的空白字符
- cin当提取到非空白字符后,遇到空白字符时就终止提取,指针就停留在空白字符处;而cin.getline是提取到规定的终止字符或规定的字符个数后终止提取,指针停留在提取的最后一个字符后面相邻的字节
- 通过对>>的重载,cin可以提取其他类型的数据;而cin.getline只能输入字符串
(8)【例7.7】用成员函数getline读入一行字符
#include <iostream>
using namespace std;
int main()
{
char ch[20];
cout << "输入一句话:" << endl;
cin >> ch;
cout << "第一次 cin 提取的字符串是:" << ch << endl;
cin.getline(ch, 20, '/');
cout << "第二次 cin.getline 提取的字符串是:" << ch << endl;
cin.getline(ch, 20);
cout << "第三次 cin.getline 提取的字符串是:" << ch << endl;
return 0;
}
#include <iostream>
using namespace std;
int main()
{
char ch[20];
cout << "输入一句话:" << endl;
cin >> ch;
cout << "第一次 cin 提取的字符串是:" << ch << endl;
cin.get( ch, 20, '/');
cout << "第二次 cin.get 提取的字符串是:" << ch << endl;
cin.getline(ch, 20);
cout << "第三次 cin.getline 提取的字符串是:" << ch << endl;
return 0;
}
3.istream类其他函数
(1)eof()函数
当输入缓冲区的指针遇到文件结束符时函数值为真,否则为假。从键盘用ctrl+z输入文件结束符。
(2)【例7.8】从键盘输入字符串,以文件结束符作为结束标志,逐个输出非空格字符
#include <iostream>
using namespace std;
int main()
{
char c;
while (!cin.eof())
if ((c = cin.get()) != ' ')
//cout.put(c);
cout << c ;
return 0;
}
四、文件操作和文件流
1.文件的概念
文件是指存储在存储介质上的数据集合。操作系统把存储介质上的相关数据抽象为文件,用标识符为其取名并由文件系统管理文件。只要用户指出文件名,操作系统就可以按名存取文件信息。
根据文件中数据的表现形式,文件分为ASCII文件和二进制文件。ASCII文件就是文本文件,每个字节表示一个字符。二进制文件是把内存中的数据、指令按其在内存的格式存放在磁盘上。
字符信息在内存也是以ASCII码形式存放,所以字符在ASCII码文件和在二进制文件中形式是一样的。对于数值数据,两者是不一样的。
例如,一个十进制长整数100000,用二进制表示时用四个字节;而用ASCII表示时用六个字节。
2.文件流类与文件流对象
文件流是以外存文件为输入输出对象的数据流。输出文件流是从内存流向外存文件的数据流,输入文件流是从外存文件流向内存的数据流。为了弥补访问内存和访问外村的速度差,每个文件流都有一个内存缓冲区。
在C++的I/O类库里定义了几种文件类,专门用于文件的输入和输出操作。
从图中可以看到C++从标准输入、输出流类派生出三个文件流类。
ifstream类,支持从磁盘文件输入。
ofstream类,支持向磁盘文件输出。
fstream类,支持对磁盘文件输入和输出。
要对文件进行输入输出,必须定义一个文件流类对象,用对象调用类的成员函数对文件操作。
3.文件的打开与关闭
(1)打开磁盘文件
打开文件是指在读写文件前做必要的准备工作,包括:
- 在文件流对象和磁盘文件之间建立关联
- 指定文件的格式和操作方式
打开文件有两种方法
1)建立文件流对象,用对象调用类成员函数open
ofstream outfile;
outfile.open( “f1.txt”, ios::out);
调用成员函数的一般形式为:
文件流对象.open(文件名,输入输出方式);
文件名可以包括路径,如省略路径,默认文件在当前目录(工程文件目录)。
输入输出方式在ios类中定义,它们是枚举常量,有多种选择。表7.6列出了文件输入输出方式设置值。
2)在定义文件流对象时指定参数
文件流类 对象(文件名,输入输出方式);
例:
ofstream outfile ( “f1.txt”, ios::out);
打开文件操作可能成功也可能失败,可以测试文件流对象判定。文件流对象是真,表示成功;否则表示失败。
(2)关闭磁盘文件
文件使用结束,必须关闭文件,用文件流对象调用关闭文件成员函数实现。
格式:文件流对象.close();
功能:解除文件流对象与磁盘文件的关联
4.对ASCII码文件操作
ASCII码文件也是文本文件,文件中一个字节存放一个字符。对ASCII码文件操作包括向文件写入字符和从文件读取字符。
读写ASCII码文件有用文件流对象与提取、插入运算符和用文件流对象调用类的成员函数put,get,getline两种方法。
(1)【例7.11】定义一个有十个元素的整形数组,从键盘输入十个整数,将他们放入数组,同时用插入运算符将他们写入当前目录下的f1.txt文件。
#include <iostream>
using namespace std;
int main()
{
int a[10];
ofstream outfile("D:\个人成长\学业\课程\c++\f1.txt");
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] << " ";
}
outfile.close();
return 0;
}
程序中用文件流类ofstream,它是在头文件fstream中定义的,用vc6.0时要把这个头文件包含进来。
建立输出流对象默认就是向文件输出,所以对文件的操作方式可以省略。
对文本文件写数值数据时,两个数据之间要用空格或换行符隔开,便于读文件。
(2)【例7.12】从【例7.11】建立的f1.txt文件中读取10个整数放入数组中,找出并输出最大数和它的下标值
对程序分析从顶到下,逐步细化。这是结构化程序设计的基本功。前面分析中先设计出一个大框架,然后再把不能用语句表示的功能细化成能用语句组合表示的功能。
#include <iostream>
using namespace std;
int main()
{
int a[10], max, i, order;
ifstream infile("f1.txt", ios::in);
if (!infile)
{
cerr << "open error!" << endl;
exit(1);
}
for (i = 0; i < 10; i++)
{
infile >> a[i];
cout << a[i] << " ";
}
cout << endl;
infile.close();
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;
return 0;
}
(3)【例7.13】从键盘读入一行字符,把其中的个字母字符存放到磁盘文件f2.txt中。再从f2.txt读入数据,把其中的小写字母改写为大写字母并存入磁盘文件f3.txt。
分析:程序中使用两个文件,其中f2先做输出文件(写入字母),再做输入文件(读取字母),f3做输出文件(写入大写字母)
#include <iostream>
using namespace std;
void save_to_file()
{ // 写文件
ofstream outfile("f2.txt");
if (!outfile)
{
cerr << "open f2.txt error!" << endl;
exit(1);
}
char c[80];
cin.getline(c, 80);
for (int i = 0; c[i] != 0; i++)
if ( c[i] >= 65 && c[i] <= 90 || c[i] >= 97 && c[i] <= 122)
{
outfile << (c[i]);
cout << c[i];
}
cout << endl;
outfile.close();
}
void get_from_file()
{
char ch;
ifstream infile("f2.txt", ios::in);
if (!infile)
{
cerr << "open f2.txt error!" << endl;
exit(1);
}
ofstream outfile("f3.txt");
if (!outfile)
{
cerr << "open f3.txt error!" << endl;
exit(1);
}
while (infile.get(ch))
{
if (ch >= 97 && ch <= 122)
ch = ch - 32;
outfile << ch;
cout << ch;
}
cout << endl;
infile.close();
outfile.close();
}
int main()
{
save_to_file();
get_from_file();
return 0;
}
#include <iostream>
//专门设计的读文件程序
#include <fstream>
using namespace std;
void display_file(char *filename)
{
ifstream infile(filename, ios::in);
if (!infile)
{
cerr << "open error!" << endl;
exit(1);
}
char ch;
while (infile.get(ch))
cout << (ch);
cout << endl;
infile.close();
}
int main()
{
display_file("f3.txt");
return 0;
}
5.对二进制文件操作
(1)介绍
二进制文件是按内存中的数据存储形式写入磁盘文件,因此又称为内存数据的映象文件。
对二进制文件操作与对文本文件操作相似的是先定义文件流对象,然后打开文件,使用完要关闭文件。在打开时必须指定文件的存储形式是二进制形式,二进制文件既可以作为输入文件也可以作为输出文件,还可以作为既能输入又能输出的文件。这是与ASCII文件不同的地方。
分别用成员函数read和write读写文件。
读二进制文件用istream类read成员函数;写二进制文件用ostream类write成员函数。它们的函数原型分别是:
istream&read(char * bu, int len);
ostream&write( const char * bu, int len);
字符指针bu指向内存要读或写的数据起始位置。len是一次要读写的数据字节个数(数据长度)。调用格式:
输入文件流对象.read( 内存指针, 长度);
输出文件流对象.write( 内存指针, 长度);
(2)【例7.14】把一批数据以二进制形式写入磁盘文件
#include <iostream>
#include <fstream>
using namespace std;
struct student
{
char name[20];
int num;
int age;
char sex;
};
int 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();
}
outfile.write( (char *)&stud, sizeof(stud));
outfile.close();
return 0;
}
(3)【例7.15】从【例7.14】产生的文件中读数据并显示到屏幕上
【分析】从文件读取数据必须先放入内存,所以必须设置一个与文件数据格式相同的数据结构即机结构数组,然后再将结构数组元素逐个输出
#include <iostream>
#include <fstream>
using namespace std;
struct student
{
char name[20];
int num;
int age;
char sex;
};
int main()
{
student stud[3];
int i;
ifstream infile("stud.dat", ios::binary);
if (!infile)
{
cerr << "open error!" << endl;
abort();
}
infile.read((char *)stud, sizeof(stud));
infile.close();
for (i = 0; i < 3; i++)
{
cout << "NO." << i + 1 << endl;
cout << "姓名:" << stud[i].name << endl;
cout << "学号:" << stud[i].num << endl;
cout << "年龄:" << stud[i].age << endl;
cout << "性别:" << stud[i].sex << endl;
}
return 0;
}
(4)与文件指针有关的流成员函数
为了随机读取二进制文件中数据,磁盘文件用一个指针表示当前要访问的位置。每次读或写文件后会自动修改指针。使指针总是指向当前要访问的位置。对于二进制文件,允许程序控制指针移动,实现随机访问文件。文件流提供了有关文件指针的成员函数。表7.7列出这些函数。
这些函数名头或尾字母不是g就是p。带g的用于输入,带p的用于输出。对于输入输出文件不区分g和p。
函数参数文件中的位置和位移量以字节为单位,是长整型。参照位置表示以什么作为移动起点。ios类定义为:
- ios::beg 以文件开始为起点,这是默认值
- ios::cur 以指针当前位置为起点
- ios::end 以文件结尾为起点
例:
infile.seekg( 100 );
infile.seekg( -50,ios::cur);
outfile.seekp( -75,ios::end);
(5)随机访问二进制数据文件
利用流类的成员函数移动文件指针,实现随机访问文件中任何一个字节里的数据。
例,有五个学生的数据,要求:
- 把它们写入磁盘文件
- 从磁盘文件读第1,3,5学生数据并显示
- 从磁盘文件读入修改过的5个学生数据并显示
#include <iostream>
using namespace std;
struct student
{ int num;
char name[20];
float score;
};
int 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++)
iofile.write((char *)&stud[i],sizeof(stud[i]));
student stud1[5];
for(i=0;i<5;i=i+2)
{
iofile.seekg(i*sizeof(stud[i]),ios::beg);
iofile.read((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;
iofile.seekp(2*sizeof(stud[0]),ios::beg);
iofile.write((char *)&stud[2],sizeof(stud[2]));
iofile.seekg(0,ios::beg);
for(i=0;i<5;i++)
{
iofile.read((char *)&stud[i],sizeof(stud[i]));
cout<<stud[i].num<<" "<<stud[i].name<<" "<<stud[i].score<<endl;
}
iofile.close();
return 0;
}
五、字符串流
字符串流以内存中用户定义的字符数组(字符串)为输入输出对象,即将数据写入内存数组,或从内存字符数组读取数据。
字符串流也需要缓冲区,读取或写入时,流缓冲区中的数据不断增加,待缓冲区满或遇到换行符时,缓冲区中数据一起写入字符数组或赋予指定变量。
1.建立写字符串流对象
ostrstream类的构造函数原型是:
ostrstream::ostrstream( char *bu, int n, int mode =ios::out);
bu是指向字符数组首址的指针,n是指定流缓冲区的长度,第三个参数可忽略,默认是ios::out。
例:
ostrstream strout( ch1,20);
建立字符流对象strout,并与字符数组ch1关联(通过字符串流把数据写入字符数组ch1),流缓冲区长度是20个字节。
2.建立读取字符串流对象
istrstream::istrstream( char *bu, int n);
istrstream::istrstream( char *bu);
bu是指向字符数组首址的指针,n是流缓冲区的长度,如没有n,表示缓冲区的长度与字符串数组长度相同。例
istrstream strin( ch2);
istrstream strin( ch2, 20);
第一条语句是建立读取字符串流对象strin,将字符数组ch2所有数据作为读取字符串流的内容。
第二条语句是建立读取字符串流对象strin,将字符数组ch2前20个字符作为读取字符串流的内容。
3.【例7.17】
#include <strstream>
#include <iostream>
using namespace std;
struct student
{
int num;
char name[20];
float score;
};
int main()
{
student stud[3] = {1001, "Li", 78, 1002, "Wang", 89.5, 1004, "Fun", 90 };
char c[50];
ostrstream strout(c, 30);
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;
return 0;
}
4.【例7.18】在一个字符数组c中存放10个整数,以空格为分隔符,要求将它们放到整形数组中排升序,然后再写入原来的字符数组中。
#include <strstream>
#include <iostream>
using namespace std;
int 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, sizeof(c));
for (i = 0; i < 10; i++)
strout << a[i] << " ";
strout << ends;
cout << "array c:" << c << endl;
return 0;
}