实验 7:流类库与输入输出

一、实验目的

  • 理解流的概念
  • 熟悉流类库中常用的类及成员函数用法
  • 熟悉 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++程序实现题目基本功能要求。(必做)
      • ******选做******
        • 提供菜单,由用户选择统计内容;
        • 思考当文本内容数量级偏大,①处已实现的程序能否胜任,实现快速统计?在算法和处理逻辑上是否存在进一步改进的部分?

四、实验步骤

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()=='\n');
    } 
    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.\n";
    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<<"\nPlz 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[]={'"',',',' ','.','\0','!','?','-','(',')','#','/',':'};
    int main(){
    cout<<"Please Enter filname:\n";
    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):

猜你喜欢

转载自www.cnblogs.com/shy-/p/9163026.html