实验6 模板类和文件I/O

1.

程序源码

task1

#include <iostream>
#include <fstream>
#include "Complex.hpp"

void test1() {
    using namespace std;

    Complex<double> c1{1, 2}, c2;

    cout << "Enter c2: ";
    cin >> c2;
    cout << "c1 = " << c1 << endl;
    cout << "c2 = " << c2 << endl;

    cout << "c1 + c2 = " << c1 + c2 << endl;
    c1 += c2;
    cout << "c1.real = " << c1.get_real() << endl;
    cout << "c1.imag = " << c1.get_imag() << endl;

    cout << boolalpha << (c1 == c2) << endl;
}

void test2() {
    using namespace std;

    ofstream out;
    out.open("ans.txt");
    if(!out.is_open()) {
        cout << "fail to open file ans.txt to write\n";
        return;
    }
    Complex<int> c1{1, 9}, c2{8, 4};

    out << "c1 = " << c1 << endl;
    out << "c2 = " << c2 << endl;
    out << "c1 + c2 = " << c1 + c2 << endl;

    out.close();
}


int main() {
    using namespace std;

    cout << "test template Class Complex<T>....\n";
    test1();

    cout << "\ntest FILE I/O...\n";
    test2();
}

Complex.hpp

#pragma once

#include <iostream>

using std::cout;
using std::endl;
using std::ostream;
using std::istream;

// declaration of template class
template<typename T>
class Complex {
public:
    Complex(T r = 0, T i = 0): real{r}, imag{i} {}
    Complex(const Complex<T> &c): real{c.real}, imag {c.imag} {}

    T get_real() const { return real; }
    T get_imag() const { return imag; }
    
    Complex<T>& operator+=(const Complex<T> c1);

    template<typename T1>
    friend ostream &operator<<(ostream &out, const Complex<T1> &c1);

    template<typename T1>
    friend istream &operator>>(istream &in, Complex<T1> &c1);

private:
    T real;
    T imag;
};

// definition of template class 
// ----------------member function----------------
// overload operator+=, support operation such as c1 += c2
template<typename T>
Complex<T>& Complex<T>::operator+=(const Complex<T> c1) {
    real += c1.real;
    imag += c1.imag;

    return *this;
}

// ---------------general function-----------------
// overload operator+, support operation such as c1 + c2
template<typename T>
Complex<T> operator+(const Complex<T> &c1, const Complex<T> &c2) {
    return Complex<T>(c1.get_real() + c2.get_real(),
                      c1.get_imag() + c2.get_imag());
}

// overload operator==, support operation such as c1 == c2
template<typename T>
bool operator==(const Complex<T> &c1, const Complex<T> &c2) {
    return c1.get_real() == c2.get_real() &&
           c1.get_imag() == c2.get_imag();
}

//--------------------friend function---------------
// overload operator<<, support operation such as cout << c1 << endl;
template<typename T1>
ostream &operator<<(ostream &out, const Complex<T1> &c1) {
    if(c1.imag == 0)
        out << c1.real;
    else if(c1.imag > 0)
        out << c1.real << " + " << c1.imag << "i";
    else
        out << c1.real << " - " << -c1.imag << "i";
    
    return out;
}

// overload operator>>, support operation such as cin >> c1 >> c2
template<typename T1>
istream &operator>>(istream &in, Complex<T1> &c1) {
    in >> c1.real >> c1.imag;

    return in;
}

测试运行结果截图

2.实验任务2

task2.cpp

#include "stu.hpp"
#include "utils.hpp"
#include <vector>
#include <fstream>
#include <algorithm>

int main() {
    using namespace std;

    vector<STU> stu;
    STU t;

    ifstream in;
    in.open("data.txt", ios::in);
    if(!in.is_open()) {
        cout << "fail to open file data.txt\n";
        return 1;
    }

    while(in >> t) 
        stu.push_back(t);

    in.close();

    // ouput original stu info to screen
    cout << endl << "original info: " << endl;
    output(cout, stu);

    // sort by no
    // save to file data_by_no.txt
    sort(stu.begin(), stu.end(), compare_by_no);
    save("data_by_no.txt", stu);

    // sort by name
    // save to file data_by_name.txt
    sort(stu.begin(), stu.end(), compare_by_name);
    save("data_by_name.txt", stu);

    // sort by score, in decending order
    // output to file data_by score
    sort(stu.begin(), stu.end(), compare_by_score);
    save("data_by_score.txt", stu);
}

stu.hpp

#pragma once

#include <iostream>
#include <iomanip>
#include <string>

using std::string;
using std::ostream;
using std::istream;
using std::setw;
using std::setiosflags;
using std::ios_base;

class STU{
public:
    STU() = default;
    ~STU() = default;

    string get_name() const { return name; }
    string get_no() const { return no; }
    int get_score() const { return score; }

    friend ostream& operator<<(ostream &out, const STU &s);
    friend istream& operator>>(istream &in, STU &s);

private:
    string no;  
    string name;    
    int score;      
};

ostream& operator<<(ostream &out, const STU &s) {
    out << setiosflags(ios_base::left) << setw(15) << s.no
        << setw(15) << s.name
        << s.score;
    
    return out;
}

istream& operator>>(istream &in, STU &s) {
    in >> s.no >> s.name >> s.score;

    return in;
}

