C++实验4 模板和IO流

【实验目的】
掌握运算符重载的基本方法。
掌握标准输入输出的使用及格式控制方法。
掌握磁盘文件(如二进制文件、文本文件)的输入输出的方法。
【实验内容】
1.编写程序,重载运算符“<<”和“>>”,使用户能直接输入和输出固定电话的号码。电话号码以如下形式输入和输出: (027)xxxxxxxx
重载输入输出流进行类对象的输入与输出,固定电话号码类包含区号以及手机号string数据类型
Code:

#include
#include
using namespace std;
class Tel {
private:
 string _Area;
 string _Tel;
public:
 Tel() {}
 //返回is引用 保证只有一个输入流对象
 friend istream& operator>>(istream &in, Tel &tel) {
  cout << "请输入正确的电话号码:";
  string Num;
  in >> Num;
  int rightBrack = Num.find(")");
  tel._Area = Num.substr(1, rightBrack);
  tel._Tel = Num.substr(rightBrack + 1, Num.length());
  return in;
 }
 friend ostream& operator<<(ostream &out, Tel &tel) {
  //输出带括号的电话号码
  cout << "输出电话号码为:";
  out << "(" + tel._Area + ")" + tel._Tel << endl;
  return out;
 }
};
void main() {
 Tel tel;
 cin >> tel;
 cout << tel;
 return;
}

2.编写一个程序,实现以下功能:
(1)输入一系列的学生成绩(包括学号、姓名、成绩等数据)存放在文件stud.dat中。
(2)从stud.dat文件中读出这些数据并显示出来。
(3)在stud.dat文件中按姓名进行查询,如输入“李”,则将所有姓李的学生的数据都显示出来。所编写的程序运行结果示例如下:
选择(1:输入数据 2:输出数据 3:按姓名查找数据 其他退出):1
输入数据
学生人数:5
第1个学生(学号 姓名 成绩):1001 张三 89
第2个学生(学号 姓名 成绩):1002 李四 78
第3个学生(学号 姓名 成绩):1003 王五 92
第4个学生(学号 姓名 成绩):1004 李沅芷 88
第5个学生(学号 姓名 成绩):1005 赵六 56
选择(1:输入数据 2:输出数据 3:按姓名查找数据 其他退出):2
输出数据
学号 姓名 成绩
1001 张三 89
1002 李四 78
1003 王五 92
1004 李沅芷 88
1005 赵六 56
选择(1:输入数据 2:输出数据 3:按姓名查找数据 其他退出):3
输入姓名:李
输出匹配的结果:
学号 姓名 成绩
1002 李四 78
1004 李沅芷 88
选择(1:输入数据 2:输出数据 3:按姓名查找数据 其他退出):3
输入姓名:李四
输出匹配的结果:
学号 姓名 成绩
1002 李四 78
选择(1:输入数据 2:输出数据 3:按姓名查找数据 其他退出):0
【提示】在重载运算符“<<”和“>>”时,不能将其定义为类的成员函数,只能定义为类的友元函数
Code:

#include
#include
#include
using namespace std;
char name[13];
class Student {
private:
 char Number[13];
 char Name[13];
 double Grade;
 static int i;
public:
 friend istream& operator>>(istream &in, Student *stuIn) { //先写入变量 再写入文件
  ofstream binFile;//写入文件
  binFile.open("D:\\stud.dat");
  for (int i = 0; i <5; i++){
   cout << "第" << i+1 << "个学生(学号 姓名 成绩):";//写入变量
   cin >> stuIn[i].Number;
   cin >> stuIn[i].Name;
   cin >> stuIn[i].Grade;
   binFile.write((char*)&stuIn[i], sizeof(Student));//写入文件
  }
  binFile.close();
  return in;
 }
 friend ostream& operator<<(ostream &out, Student &stuOut) {
  ifstream inFile;
  inFile.open("D:\\stud.dat");
  cout << "学号  姓名  成绩" << endl;
  for (int j = 1; j <=5; j++) {
   inFile.read((char*)&stuOut, sizeof(Student)); //先从文件写入变量
   out<<stuOut.Number << " " << stuOut.Name << " " << stuOut.Grade << endl;
  }
  inFile.close();
  return out;
 }
 char* Getnumber() { return Number; }
 char* Getname() { return Name; }
 double Getgrade() { return Grade; }
};
int Student::i = 0;
void main() {
 Student *stuIn=new Student[5];
 Student stuOut;
 int choice,flag=0;
 while (true){
  cout << "1.输入数据" << endl;
  cout << "2.输出数据" << endl;
  cout<<"3.按姓名查找数据"<<endl;
  cout << "0.退出" << endl;
  cin >> choice;
  switch (choice)
  {
  case 1:
     cout << "学生人数:5" << endl;
     cin >> stuIn; //输入并保存
     flag = 1;
     break;
  case 2:
    if (flag == 0) {
     cout << "请先输入学生信息再进行查询" << endl;
     break;
   }
    cout << stuOut;//输出
    break;
  case 3:
    if (flag==0){
     cout << "请先输入学生信息再进行查询" << endl;
     break;
    }
     cout << "输入姓名:";
     char nameIn[20];
     cin >> nameIn;
    if (strstr(stuIn[1].Getname(), nameIn)!=0 || strcmp(stuIn[1].Getname(), nameIn) == 0) {
      cout<<"hhh"<<endl;
    }
      cout << "输出匹配结果:" << endl;
      cout << "学号 姓名 成绩" << endl;
    for (int i = 0; i < 5; i++){
      if (strstr(stuIn[i].Getname(),nameIn)!=0 || strcmp(stuIn[i].Getname(),nameIn)==0){
       cout << stuIn[i].Getnumber() << " " << stuIn[i].Getname() << " " << stuIn[i].Getgrade() << endl;
     }
    }
    break;
  case 0:
    exit(0);
    break;
  }
 }
 return;
}

