实验八 流类库与输入输出
一、实验目的
1.掌握流类库中常用的类及其成员函数的使用方法,掌握C++格式输入输出的方法,学习文本文件和二进制文件的输入输出方法。
2.正确理解C++的异常处理机制,学习异常处理的声明和执行过程。
二、实验内容
1.编写程序lx1.cpp实现求取1-100之间的质数,通过文件输出流对象将结果保存在文件data1.txt中。(20分)
2.编写程序lx2.cpp,其中定义函数void yanghuiTriangle(int n)实现图所示杨辉三角形输出。 在主函数中输出n=8的杨辉三角形,并利用输入流读取本程序,将代码在屏幕逐行输出。(30分)
1
1 1
1 2 1
1 3 3 1
3.编写函数sort(int a[],int n)对整形数组a[10] = {19, 32, 45, 51, 71, 23, 38, 11, 17, 8}升序排序,并将排序结果写入磁盘文件f3.dat中。(25分)
4.处理除数为0的异常,用try/catch语句来捕获异常,并使用throw语句来抛出异常,从而实现异常处理。(20分)
三、实验步骤及结果
题目1:
解题思路:
1.写一个判断一个数是否是素数的函数,然后通过循环来调用,选出1-100之间的素数,再逐一赋给数组
2.创建输出流对象,然后利用循环将数组存入文件中
程序代码:
/*
程序名:lx1.cpp
功能:编写程序lx1.cpp实现求取1-100之间的质数,通过文件输出流对象将结果保存在文件data1.txt中。(20分)
日期:2021.12.4
版本:1.0
*/
#include <iostream>
#include <fstream>
using namespace std;
int isPrime(int n)//判断一个数是否是素数
{
int i;
if(n<=1) return 0;
if(n==2) return 1;
for(i=2;i<n;i++)
{
if(n%i==0) return 0;
}
return 1;
}
int main()
{
int b[30];
static int j=0;
for(int i=0;i<100;i++)//输出1-100之间的素数
{
if(isPrime(i)==1)
{
b[j]=i;
j++;
cout << i << endl;
}
}
ofstream ofs("data1.txt",ios::out);//创建输出流对象,把该流与"data1.txt"相关联。
//判断文件是否能打开
if(!ofs)
{
cout<<"open 'data1.txt' error !"<<endl;
exit(0);
}
cout<<"open 'data.txt' successfully !"<<endl;
for (int i = 0; i < j; i++)//利用循环将数组存入文件中
{
ofs << b[i] << endl;
}
ofs.close();//关闭流
cout << "run end !" << endl;
system("pause");
return 0;
}
运行结果截图:
题目2:
解题思路:
1.杨辉三角:
利用数组和循环构建杨辉三角;a[i][j] = a[i - 1][j - 1] + a[i - 1][j]
2.读取:通过read函数将文件中的数据按照一定的长度读取出来并且存放在新的数组中。
函数原型istream& read(char* s, streamsize n); 用来暂存内容的数组(必须是char*型),以及流的长度
先通过文件流将流与txt文件绑定,然后获取文件长度
然后读取文件,将流中的内容读取到容器中
注意,读取时必须标识读入的位置,一般从第一个位置开始读入,即vec[0] 或者string[0]
程序代码:
/*
程序名:题目2.cpp
功能:.编写程序lx2.cpp,其中定义函数void yanghuiTriangle(int n)实现图所示杨辉三角形输出。
在主函数中输出n=8的杨辉三角形,并利用输入流读取本程序,将代码在屏幕逐行输出。(30分)
1
1 1
1 2 1
1 3 3 1
作者:宋抗非
日期:2021.12.4
版本:1.0
*/
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
using namespace std;
void yanghuiTriangle(int n)//杨辉三角形输出函数
{
static int a[10][10];
a[0][1] = 1;
for (int i = 1; i < n; i++)
{
for (int j = 1; j < i + 2; j++)
{
a[i][j] = a[i - 1][j - 1] + a[i - 1][j];//杨辉三角规律:一个数等于上面两个数之和
}
}
for (int i = 0; i < n; i++)//输出杨辉三角
{
for (int j = 1; j < i + 2; j++)
{
cout << a[i][j] << " ";
}
cout << endl;
}
}
//将流中的内容读取到容器中
template<typename T>
std::vector<T> ReadArray(std::ifstream &ifs, int size) //size标识vector的大小
{
std::vector<T> v(size, 0);
ifs.read((char*)(&v[0]), sizeof(T)*size);
return v;
}
int main()
{
yanghuiTriangle(8);
ifstream ifs("C:\\Users\\Lenovo\\Desktop\\实验报告\\宋抗非实验报告9\\lx2.cpp");//创建输入流对象,把该流与"lx2.cpp"相关联。
//获取文件的大小
ifs.seekg(0, ifs.end); //追溯到流的尾部
int length = ifs.tellg(); //获取流的长度
ifs.seekg(0, ifs.beg); //回到流的头部
//读取文件
char* temp = new char[length]; //用来暂存内容的数组
memset(temp, 0, length);//堆中内存初始化,否则会出现"屯屯屯屯屯屯屯"
if (ifs.is_open())
{
cout << "Now reading..." << endl;
ifs.read(temp, length); //read函数
}
for (int i = 0; i < length; ++i)
{
cout << temp[i] ;
}
cout << endl;
ifs.seekg(0, ifs.beg); //回溯到流头部
vector<char> textVec;
textVec = ReadArray<char>(ifs, length); //读取成功
ifs.close(); //关闭流
system("pause");
return 0;
}
运行结果截图:
题目3:
解题思路:
1.编写冒泡排序对数组进行升序排序
2.创建输出流对象,利用循环将数组存入文件中
程序代码:
/*
程序名:题目3.cpp
功能:编写函数sort(int a[],int n)对整形数组a[10] = {19, 32, 45, 51, 71, 23, 38, 11, 17, 8}升序排序,并将排序结果写入磁盘文件f3.dat中。(25分)
日期:2021.12.4
版本:1.0
*/
#include <iostream>
#include <fstream>
using namespace std;
void sort(int a[], int n)//冒泡排序
{
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n - 1 - i; j++)
{
if (a[j] > a[j + 1])
{
int swap = a[j];
a[j] = a[j + 1];
a[j + 1] = swap;
}
}
}
}
int main()
{
int a[10] = { 19, 32, 45, 51, 71, 23, 38, 11, 17, 8 };//定义整形数组
sort(a, 10);//对数组进行排序
for (int i = 0; i < 10; i++)//输出排序后的数组
{
cout << a[i] << " ";
}
cout << endl;
ofstream ofs("f3.dat");//定义输出流对象ofs,把该流与"f2.dat"相关联。
//判断文件是否能打开
if(!ofs)
{
cout<<"open 'f3.dat' error !"<<endl;
exit(1);
}
cout<<"open 'f3.dat' successfully"<<endl;
for (int i = 0; i < 10; i++)//利用循环将数组存入文件中
{
ofs << a[i] << endl;
}
ofs.close();//关闭流
cout << "run end !" << endl;
system("pause");
return 0;
}
运行结果截图:
题目4:
解题思路:
1.在divide函数中声明抛出int类型异常
2.在try中执行保护段,如果保护段中有异常就执行try后面的catch子句
程序代码:
/*
程序名:题目4.cpp
功能:处理除数为0的异常,用try/catch语句来捕获异常,并使用throw语句来抛出异常,从而实现异常处理。(20分)
日期:2021.12.5
版本:1.0
*/
#include <iostream>
using namespace std;
int divide(int x,int y)
{
cout << "before dividing." << endl;
if (y == 0)
throw x;//抛出int类型异常
cout << "after dividing." << endl;
return x/y;
}
int main()
{
//捕获并处理异常
try
{
//保护段
cout << "5/2=" << divide(5,2) << endl;
cout << "8/0=" << divide(8,0) << endl;
cout << "7/1 = " << divide(7,1) << endl;
}
catch (int x) //或者catch(...)用于接受任何异常,但是如何接受参数x是一个问题
{
//异常处理程序
cout <<"catch(int):"<< x << " is divided by zero!" << endl;
}
cout << "finished" << endl;
system("pause");
return 0;
}
运行结果截图:
四、实验小结
问题与解决办法:
问题1:
出现异常:std::bad_alloc
解决:
内存出现了问题。存储信息都是用vector来存储的,动态内存分配失败,致使超出动态内存最大容量。
问题2:
代码最后出现“屯屯屯屯屯屯屯”
解决:
内存没有初始化造成的,而对于栈中内存如果没有初始化,则会出现“烫烫烫烫烫烫”。对于堆中内存如果没有初始化,则会出现“屯屯屯屯屯”
有时候数组没有结束符,输出数组也会有这些汉字的出现,就是因为没有结束符占用了后面的空闲的内存块即没有初始化的内存块
使用memset去初始化如memset(temp, 0, length);
心得体会:
1.流类库与输入/输出这一章内容感觉书上讲的听不懂,太杂了,而且讲的顺序感觉有问题(自我感觉,因为我看不懂),然后去B站和学堂在线上看课,才终于弄懂。所以看不懂书是正常的,不懂就上网搜,现在网上资源很多。
2.在写的时候已经大概构思好该如何写代码了,但是中间有一步不知道该怎么实现,比如用vector创建自动获取长度的数组,这时候可以去网上搜相关知识来参考,实现代码。
3.C++相关内容已经完全结束了,但是还是感觉很多地方不理解,例如堆栈、内存分配、SQL(这个是一点都不懂,太痛苦了)、类模板后面的知识(数组啥的)。应该找其他书去看,深入去学习C++。