utils.hpp

#include "stu.hpp"
#include <vector>
#include <fstream>
#include <iostream>

bool compare_by_name(const STU &s1, const STU &s2) {
    return s1.get_name() < s2.get_name();
}

bool compare_by_no(const STU &s1, const STU &s2) {
    return s1.get_no() < s2.get_no();
}

bool compare_by_score(const STU &s1, const STU &s2) {
    return s1.get_score() > s2.get_score();
}

void output(std::ostream &out, std::vector<STU> &v) {
    for(auto &i: v) 
        out << i << std::endl;
}

void save(string filename, std::vector<STU> &v) {
    using std::ofstream;

    ofstream out;

    out.open(filename);
    if(!out.is_open()) {
        std::cout << "fail to open file " << filename << std::endl;
    }

    output(out, v);
    
    out.close();
}

测试运行结果截图

3.实验任务3

程序源码

task3_1

#include <iostream>
#include <fstream>
#include <array>
#define N 5

int main() {
    using namespace std;

    array<int, N> x {97, 98, 99, 100, 101};

    ofstream out;
    out.open("data1.dat", ios::binary);
    if(!out.is_open()) {
        cout << "fail to open data1.dat\n";
        return 1;
    }

    out.write(reinterpret_cast<char *>(&x), sizeof(x));
    out.close();
}

测试运行结果截图

程序源码

task3_2

#include <iostream>
#include <fstream>
#include <array>
#define N 5

int main() {
    using namespace std;
    array<int, N> x;

    ifstream in;
    in.open("data1.dat", ios::binary);
    if(!in.is_open()) {
        cout << "fail to open data1.dat\n";
        return 1;
    }

    in.read(reinterpret_cast<char *>(&x), sizeof(x));
    in.close();

    for(auto i = 0; i < N; ++i)
        cout << x[i] << ", ";
    cout << "\b\b \n";
}#include <iostream>
#include <fstream>
#include <array>
#define N 5

int main() {
    using namespace std;
    array<int, N> x;

    ifstream in;
    in.open("data1.dat", ios::binary);
    if(!in.is_open()) {
        cout << "fail to open data1.dat\n";
        return 1;
    }

    in.read(reinterpret_cast<char *>(&x), sizeof(x));
    in.close();

    for(auto i = 0; i < N; ++i)
        cout << x[i] << ", ";
    cout << "\b\b \n";
}

测试运行结果截图

 

问题:对task3_2.cpp的代码稍做改动,把line8的数组类型从int类型修改成char类型,即: array<int,N> x; ----> 修改成: array<char, N> x; 其它不做任何改动,再次运行程序,观察运行结果是什么?尝试分析原因:为什么会是那样 的结果?

测试运行结果截图

原因分析:

char型占用1字节,int型占用4个字节。存储于data1.dat文件中时是用的char型,即a   b   c   d   e,原代码是int型读取,即97 98 99 100 101,而修改后以char型读取,读取时是一个字节个字节读取,所以会产生空格。

4.实验任务4

程序源码

task4.cpp

#include <iostream>
#include "Vector.hpp"

void test() {
    using namespace std;

    int n;
    cin >> n;
    
    Vector<double> x1(n);
    for(auto i = 0; i < n; ++i)
        x1.at(i) = i * 0.7;

    output(x1);

    Vector<int> x2(n, 42);
    Vector<int> x3(x2);

    output(x2);
    output(x3);

    x2.at(0) = 77;
    output(x2);

    x3[0] = 999;
    output(x3);
}

int main() {
    test();
}

Vector.hpp

#pragma once
using namespace std;
template <typename T>
class Vector
{
private:
    int size;
    T *p;

public:
    Vector(int n): size{n} {p = new T[n];};
    Vector(int n, T x):size{n}
    {
        p = new T[n];
        for (auto i = 0; i < n; i++)
            p[i] = x;
    };
    Vector(const Vector<T> &y): size{y.size}
    {
        p = new T[size];
        for (auto i = 0; i < y.size; i++)
        p[i] = y.p[i];
    };
    ~Vector()=default;
    
    int get_size() { return size; }
    T &at(int index){return p[index];}
    T &operator[](int index){return p[index];}
   
    friend void output(Vector &x)
    {
        int i;
        for (i = 0; i < x.size - 1; i++)
        {
            cout << x.p[i] << ", ";
        }
        cout << x.p[i] << endl;
    }
};

测试运行结果截图

5.实验任务5

程序源码

task5

#include<iostream>
#include <fstream>
#include<iomanip>
using namespace std;

void output(std::ostream &out)
{
    out<<"   ";
    for(int i=97;i<123;i++)
    {
        out<<char(i)<<" ";
    }
    out<<endl;
    for(int i=1;i<=26;i++)
    {
        out<<setw(2)<<i;
        for(int j=i;j<i+26;j++)
        {
            out<<setw(2)<<char(65 + j % 26);
        }
        out<<endl;
    }
}

int main()
{
    output(cout);
    ofstream out;
    out.open("cipher_key.txt");
    if(!out.is_open()){
        cout<<"fail to open file cipher_key.txt to write"<<endl;
        return 0;
    }
    output(out);
    out.close();
}

测试运行结果截图

 

 

posted @ 2022-11-30 19:00  阑夜风华  阅读(38)  评论(0编辑  收藏  举报