【C++面向对象程序设计】CH7 输入输出流

news2025/7/4 22:54:16

目录

一、前言

二、标准输出流

1.流对象

(1)cout流对象

(2)cerr流对象

(3)【例7.1】编写程序,从键盘输入a,b,c的值求解一元二次方程。如果a=0或判别式的值<0,输出出错信息

 (4)clog流对象

2.格式输出

(1)用控制符设置输出格式

(2)【例7.2】用控制符控制输出格式

 (3)用流对象的成员函数控制输出格式

(4)用流控制成员函数输出数据

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

(1)介绍

(2)【例7.4】按相反的顺序输出“BASIC”

三、标准输入流

1.cin流

2.【例7.5】测试cin的值,判断流对象的状态

3.输入字符的流成员函数

(1)用get函数读入一个字符

(2)【例7.6】用get函数读入字符

(3)带一个参数的get函数

(4)【例7.6.2】把【例7.6】改写如下

(5)带三个参数的get函数

(6)【例7.6.3】

(7)用成员函数getline读入一行字符

(8)【例7.7】用成员函数getline读入一行字符

3.istream类其他函数

(1)eof()函数

(2)【例7.8】从键盘输入字符串,以文件结束符作为结束标志,逐个输出非空格字符

四、文件操作和文件流

1.文件的概念

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

3.文件的打开与关闭

(1)打开磁盘文件

 (2)关闭磁盘文件

4.对ASCII码文件操作

(1)【例7.11】定义一个有十个元素的整形数组,从键盘输入十个整数,将他们放入数组,同时用插入运算符将他们写入当前目录下的f1.txt文件。

(2)【例7.12】从【例7.11】建立的f1.txt文件中读取10个整数放入数组中,找出并输出最大数和它的下标值

(3)【例7.13】从键盘读入一行字符,把其中的个字母字符存放到磁盘文件f2.txt中。再从f2.txt读入数据,把其中的小写字母改写为大写字母并存入磁盘文件f3.txt。

5.对二进制文件操作

(1)介绍

(2)【例7.14】把一批数据以二进制形式写入磁盘文件

(3)【例7.15】从【例7.14】产生的文件中读数据并显示到屏幕上

(4)与文件指针有关的流成员函数

(5)随机访问二进制数据文件

五、字符串流

1.建立写字符串流对象

2.建立读取字符串流对象 

3.【例7.17】

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;
}


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/56229.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

拾壹博客拆解改造,页面元素替换(二)

页面元素替换 首先要做的当然是换成自己风格的站名和内容啦。 1、网站配置 跟踪前端代码后发现配置是来自后端接口&#xff0c;想着既然入库了&#xff0c;那应该有对应的管理页面吧&#xff0c;果然找到了&#xff0c;就是…演示账号不允许操作&#xff01;那么接下来要干的…

stm32f767的fft

仅作自己笔记用 1&#xff0c;FFT函数调用基础知识 采样得到的数字信号&#xff0c;就可以做FFT变换了。N个采样点&#xff0c;经过FFT之后&#xff0c;就可以得到N个点的FFT结果。为了方便进行FFT运算&#xff0c;通常N取2的整数次方。 假设采样频率为Fs&#xff0c;信号频率…

基于Java环境下的高校跳蚤市场商城系统

目 录 摘 要 I Abstract II 1绪论 1 1.1 课题背景 1 1.2 目的和意义 1 1.3 研究现状 2 1.4 研究主要内容 3 2开发平台与技术的介绍 4 2.1 Eclipse简介 4 2.2 Java EE简介 4 2.2.1 Java EE概念 4 2.2.2 Java EE运行模式 4 2.3 Jsp技术简介 5 2.4 Struts 2框架简介 5 2.5 MySQL简…

[附源码]计算机毕业设计springboot新冠疫苗接种预约系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

Docker最新超详细教程——Docker创建运行Redis并挂载

Docker最新超详细教程——Docker创建运行Redis并挂载 Docker官网关于Redis的描述 redis - Official Image | Docker Hubhttps://hub.docker.com/_/redis 一、拉取Redis镜像 docker pull <镜像名称>:<版本号> docker pull redis:6.2.27 首先我们要在Docker上获取…

2023最新SSM计算机毕业设计选题大全(附源码+LW)之java高校教学过程管理系统34085

现在毕设刚开始。时间还有很多&#xff0c;可以从头开始学也可以。毕设其实不难&#xff0c;难的是我们懒散到这种时候再去静下心学。能自己独立完成尽量自己独立完成。相信你看过很多上面回答的&#xff0c;都不建议去某宝。毕竟这一行参差不齐哈。能找到靠谱的也不容易。近期…

