实验 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:
    394393-20180610140510942-628254655.png

    4.1.2 11-3
  • Code:
#include<bits/stdc++.h>
using namespace std;
int main(){
    ofstream fout("test1.txt");
    fout<<"已成功写入文件!";
    fout.close();
    return 0; 
}
  • 演示:
    394393-20180610140540773-1988516886.gif
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; 
}
  • 演示:
    394393-20180610140640321-1623271177.gif

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

控制台窗口运行结果:
394393-20180610130600876-1068741076.png
运行文件夹及文件截图:
394393-20180610130619371-67021613.png

  • ②:选做部分
    实现功能:通过输入班级序号选择班级进行点名,通过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;
}

演示效果如下:
394393-20180610135128605-2037980101.gif
394393-20180610135133200-439630271.gif

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):
    394393-20180610145506300-612257223.png
  • 测试文件2 (bible.txt):
    394393-20180610145541804-1275187664.png

转载于:https://www.cnblogs.com/shy-/p/9163026.html

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值