一、实验目的
- 理解流的概念
- 熟悉流类库中常用的类及成员函数用法
- 熟悉 I/O 格式控制方法,掌握常用格式控制
- 了解文件 I/O,掌握文件 I/O 基本用法
二、实验准备
结合第 11 章教材、课件,复习/学习如下内容:
- 基础知识
- 流是什么?如何理解?
- C++中 I/O 是通过什么来实现的?
- 常用 I/O 流类的继承/派生层次关系
- 预定义标准流对象 cin, cout, cerr, clog
- C++中格式化 I/O 方法
- 文件 I/O 方法及常用成员函数
三、实验内容
- 基础练习
- 教材习题 11-7
- 教材习题 11-3
- 教材习题 11-4
- 应用练习
- 已知有班级名单文件 list.txt(见实验 7 附件包)。编写一个应用程序实现随机抽点
5 位同学,在屏幕上显示结果,同时,也将结果写入文件 roll.txt。- 编写程序实现题目基本功能要求。(必做)
- (选做)
对①中实现的基本功能进行完善、扩充,使得这个点名应用程序更灵活、更方便。比如:- 从键盘输入班级文件名,支持对不同班级的点名操作;
- 从键盘输入用于保存点名结果的文件名。更灵活地,自动获取当前系统日期作为文件名,比如 20180612.txt。(如果希望更细粒度,文件名可以到小时和分钟这一层级);
- 随机抽点人数不固定,通过键盘按键控制何时抽点结束;
- 通过菜单及程序的函数模块划分,或类的设计与实现,做成一个更完善的应用,等等。
- 统计英文文本文件字符数、单词数、行数,文件名由键盘输入。
- 编写 C++程序实现题目基本功能要求。(必做)
- 选做
- 提供菜单,由用户选择统计内容;
- 思考当文本内容数量级偏大,①处已实现的程序能否胜任,实现快速统计?在算法和处理逻辑上是否存在进一步改进的部分?
- 已知有班级名单文件 list.txt(见实验 7 附件包)。编写一个应用程序实现随机抽点
四、实验步骤
4.1 基础练习
4.1.1 11-7
- 注释:
#include <iostream>
using namespace ::std;
int main() {
ios_base::fmtflags original_flags = cout.flags(); //保存cout参数设置
cout<< 812<<'|';
cout.setf(ios_base::left,ios_base::adjustfield); //设置cout的对齐方式为左对齐
cout.width(10); //将cout宽度改为10
cout<< 813 << 815 << '/n';
cout.unsetf(ios_base::adjustfield); //取消cout对齐方式的设置
cout.precision(2);// 设置浮点数输出的精度值
cout.setf(ios_base::uppercase|ios_base::scientific); //设置浮点数的显示参数
cout << 831.0 ;
cout.flags(original_flags); //恢复cout原参数设置
return 0;
}
- Screenshot:
4.1.2 11-3
- Code:
#include<bits/stdc++.h>
using namespace std;
int main(){
ofstream fout("test1.txt");
fout<<"已成功写入文件!";
fout.close();
return 0;
}
- 演示:
4.1.3 11-4
- Code:
#include<bits/stdc++.h>
using namespace std;
int main(){
ifstream fin("test1.txt");
string tmp;
getline(fin,tmp);
cout<<tmp;
fin.close();
system("pause");
return 0;
}
- 演示:
4.2 应用练习
4.2.1
- ①:必做部分:
#include<bits/stdc++.h>
#define rap(a,b) for(int a=0;a<b;++a)
using namespace std;
struct stu{
int num;
string stuid,name,cls;
}tmp;
ostream &operator <<(ostream &o,const stu &tmp){
o<<tmp.num<<" "<<tmp.stuid<<" "<<tmp.name<<" "<<tmp.cls<<endl;
return o;
}
ifstream fin;
int main(){
ifstream fin("list.txt");
vector<stu>a;
while(fin>>tmp.num>>tmp.stuid>>tmp.name>>tmp.cls){
a.push_back(tmp);
}
//cout<<a.size();
fin.close();
ofstream fout("roll.txt");
srand((unsigned)time(NULL));
rap(i,5){
int tmp2=rand()%a.size();
cout<<a[tmp2];
fout<<a[tmp2];
}
fout.close();
return 0;
}
控制台窗口运行结果:
运行文件夹及文件截图:
- ②:选做部分
实现功能:通过输入班级序号选择班级进行点名,通过ENTER键控制点名数量,通过时间或用户输入的字符串保存文件:
Code:
#include<bits/stdc++.h>
#define rap(a,b) for(int a=0;a<b;++a)
using namespace std;
struct stu{
int num;
string stuid,name,cls;
}tmp;
ostream &operator <<(ostream &o,const stu &tmp){
o<<tmp.num<<" "<<tmp.stuid<<" "<<tmp.name<<" "<<tmp.cls<<endl;
return o;
}
int cmp(const stu &a,const stu &b){
return a.cls>b.cls;
}
void callbyclass(vector<stu>a,vector<stu>*res){
int sz=a.size();
sort(a.begin(),a.end(),cmp);
vector<int>clsidx;
string tmp=a[0].cls;
clsidx.push_back(0);
rap(i,sz){
if(a[i].cls!=tmp){
clsidx.push_back(i);
tmp=a[i].cls;
}
}
clsidx.push_back(sz);
cout<<"Class:"<<endl;
rap(i,clsidx.size()-1)cout<<i+1<<" : "<<a[clsidx[i]].cls<<endl;
cout<<"Please Choose Class num to call student"<<endl;
int idx;
cin>>idx;
while(idx>clsidx.size()){
cout<<"Wrong Class number, plz choose again!"<<endl;
cin>>idx;
}
getchar();
do{
int t=rand()%(clsidx[idx]-clsidx[idx-1]);
cout<<a[t+clsidx[idx-1]];
res->push_back(a[t+clsidx[idx-1]]);
}while(getchar()=='
');
}
int main(){
time_t t = time(0);
ifstream fin("list.txt");
vector<stu>a;
while(fin>>tmp.num>>tmp.stuid>>tmp.name>>tmp.cls){
a.push_back(tmp);
}
fin.close();
srand((unsigned)time(NULL));
vector<stu>res;
callbyclass(a,&res);
cout<<"Save by time enter 1, by your desired string enter 2.
";
int tmp;
cin>>tmp;
if(tmp==1)
{
char ch[64];
strftime(ch, sizeof(ch), "%Y%m%d%H%M%S.txt", localtime(&t));
ofstream fout(ch);
rap(i,res.size())fout<<res[i];
fout.close();
}
else if(tmp==2){
string n;
cout<<"
Plz enter your filename:"<<endl;
cin>>n;
ofstream fout(n.c_str());
rap(i,res.size())fout<<res[i];
fout.close();
}
return 0;
}
演示效果如下:
4.2.2
- ① 必做部分:
算法思路:利用getline函数读入每一行,每一行得到的 string.size() 即为每行字符数量,利用 strtok 分割文本得到单词数。
Code:
#include<bits/stdc++.h>
using namespace std;
const char de[]={'"',',',' ','.',' ','!','?','-','(',')','#','/',':'};
int main(){
cout<<"Please Enter filname:
";
string filename;
cin>>filename;
ifstream fin(filename.c_str());
string line;
long long linenum=0,chnum=0,wordnum=0;
while(getline(fin,line)){
char *tmp=new char[line.length()+1];
strcpy(tmp,line.c_str());
char *tmp2;
tmp2=strtok(tmp,de);
if(tmp2!="")wordnum++;
while((tmp2=strtok(NULL,de)))wordnum++;
linenum++;
chnum+=line.size();
}
cout<<"行数:"<<linenum<<" 字符数:"<<chnum<<" 单词数:"<<wordnum;
fin.close();
return 0;
}
- 测试文件1(233.txt):
- 测试文件2 (bible.txt):