Unity Debug的简单封装

对Unity Debug的简单封装 使用前提&#xff1a; Project Settings-Player-Other Settings-Script Define Symbols添加 EnableLog&#xff0c;点击Apply 测试代码&#xff1a; using MTools.Debuger; using UnityEngine;public class NewBehaviourScript : MonoBehaviour {p…

基于PHP+MySQL家庭医生签约预约诊疗管理信息系统

随着时代的发展,人们对医疗方面的要求也越来越高,也是人们更希望通过家庭医生来对自己提供所需的医疗服务,从而享受更加个性化的医疗服务,为此我们开发了本家庭医生签约预约诊疗管理信息系统,通过本系统患者可以享有签约,预约,和诊疗等一系类的服务。 本系统是一个家庭医生签约…

[附源码]Python计算机毕业设计Django基于微信小程序的网络办公系统

项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等等。 环境需要 1.运行环境&#xff1a;最好是python3.7.7&#xff0c;…

qmake 参数

E:\workspace\QtWork\qmake\option.cpp:Option::init() -project 设置qmake生成工程相关文件&#xff0c;如果用qt creator开发的话这个命令参数基本用不到。 -prl 设置qmake生成prl文件。 -set 设置自定义属性&#xff0c;会存放到注册表中。具体参考属性 -unset 取消自定义…

网页JS自动化脚本(六)在特定位置添加元素

在某元素后插入元素 我们这一次在按钮元素后面复制一个一模一样的按钮,所以分为几个步骤,先新建一个一样的元素,然后把相同中的属性赋值给它,再插入到合适的位置,最后再稍微修改一下外观样式即可 首先新建一个input元素,看一下效果 window.onloadfunction(){var theElementdo…

[附源码]Python计算机毕业设计Django基于人脸识别的社区防疫管理系统

项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等等。 环境需要 1.运行环境&#xff1a;最好是python3.7.7&#xff0c;…

Pytest自动化测试框架---(单元测试框架)

unittest是python自带的单元测试框架&#xff0c;它封装好了一些校验返回的结果方法和一些用例执行前的初始化操作&#xff0c;使得单元测试易于开展&#xff0c;因为它的易用性&#xff0c;很多同学也拿它来做功能测试和接口测试&#xff0c;只需简单开发一些功能&#xff08;…

阿里云新用户活动:云服务器ECS 新购、升级报价出炉了!

阿里云新人特惠&#xff0c;阿里云新用户新购升级立享满减&#xff0c;新购升级云服务器ECS &#xff0c;购买热门产品 s6/u1/c6/g6/r6/c7/g7/r7指定配置&#xff0c;可享折上折&#xff01;从未购买过云服务器ECS或者轻量应用服务器的用户一次性可领取3张优惠券。优惠券适用于…

深入浅出Seata的AT模式

单个掉队&#xff0c;导致集体被动摆烂&#xff1b; 一、业务背景 在分布式架构中&#xff0c;事务管理是个无法避开的复杂问题&#xff0c;虽然有多种解决方案&#xff0c;但是需要根据业务去选择合适的&#xff1b; 从个人最近几年的实践经验来看&#xff0c;Seata组件的AT…

【JUC】SpringBoot使用线程池的两种方式 注解和注入

学习笔记一、ThreadPoolTaskExecutor与ThreadPoolExecutor的区别二、编写配置文件ThreadPoolConfig二、编写Controller三、编写Service3.1、注解3.1、注入一、ThreadPoolTaskExecutor与ThreadPoolExecutor的区别 ThreadPoolExecutor 是JDK自1.5添加的线程池。 ThreadPoolTaskE…

排序算法:插入排序,选择排序,冒泡排序

插入排序 一般来说&#xff0c;插入排序都采用in-place在数组上实现。具体算法描述如下&#xff1a; 步骤1: 从第一个元素开始&#xff0c;该元素可以认为已经被排序&#xff1b; 步骤2: 取出下一个元素&#xff0c;在已经排序的元素序列中从后向前扫描&#xff1b; 步骤3: 如…

[附源码]计算机毕业设计-中国传统手工艺销售平台Springboot程序

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

[附源码]计算机毕业设计JAVA校园失物招领平台

[附源码]计算机毕业设计JAVA校园失物招领平台 项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybati…

李峋同款会动的爱心Python代码版

最近看到不少关于李峋同款爱心的视频、文章&#xff0c;今天我们也分享一下李峋同款爱心 Python 代码版。要问李峋是谁&#xff1f;我也不太清楚&#xff0c;大家可自行百度&#xff0c;这个是我百度的结果&#xff0c;仅供参考。 简单来说李峋同款爱心就是一个动态的♥型效果&…