3.已知
void Sort(int a[],int size);
void Sort(double a[],int size);
是一个函数模板的两个实例,其功能是将数组a中的前size个元素按从小到大顺序排列。试设计这个函数模板,并构建main主函数和数据测试函数模板。
(比较简单 但写的时候突然想到了堆排序 就试着回忆着用推排序 知道思路但是写的时候还是遇到了问题
老师的ppt上有这道实验题答案 用冒泡排序写的哈哈哈哈)
堆排序讲解 非常透彻!!
另外,代码和实验要求不是很符合,权当复习下堆排序了。

#include
using namespace std;
#define LeftChild(i) (2*(i)+1)
template<typename T>
//元素下沉(从编号为i的元素开始调整)
void PercDown(T a[], int i, int N) {
 int child;
 T tmp;
 for (tmp = a[i]; LeftChild(i) < N; i = child) {
  child = LeftChild(i);
  if (child != N - 1 && a[child + 1] > a[child]) {
   child++;
  }
  if (a[i] < a[child]) {
   tmp = a[i];
   a[i] = a[child];
   a[child] = tmp;
  }
 }
}
template<typename T>
//数组a的前size个元素进行排序
void Sort(T a[], int size) {
    T end[5];
 for (int i = 0; i < size; i++) {
   end[i] = a[i];
 }
 //1.创建一个大根堆 (从第一个非叶子节点开始)
 for (int i = size/2-1; i >=0; i--){
   PercDown(end, i, size);
 }
 //2.不断调整大根堆,使其到达有序 (交换size-1次)
  for (int i = size-1; i>0; i--){
   T flag=end[i];
   end[i] = end[0];
   end[0] = flag;
   PercDown(end, 0, i);
 }
  for (int i = 0; i < size; i++) {
   a[i] = end[i] ;
 }
}
void main() {
 int a[7] = { 1,3,4,2,5,7,6 };
 double b[7] = { 1.1,3.1,4.1,2.1,5.1,7.1,6.1};
 Sort(a, 5);
 Sort(b, 5);
 cout << "a数组排序后前5个元素";
 for (int i = 0; i < 5; i++){
   cout << a[i] << " ";
 }
 cout << endl;
 cout << "b数组排序后前5个元素";
 for (int i = 0; i < 5; i++){
   cout << b[i] << " ";
 }
}

4.设有如下的类声明:

试将此类声明改为类模板声明,使得数据成员data1和data2可以是任何类型。,并构建main主函数和数据测试类模板。(比较简单)

#include
using namespace std;
//类模板:声明一个类时将实现这个类所需要的数据成员的类型、成员函数的参数类型
//       或返回值的类型参数化
template<typename T1,typename T2>
class  Test
{
public:
 void SetData1(T1 val) { data1 = val; }
 void SetData2(T2 val) { data2 = val: }
 T1 GetData1() { return data1; }
 T2 GetData2() { return data2; }
private:
 T1 data1;
 T2  data2;
};
void main() {
 Test<int,double> t1;
 int x = 5;
 double y = 5.5
 t1.SetData1(x);
 t1.SetData2(y);
 cout << "data1 = " << t1.GetData1() << endl;
 cout << "data2 = " << t1.GetData2() << endl;
}

和老师发的参考做的不一样…

你可能感兴趣的:(C++)