上机六输入输出流程序设计
一、上机目的
1.了解 C++流类库结构。
2.掌握流类库中常用的类及其成员函数的使用方法。
3.了解常用控制符的使用,掌握 C++格式输入输出方法。
4.熟练掌握文件操作方法和文件流的输入输出。
二、上机内容
1.测试本章例题。
2.设计一个学生类,将 N 个学生对象的基本信息(姓名、身高、年龄)以二进制流的形式写入文件中,并将写入的文件信息在屏幕上进行随机显示
测试例题
[例 9.9] 随机访问文件。要求:
(1)设计一个包括姓名、学号和成绩的学生结构体。
(2)先把 3 个学生数据写入文件 bbb.dat,再从文件中读出第 2 个学生的数
据显示在屏幕上。
上机步骤:
(1)新建复数类模板头文件。选择菜单“File”——“New”,打开新建对话框,
如图 5-1 所示。选择“Files”标签中的“C/C++ Header File”,设置存储路径为
“D:\mywork\work6”,文件名称为“Student”。默认选中“Add to project”,如图 6-4
所示。
(2)单击“OK”按钮,打开 Student.h 文件,编辑代码如下: //Student.h struct Student{ char name[20]; long number; int score; }; (3)在主文件中 work6.cpp 中编辑测试代码: #include "Student.h" #include <fstream.h> int main(int argc, char* argv[]) { Student stu[3] = {{"Zhang", 111, 100}, {"Li", 222, 90}, {"Wang", 333, 80}}, stu2; char filename[] = "bbb.data"; int n=3, i; fstream datafile(filename, ios::in|ios::out|ios::binary); for(i=0; i<3; i++) datafile.write((char*)&stu[i], sizeof(struct Student)); datafile.seekg(1*sizeof(struct Student), ios::beg); datafile.read((char*)&stu2, sizeof(struct Student)); datafile.close(); 64 cout<<"Name: "<<stu2.name<<endl; cout<<"Number: "<<stu2.number<<endl; cout<<"score: "<<stu2.score<<endl; return 0; }
(4)在工具栏中单击“Build”命令图标 ,生成 work6.exe。
(5)在工具栏中单击“Excute”命令图标 ,运行 work6.exe,
- 上机实践
设计一个学生类,将 N 个学生对象的基本信息(姓名、身高、年龄)以二进制流的形式写入文件中,并将写入的文件信息在屏幕上进行随机显示。
上机步骤:
(1)新建复数类模板头文件。选择菜单“File”——“New”,打开新建对话框,如图 6-6 所示。选择“Files””标签中的“C/C++ Header File”,设置存储路径为“D:\mywork\work6”,文件名称“Student2”。默认选中“Add to project”,如图 6-6所示。
图 6-6 新建学生类头文件
(2)单击“OK”按钮,打开 Student2.h 文件,编辑代码如下: //Student2.h #include <string.h> class Student{ public: char name[20]; float height; int age; Student(char *n=" ", float h=1.6, int a=20) : height(h), age(a) { strcpy(name, n); } }; (3)在主文件中 work6.cpp 中编辑测试代码: #include "stdafx.h" #include "Student2.h" #include <fstream.h> int main(int argc, char* argv[]) { int n; cout<<"please input the number of student: "; cin>>n; 66 Student *ps, stu; ps = new Student[n]; char name[20]; float height; int age; for(int i=0; i<n; i++) { cout<<endl<<"Name: "; cin>>name; cout<<"Height: "; cin>>height; cout<<"Age: "; cin>>age; *(ps+i) = Student(name, height, age); } char filename[] = "info.data"; fstream datafile(filename, ios::in|ios::out|ios::binary); for(i=0; i<n; i++) datafile.write((char*)(ps+i), sizeof(struct Student)); int num; cout<<"Please input the number to print: "; cin>>num; while(num) { datafile.seekg((num-1)*sizeof(struct Student), ios::beg); datafile.read((char*)&stu, sizeof(struct Student)); cout<<"Name: "<<stu.name<<endl; cout<<"Height: "<<stu.height<<endl; cout<<"Age: "<<stu.age<<endl; cout<<"Please input the number to print: "; cin>>num; } datafile.close(); return 0; }
(4)在工具栏中单击“Build”命令图标 ,生成 work6.exe。
(5)在工具栏中单击“Excute”命令图标 ,运行 work6.exe
思考题
1.在 C++中通过控制文件指针的移动实现文件的随机访问,一般文本文件难准确定位,所以随机访问多用于二进制文件,请测试。C++实现文件的随机访问需要考虑哪几个因素?
在 C++ 中实现文件的随机访问需要考虑以下几个因素:
- 打开文件时,需要指定正确的文件访问模式和打开方式。对于二进制文件,应该使用“二进制”模式来进行读写操作,以避免对数据的意外改变。
- 文件指针位置的移动。通过调用 fseek 函数,可以将文件指针移动到所需位置,从而实现随机访问。在移动指针时,需要注意偏移量的单位及正负方向,以确保文件指针移动到正确的位置。
- 读取或写入数据的大小和格式。对于二进制文件,由于数据类型的大小和格式可能不同,因此需要根据具体情况决定读取或写入的数据大小和格式。
- 关闭文件时,需要确保所有的文件指针都正确地指向了文件末尾,以避免数据的丢失和损坏。
下面是一个简单的示例,演示如何在C++中随机访问一个二进制文件:
#include <iostream> #include <fstream> using namespace std; int main() { // 打开二进制文件 fstream file("test.bin", ios::out | ios::binary); // 写入数据 int num1 = 12345; float num2 = 3.1415926; file.write(reinterpret_cast<char*>(&num1), sizeof(num1)); file.write(reinterpret_cast<char*>(&num2), sizeof(num2)); // 将文件指针移动到开头 file.seekg(0); // 读取数据 int num3; float num4; file.read(reinterpret_cast<char*>(&num3), sizeof(num3)); file.read(reinterpret_cast<char*>(&num4), sizeof(num4)); // 输出数据 cout << "num1 = " << num3 << endl; cout << "num2 = " << num4 << endl; // 关闭文件 file.close(); return 0; }
在上面的示例中,我们首先打开了一个名为“test.bin”的二进制文件,并向其中写入了一个整型数和一个浮点数。接着,通过调用 seekg 函数将文件指针移动到文件开头处,然后读取了这两个数据并输出。最后关闭了文件。
2.测试 seekp 函数和 seekg 函数实现文件指针重定位的区别?
在 C++ 中,文件指针有两种类型:读取指针和写入指针。为了方便操作,C++ 标准库分别提供了 seekg 和 seekp 函数来实现对这两种指针位置的重定位。
seekg 函数是用于改变当前文件读指针位置的函数,它可以让文件读指针在文件中任意一个位置定位,从而可以实现读取数据时的随机访问。而 seekp 函数则是用于改变当前文件写指针位置的函数,它可以让文件写指针在文件中任意一个位置定位,从而可以实现插入和修改数据时的随机访问。
下面是一个简单的示例,演示如何使用 seekg 和 seekp 函数实现文件指针的重定位:
#include <iostream> #include <fstream> using namespace std; int main() { // 打开文件 fstream file("test.txt", ios::out | ios::in); // 写入数据 file << "0123456789"; // 重定位读指针(从开头开始向右移动3个字符) file.seekg(3, ios::beg); // 读取一个字符 char ch; file.get(ch); cout << ch << endl; // 输出3 // 重定位写指针(从当前位置开始向右移动2个字符) file.seekp(2, ios::cur); // 插入一个字符 file.put('A'); // 重定位读指针(从开头开始向右移动2个字符) file.seekg(2, ios::beg); // 读取一个字符 file.get(ch); cout << ch << endl; // 输出0 // 关闭文件 file.close(); return 0; }
在上面的示例中,我们首先打开了一个名为“test.txt”的文件,并向其中写入了一串数字字符串。接着,通过调用 seekg 函数将文件读指针移动到该字符串的第四个字符位置处,然后读取了这个字符并输出。接下来,我们通过调用 seekp 函数将文件写指针移动到当前读指针的后两个字符位置处,然后向文件中插入了一个大写字母“A”。最后,我们再次通过调用 seekg 函数将文件读指针移动到该字符串的第三个字符位置处,然后再次读取了这个字符并输出。
可以看出,通过使用 seekg 和 seekp 函数,我们可以灵活地控制文件指针的位置,从而实现了对文件数据的灵活访问和修改。需要注意的是,两个函数的偏移量参数的计算方式以及参数的含义略有不同,请根据具体情况选择合适的参数类型和参数值。
3.补充完善[上机实践]题目内容,对 N 个学生信息,根据用户需求(按照身高、年龄)对学生信息进行排序后再显示。