广州大学程序设计基础实验报告三

广州大学学生实验报告

                                       

学院

年级/专业/班

姓名

学号

实验课程名称

程序设计基础(实验课)

成绩

实验项目名称

实验3 数组、结构体及指针

指导

老师

实验A 数组字符串

一、实验目的及要求

1.了解数组与数学矩阵的关系;

2.掌握数组的定义、引用与初始化;

3.理解二维数组数据的存储顺序;

4.理解并掌握冒泡排序法、选择排序法;

5.掌握字符数组与字符串的定义、引用;

6.了解字符串处理函数的用法。

二、实验设备与平台

1. 实验设备:计算机

2. 平台:Windows操作系统,Microsoft Visual C++或其它合适的C++编程环境。

三、实验内容及步骤

编写程序,解下列问题,然后把编写的程序代码和运行结果截图复制到题目后面的空白处。

    1、某班期末考试科目为数学(MT)、英语(EN)和物理(PH),有最多不超过30人参加考试。考试后要求:

(1)计算每个学生的总分和平均分;

(2)按总分成绩由高到低排出成绩的名次;

(3)打印出名次表,表格内包括学生编号、各科分数、总分和平均分;

(4)任意输入一个学号,能够查找出该学生在班级中的排名及其考试分数。

程序代码:

// 程序设计基础实验3 数组、结构体及指针

// 实验A 数组字符串

// 问题描述:

/*1、某班期末考试科目为数学(MT)、英语(EN)和物理(PH),有最多不超过30人参加考试。

考试后要求:

(1)计算每个学生的总分和平均分;

(2)按总分成绩由高到低排出成绩的名次;

(3)打印出名次表,表格内包括学生编号、各科分数、总分和平均分;

(4)任意输入一个学号,能够查找出该学生在班级中的排名及其考试分数。*/

#include<iostream>

#include<iomanip>

using namespace std;

//数组初始化

void Initial(int num, string*& p_Code, double*& p_MT, double*& p_EN, double*& p_PH, double*& p_TotalScore, double*& p_AvrScore, int*& p_Rank);

//学生考试成绩分数录入

void RigisterGrades(int num, string*& p_Code, double*& p_MT, double*& p_EN, double*& p_PH, double*& p_TotalScore, double*& p_AvrScore);

//交换函数:函数模板

template<typename T>

void Swap(T& element1, T& element2);

//按总分成绩排序 冒泡排序

void BubbleSort(int num, string*& p_Code, double*& p_MT, double*& p_EN, double*& p_PH, double*& p_TotalScore, double*& p_AvrScore);

//学生成绩排名生成

void PrdRank(int num, double* p_TotalScore, int*& p_Rank);

//考试成绩名次表打印

void DispGradesRank(int num, string* p_Code, double* p_MT, double* p_EN, double* p_PH, double* p_TotalScore, double* p_AvrScore, int* p_Rank);

//学生考试成绩查询

void SeekStudentGrades(int num, string* p_Code, double* p_MT, double* p_EN, double* p_PH, double* p_TotalScore, double* p_AvrScore, int* p_Rank);

//释放内存空间

void DeleteSpace(string*& p_Code, double*& p_MT, double*& p_EN, double*& p_PH, double*& p_TotalScore, double*& p_AvrScore, int*& p_Rank);

int main()

{

    //double array_MT[30], array_EN[30], array_PH[30], num;  //动态数组使用,而不采用固定数组

    //定义指针并将其赋空值

    int* p_Rank;

    double* p_MT, * p_EN, * p_PH, * p_TotalScore, num;

    double* p_AvrScore;

    string* p_Code;

    p_Rank = NULL;

    p_MT = p_EN = p_PH = p_TotalScore = p_AvrScore = NULL;

    p_Code = NULL;

    cout << "请输入考试参与人数:" << endl;

    cin >> num;

    Initial(num, p_Code, p_MT, p_EN, p_PH, p_TotalScore, p_AvrScore, p_Rank);            //数据初始化

    RigisterGrades(num, p_Code, p_MT, p_EN, p_PH, p_TotalScore, p_AvrScore);             //学生成绩录用

    BubbleSort(num, p_Code, p_MT, p_EN, p_PH, p_TotalScore, p_AvrScore);                 //学生成绩排序

    PrdRank(num, p_TotalScore, p_Rank);                                                  //学生成绩排名生成

    DispGradesRank(num, p_Code, p_MT, p_EN, p_PH, p_TotalScore, p_AvrScore, p_Rank);     //学生成绩打印

    SeekStudentGrades(num, p_Code, p_MT, p_EN, p_PH, p_TotalScore, p_AvrScore, p_Rank);  //学生成绩查询

    DeleteSpace(p_Code, p_MT, p_EN, p_PH, p_TotalScore, p_AvrScore, p_Rank);             //释放指针所指空间

    return 0;

}

//数组初始化

void Initial(int num, string*& p_Code, double*& p_MT, double*& p_EN, double*& p_PH, double*& p_TotalScore, double*& p_AvrScore, int*& p_Rank)

{

    //动态创建数组

    p_MT = new double[num];

    p_EN = new double[num];

    p_PH = new double[num];

    p_TotalScore = new double[num];

    p_AvrScore = new double[num];

    p_Code = new string[num];

    if (p_MT && p_EN && p_PH && p_TotalScore && p_AvrScore && p_Code)  //内存分配成功

    {

        //为数组赋初值

        for (int i = 0; i < num; i++)

        {

            p_Code[i] = " ";

            p_MT[i] = p_EN[i] = p_PH[i] = p_TotalScore[i] = p_AvrScore[i] = 0;

        }

    }

    else

    {

        cout << "内存申请出错!" << endl;

    }

}

//学生考试成绩分数录入

void RigisterGrades(int num, string*& p_Code, double*& p_MT, double*& p_EN, double*& p_PH, double*& p_TotalScore, double*& p_AvrScore)

{

    cout << "请依次输入每位学生的学生编号、数学分数、英语分数、物理分数:" << endl;

    cout << "(注意:输入学生编号后使用按下回车,然后输入分数,分数之间用空格间隔)" << endl;

    for (int i = 0; i < num; i++)

    {

        cout << "学生编号:";

        cin >> p_Code[i];

        bool isExist = 0;

        for (int j = 0; j < i; j++)  //遍历已录入的成绩表

        {

            if (p_Code[i] == p_Code[j])  //当前输入的学生编号已存在于成绩表中

            {

                isExist = 1;

                cout << "该学生编号的成绩已录入,无需再次录入" << endl;

                i--;

                cout << "请继续录用下一个学生的成绩" << endl;

                break;

            }

        }

        if (!isExist)  //该学生编号不存在成绩表中时,继续录用

        {

            cout << "数学成绩、英语成绩、物理成绩:";

            cin >> p_MT[i] >> p_EN[i] >> p_PH[i];  //输入该学生的相关数据

            p_TotalScore[i] = p_MT[i] + p_EN[i] + p_PH[i];      //计算该学生的总分

            p_AvrScore[i] = p_TotalScore[i] / 3.0;              //计算该学生的平均分

        }

    }

}

整型交换函数

//void Swap_int(int& num1, int& num2)  //进行两元素的交换

//{

//    int temp;

//    temp = num1;

//    num1 = num2;

//    num2 = temp;

//}

字符串交换函数

//void Swap_string(string& code1, string& code2)  //进行两元素的交换

//{

//    string temp;

//    temp = code1;

//    code1 = code2;

//    code2 = temp;

//}  //这样子写不够高效。改进:使用泛型程序设计。

//交换函数:函数模板

template<typename T>

void Swap(T& element1, T& element2)

{

    T temp;

    temp = element1;

    element1 = element2;

    element2 = temp;

}

//按总分成绩排序 冒泡排序         //把高成绩冒在数组前面

void BubbleSort(int num, string*& p_Code, double*& p_MT, double*& p_EN, double*& p_PH, double*& p_TotalScore, double*& p_AvrScore)

{

    int i, j;

    bool exchange;

    for (i = 0; i < num - 1; i++)

    {

        exchange = false;                 //判别因子

        for (j = num - 1; j > i; j--)

            if (p_TotalScore[j] > p_TotalScore[j - 1])  //相邻元素反序时

            {

                Swap(p_TotalScore[j], p_TotalScore[j - 1]);  //将总分中的两元素交换

                Swap(p_AvrScore[j], p_AvrScore[j - 1]);      //将平均分中的两元素交换

                Swap(p_MT[j], p_MT[j - 1]);                  //将数学分数中的两元素交换

                Swap(p_EN[j], p_EN[j - 1]);                  //将英语分数中的两元素交换

                Swap(p_PH[j], p_PH[j - 1]);                  //将物理分数中的两元素交换

                Swap(p_Code[j], p_Code[j - 1]);              //将学生编号中的两元素交换

                exchange = true;

            }

        if (!exchange)                   //本趟没有发生交换,结束算法

            break;

    }

}

//学生成绩排名生成:学生成绩相同时,他们的成绩排名应相同

void PrdRank(int num, double* p_TotalScore, int*& p_Rank)

{

    p_Rank = new int[num];  //申请内存空间

    if (p_Rank)

    {

        for (int i = 0; i < num; i++)

        {

            if (i == 0)

            {

                p_Rank[i] = 1;  //总分第一的无需进行比较

            }

            else  //总分非第一的同学,需要判断是否与前一位同学总分相同

            {

                //总分与上一名学生相同,则排名与其相同;总分不同,则排名+1

                p_Rank[i] = p_TotalScore[i] < p_TotalScore[i - 1] ? p_Rank[i - 1] + 1 : p_Rank[i - 1];  

            }

        }

    }

    else

    {

        cout << "内存申请出错!" << endl;

    }

}

//考试成绩名次表打印

void DispGradesRank(int num, string* p_Code, double* p_MT, double* p_EN, double* p_PH, double* p_TotalScore, double* p_AvrScore, int* p_Rank)

{

    cout << "-----------------------------------------考试成绩名次表打印-----------------------------------------" << endl;

    cout << "学生编号" << '\t' << "数学成绩" << '\t' << "英语成绩" << '\t' << "物理成绩" << '\t' << "总分    " << '\t' << "平均分  " << '\t' << "排名" << endl;

    for (int i = 0; i < num; i++)

    {

        cout << p_Code[i] << '\t' << '\t' << p_MT[i] << '\t' << '\t' << p_EN[i] << '\t' << '\t' << p_PH[i]

            << '\t' << '\t' << p_TotalScore[i] << '\t' << '\t' << setprecision(4) << p_AvrScore[i] << '\t' << '\t' << p_Rank[i] << endl;

    }

    cout << "----------------------------------------考试成绩名次表分割线-----------------------------------------" << endl;

}

//学生考试成绩查询

void SeekStudentGrades(int num, string* p_Code, double* p_MT, double* p_EN, double* p_PH, double* p_TotalScore, double* p_AvrScore, int* p_Rank)

{

    string temp_code;

    cout << "请输入需要查询的学生的编号:" << endl;

    cin >> temp_code;

    int i = 0;

    for (; i < num; i++)

    {

        if (temp_code == p_Code[i])

        {

            cout << "-----------------------------------------考试成绩查询结果打印----------------------------------------" << endl;

            cout << "学生编号" << '\t' << "数学成绩" << '\t' << "英语成绩" << '\t' << "物理成绩" << '\t' << "总分    " << '\t' << "平均分  " << '\t' << "排名" << endl;

            cout << p_Code[i] << '\t' << '\t' << p_MT[i] << '\t' << '\t' << p_EN[i] << '\t' << '\t' << p_PH[i]

                << '\t' << '\t' << p_TotalScore[i] << '\t' << '\t' << setprecision(4) << p_AvrScore[i] << '\t' << '\t' << p_Rank[i] << endl;

            cout << "------------------------------------------考试成绩查询分割线-----------------------------------------" << endl;

            break;

        }

    }

    if (i == num)

        cout << "查询出错,无该学生编号的成绩" << endl;

}

//释放内存空间

void DeleteSpace(string*& p_Code, double*& p_MT, double*& p_EN, double*& p_PH, double*& p_TotalScore, double*& p_AvrScore, int*& p_Rank)

{

    //释放指针所指的内存空间

    delete[]p_Code;

    delete[]p_MT;

    delete[]p_EN;

    delete[]p_PH;

    delete[]p_TotalScore;

    delete[]p_AvrScore;

    delete[]p_Rank;

    //将指针变量赋NULL值,以清除其无意义的地址值

    p_Code = NULL;

    p_MT = NULL;

    p_EN = NULL;

    p_PH = NULL;

    p_TotalScore = NULL;

    p_AvrScore = NULL;

    p_Rank = NULL;

}

运行结果截图:

案例1:(正确运行结果)

案例2:(输入出错检测)

心得与体会:

  1. 在对程序学生成绩按照由高到低进行排序时,因考虑到学生成绩相同时,他们的成绩排名应相同。这一点在我设计时没有考虑到,而是在我进行测试时,才想到的。
  2. 设计一些查询、打印相关函数时,参数无需设置为引用,这样子可以提高程序的正确性。这一点容易遗漏。
  3. 分数可以设置为整型,也可以设置为浮点型。就看个人如何定义分数。但是平均分不应该设置为整型,因为平均分在计算过程中可能会产生小数部分。
  4. 在编程过程中,由于学生编号与学生分数的变量类型不同,因此它们可能要分别设计两个函数来做某一样相同的功能,例如:两元素交换。但其实他们仅仅只是变量类型不同,函数中所执行的操作完全相同。这就用到了泛型程序设计中的函数模板!进而简化代码量,去除繁琐的代码。
  5. 需要设置一些差错检测,例如:录入成绩时,用户重复录入,需要提示该学生编号的成绩已录入。又如:根据学生编号进行查询成绩时,查找不到该学生编号时,需要提示“无该学生编号的成绩”。

    2、不用字符串处理函数将两个字符串连接,即将字符串b连接到字符串a的后面,变成字符串c。

程序代码:

// 程序设计基础实验3 数组、结构体及指针

// 实验A 数组字符串

// 问题描述:

/*2、不用字符串处理函数将两个字符串连接,即将字符串b连接到字符串a的后面,变成字符串c。*/

#include<iostream>

#include<string>

using namespace std;

int main()

{

    string a, b;  //定义字符串a和字符串b以及它们对应的长度

    int aSize, bSize, cSize;

    a = b = " ";

    cout << "请分别输入字符串a和字符串b:" << endl;

    cin >> a >> b;

    aSize = a.size();  //获取字符串a和b的长度,并求出字符串c的长度

    bSize = b.size();

    cSize = aSize + bSize;

    char* p_char = NULL;  //定义一个指针变量,用于指向动态字符数组

    p_char = new char[cSize + 1];  //动态创建一个字符数组

    if (p_char)  //内存申请成功

    {

        //遍历字符串a中的每个字符

        for (int i = 0; i < aSize; i++)

        {

            p_char[i] = a[i];    //将字符串a复制到字符串c的前半段

        }

        //遍历字符串b中的每个字符

        for (int i = 0; i < bSize; i++)

        {

            p_char[i + aSize] = b[i];  //将字符串b复制到字符串c的后半段

        }

        p_char[cSize] = '\0';  //添加串结束符

        cout << "将字符串b连接到字符串a的后面,变成字符串c:" << endl;

        //打印字符串c

        for (int i = 0; i < cSize; i++)  

        {

            cout << p_char[i];

        }

        delete[]p_char;  //释放p_char所指的存储空间

        p_char = NULL;   //将指针变量置为空,清除其无意义的地址值

    }

    else

    {

        cout << "内存申请出错" << endl;

    }

    return 0;

}

运行结果截图:

心得与体会:

  1. 在该程序中,我结合了string类型字符数组进行编码,使得程序更加直接、简捷。

2、值得注意的是,在动态申请字符数组空间时,应该多预留一位给串结束符\0

实验B结构实验

一、实验目的

1.掌握结构的概念;

2.学会通过结构成员来使用结构;

3.学会通过函数的参数使用结构;

4.学会结构变量成员值的输出。

二、实验设备与平台

1. 实验设备:计算机

2. 平台:Windows操作系统,Microsoft Visual C++或其它合适的C++编程环境。

三、实验内容

1、定义一个结构变量(包括年、月、日),计算该日在本年中为第几天?(注意考虑闰年问题),要求写一个函数days,实现上面的计算。由主函数将年月日传递给days函数,计算后将日子传递回主函数输出。

程序代码:

// 程序设计基础实验3 数组、结构体及指针

// 实验B 结构实验

// 问题描述:

/*1、定义一个结构变量(包括年、月、日),计算该日在本年中为第几天?

(注意考虑闰年问题),要求写一个函数days,实现上面的计算。

由主函数将年月日传递给days函数,计算后将日子传递回主函数输出。*/

#include<iostream>

using namespace std;

#define Month 12

struct Time

{

int year;  //年份

int month; //月份

int day;   //日份

};

//计算该日在本年中为第几天

int days(Time t);

//初始化

void Initial(Time& t);

//输入

void Input(Time& t);

int main()

{

Time t;

Initial(t);  //初始化

Input(t);  //数据输入

//计算该日在本年中为第几天

cout << t.year << "年"<<t.month<<"月" <<t.day<<"日" << "在本年中为第" << days(t) << "天" << endl;

return 0;

}

//初始化

void Initial(Time& t)

{

t.year = t.month = t.day = 0;  //年月日初值均为零

}

//输入

void Input(Time& t)

{

cout << "请输入年:" << endl;

cin >> t.year;

cout << "请输入月:" << endl;

cin >> t.month;

cout << "请输入日:" << endl;

cin >> t.day;

}

//计算该日在本年中为第几天

int days(Time t)

{

int* p_Month = new int[Month];  //动态数组,存储该年的每月的天数

int daysOfYear = 0;  //

if (p_Month)  //内存申请成功

{

//1、3、5、7、8、10、12月均为31天

p_Month[0] = p_Month[2] = p_Month[4] = p_Month[6] = p_Month[7] = p_Month[9] = p_Month[11] = 31;  

//4、6、9、11月均为30天

p_Month[3] = p_Month[5] = p_Month[8] = p_Month[10] = 30;  

//判断该年是否为闰年

if ((t.year % 4 == 0 && t.year % 100 != 0) || t.year % 400 == 0)  //能被4整除但不能被100整除 或 能被400整除的 为闰年

{

p_Month[1] = 29;  //闰年2月有29天

}

else

{

p_Month[1] = 28;  //平年2月有28天

}

//累加该日的月份之前的所有天数

for (int i = 0; i < t.month - 1; i++)  //这里容易发生错误:月份-1 =数组p_Month的下标

{

daysOfYear += p_Month[i];

}

//加上该日,即为该日在本年中为第几天

daysOfYear += t.day;  

}

else  //内存申请失败

{

cout << "内存申请出错!" << endl;

}

delete[]p_Month;  //释放指针所指内存空间

p_Month = NULL;  //将指针的值置为空,清除其无意义的地址值

return daysOfYear;  //返回该年的总天数

}

运行结果截图:

心得与体会:

  1. 在编写程序过程中,又出现了错误。出错原因:月份与程序设计中的数组下标不相等。正确的关系为:月份 - 1 = 数组p_Month的下标

2、编写一个程序,用结构表示一个学生的信息,每个学生的信息包括:学号、姓名、三门成绩。要求从键盘输入学生的数据,并输出成绩表(包括每个学生的学号、姓名、三门成绩及平均分数),并输出平均分在前3名的学生的姓名及平均分。

程序代码:

// 程序设计基础实验3 数组、结构体及指针

// 实验B 结构实验

// 问题描述:

/*2、编写一个程序,用结构表示一个学生的信息,每个学生的信息包括:学号、姓名、三门成绩。

要求从键盘输入学生的数据,

并输出成绩表(包括每个学生的学号、姓名、三门成绩及平均分数),

并输出平均分在前3名的学生的姓名及平均分。*/

#include<iostream>

#include<iomanip>

using namespace std;

struct Student

{

    string code;  //学生学号

    string name;  //学生姓名

    double MT;  //数学成绩

    double EN;  //英语成绩

    double PH;  //物理成绩

    double TotalScore;  //总分

    double AvrScore;    //平均分数

};

//学生信息初始化

void Initial(int num, Student*& p);

//学生信息录入

void Rigister(int num, Student*& p);

//交换函数

template<typename T>

void Swap(T& element1, T& element2);

//按总分成绩排序 冒泡排序

void BubbleSort(int num, Student*& p);

//学生成绩表打印

void DispGradesTable(int num, Student* p);

//打印平均分排名前几的学生相关数据

void DispTop(int numStudent, Student* p);

//释放内存空间

void DeleteSpace(Student*& p);

int main()

{

    int numStudent;

    cout << "请输入学生数量:" << endl;

    cin >> numStudent;

    Student* p_Student = NULL;

    Initial(numStudent, p_Student);  //学生信息初始化

    Rigister(numStudent, p_Student);  //学生信息录入

    DispGradesTable(numStudent, p_Student);  //学生成绩表打印

    BubbleSort(numStudent, p_Student);  //学生成绩排序

    DispTop(numStudent, p_Student);  //求平均分排在前几的学生信息

    DeleteSpace(p_Student);  //释放指针所指空间

    return 0;

}

//学生信息初始化

void Initial(int num, Student*& p)

{

    p = new Student[num];  //动态结构数组

    if (p)  //内存分配成功

    {

        //为数组赋初值

        for (int i = 0; i < num; i++)

        {

            p[i].code = p[i].name = " ";

            p[i].MT = p[i].EN = p[i].PH = p[i].TotalScore = p[i].AvrScore = 0;

        }

    }

    else

    {

        cout << "内存申请出错!" << endl;

    }

}

//学生信息录入

void Rigister(int num, Student*& p)

{

    cout << "请依次输入每位学生的学生编号、学生姓名、数学分数、英语分数、物理分数:" << endl;

    cout << "(注意:输入学生编号后使用按下回车,然后输入学生姓名和分数,姓名与分数、分数与分数之间用空格间隔)" << endl;

    for (int i = 0; i < num; i++)

    {

        cout << "学生编号:";

        cin >> p[i].code;

        bool isExist = 0;

        for (int j = 0; j < i; j++)  //遍历已录入的成绩表

        {

            if (p[i].code == p[j].code)  //当前输入的学生编号已存在于信息表中

            {

                isExist = 1;

                cout << "该学生编号的成绩已录入,无需再次录入" << endl;

                i--;

                cout << "请继续录用下一个学生的成绩" << endl;

                break;

            }

        }

        if (!isExist)  //该学生编号不存在信息表中时,继续录用

        {

            cout << "学生姓名:";

            cin >> p[i].name;

            cout << "数学成绩、英语成绩、物理成绩:";

            cin >> p[i].MT >> p[i].EN >> p[i].PH;  //输入该学生的相关数据

            p[i].TotalScore = p[i].MT + p[i].EN + p[i].PH;  //计算该学生的总分

            p[i].AvrScore = p[i].TotalScore / 3.0;   //计算该学生的平均分

        }

    }

}

//学生成绩表打印

void DispGradesTable(int num, Student* p)

{

    cout << "-------------------------------------------学生成绩表打印-------------------------------------------" << endl;

    cout << "学生编号" << '\t' << "学生姓名" << '\t' << "数学成绩" << '\t' << "英语成绩" << '\t' << "物理成绩" << '\t' << "平均分  " << endl;

    for (int i = 0; i < num; i++)

    {

        cout << p[i].code << '\t' << '\t' << p[i].name << '\t' << '\t' << p[i].MT << '\t' << '\t' << p[i].EN << '\t' << '\t' << p[i].PH

            << '\t' << '\t' << setprecision(4) << p[i].AvrScore << endl;

    }

    cout << "------------------------------------------学生成绩表分割线------------------------------------------" << endl;

}

//打印平均分排名前几的学生相关数据

void DispTop(int numStudent, Student* p)

{

    int n = 0;

    cout << "请输入需要打印前几名的学生信息:" << endl;

cin >> n;

    //判断总学生数是大于需要求的排名前几的学生

    if (n > numStudent)  //学生数较少时,只能打印出所有学生的信息

    {

        cout << "仅有" << numStudent << "名学生,只能打印出排名前" << numStudent << "的学生信息" << endl;

        cout << "---------------------------------------排名前" << numStudent << "的学生信息打印--------------------------------------- " << endl;

        cout << "学生姓名" << '\t' << "平均分  " << endl;

        for (int i = 0; i < numStudent; i++)

        {

            cout << p[i].name << '\t' << '\t' << fixed << setprecision(2) << p[i].AvrScore << endl;

        }

    }

    else  //学生数较多时,可以打印出所需的前几的学生的信息

    {

        cout << "---------------------------------------排名前" << n << "的学生信息打印--------------------------------------- " << endl;

        cout << "学生姓名" << '\t' << "平均分  " << endl;

        for (int i = 0; i < n; i++)

        {

            cout << p[i].name << '\t' << '\t' << fixed << setprecision(2) << p[i].AvrScore << endl;

        }

    }

    cout << "-----------------------------------------------分割线-----------------------------------------------" << endl;

}

//交换函数:函数模板

template<typename T>

void Swap(T& element1, T& element2)

{

    T temp;

    temp = element1;

    element1 = element2;

    element2 = temp;

}

//按总分成绩排序 冒泡排序

void BubbleSort(int num, Student*& p)

{

    int i, j;

    bool exchange;

    for (i = 0; i < num - 1; i++)

    {

        exchange = false;                 //判别因子

        for (j = num - 1; j > i; j--)

            if (p[j].TotalScore > p[j - 1].TotalScore)  //相邻元素反序时

            {

                Swap(p[j].code, p[j - 1].code);              //将学生编号中的两元素交换

                Swap(p[j].name, p[j - 1].name);              //将学生姓名中的两元素交换

                Swap(p[j].TotalScore, p[j - 1].TotalScore);  //将总分中的两元素交换

                Swap(p[j].AvrScore, p[j - 1].AvrScore);      //将平均分中的两元素交换

                Swap(p[j].MT, p[j - 1].MT);                  //将数学分数中的两元素交换

                Swap(p[j].EN, p[j - 1].EN);                  //将英语分数中的两元素交换

                Swap(p[j].PH, p[j - 1].PH);                  //将物理分数中的两元素交换

                exchange = true;

            }

        if (!exchange)                   //本趟没有发生交换,结束算法

            break;

    }

}

//释放内存空间

void DeleteSpace(Student*& p)

{

    delete[]p;  //释放指针所指的内存空间

    p = NULL;  //将指针变量赋NULL值,以清除其无意义的地址值

}

运行结果截图:

案例1:(正确运行结果)

案例2:(输入出错检测)

心得与体会:

  1. 该题目与本实验中的实验A第一题相似,第一题我用了很多个数组的方式,分别存储学生编号、学生姓名、学生成绩。而本题中采用结构体,极大提高了编码的扩展性。当需要添加多一个科目的成绩时,我不再需要添加一个该科目成绩的数组,而只需在结构体中添加多一个属性
  2. 题目中隐含了一个条件,当班级学生只有2名时,查询平均分前三的同学信息时,应只输出2名,而无法输出3名。这是在编程中容易搞错的、忽略的。
  3. 在编写录入学生信息的函数时,没有使用结构指针的引用。这导致数据没有办法录入。所以在一些需要更改、写入操作的函数编写时,需要注意参数是否设置为引用。

实验C 指针实验

一、实验目的

1.掌握指针的概念;

2.学会通过指针处理普通变量和一维数组;

3.学会通过指针处理动态分配的内存;

4.学会将一个问题提炼出数学模型,学会利用数学模型编写程序的方法。

二、实验设备与平台

1. 实验设备:计算机

2. 平台:Windows操作系统,Microsoft Visual C++或其它合适的C++编程环境。

三、实验内容

1、 要求使用指针处理下面的问题,输入四个整数,按由小到大的顺序输出;然后将程序改为:输入四个字符串,按由小到大顺序输出。(使用指针或指针数组)

程序代码:

// 程序设计基础实验3 数组、结构体及指针

// 实验C 指针实验

// 问题描述:

/*1、要求使用指针处理下面的问题,输入四个整数,按由小到大的顺序输出;

然后将程序改为:输入四个字符串,按由小到大顺序输出。(使用指针或指针数组)*/

#include <iostream>

using namespace std;

#define N 4  //定义需要输入的个数

//数据输入

template<typename T>

void input(int num, T* p);

//元素交换

template<typename T>

void Swap(T& element1, T& element2);

// 对整数数组进行排序

void BubbleSort_Int(int num, int* p);

// 对字符串数组进行排序

void BubbleSort_string(int num, string* p);

//排序结果打印

template<typename T>

void Disp(int num, T* p);

int main()

{

    int* p_Int = new int[N];

    string* p_String = new string[N];

    if (p_Int && p_String)  //内存申请成功

    {

        //整数输入

        cout << "请输入需要排序的" << N << "个整数:" << endl;

        input(N, p_Int);

        //字符串输入

        cout << "请输入需要排序的" << N << "个字符串:" << endl;

        input(N, p_String);

        //排序

        BubbleSort_Int(N, p_Int);

        BubbleSort_string(N, p_String);

        //打印由小到大排序后的结果

        cout << N << "个整数由小到大排序后的结果为:" << endl;

        Disp(N, p_Int);

        cout << N << "个字符串由小到大排序后的结果为:" << endl;

        Disp(N, p_String);

        delete[]p_Int;  //释放指针所指的空间

        delete[]p_String;

        p_Int = NULL;  //将指针置为空,清除其无意义的地址值

        p_String = NULL;

    }

    else  //内存申请失败

    {

        cout << "内存申请出错!" << endl;

    }

    return 0;

}

//数据输入

template<typename T>

void input(int num, T* p)

{

    for (int i = 0; i < N; i++)

    {

        cin >> p[i];

    }

}

//元素交换

template<typename T>

void Swap(T& element1, T& element2)

{

    T temp = element1;

    element1 = element2;

    element2 = temp;

}

// 对整数数组进行排序小到大排序  传入一个指针参数,并通过指针(间址)运算来操作

void BubbleSort_Int(int num, int* p)

{

    int i, j;

    bool exchange;

    for (i = 0; i < num - 1; i++)

    {

        exchange = false;  //判别因子

        for (j = num - 1; j > i; j--)

        {

            if (*(p+j - 1) > *(p+j))  //相邻元素反序时

            {

                Swap(*(p + j - 1), *(p + j));  //将这两个元素进行交换

                exchange = true;

            }

        }

        if (!exchange)  //本趟没有发生交换,结束排序算法

            break;

    }

}

// 对字符串数组进行排序小到大排序

void BubbleSort_string(int num, string* p)

{

    int i, j;

    bool exchange;

    for (i = 0; i < num - 1; i++)

    {

        exchange = false;  //判别因子

        for (j = num - 1; j > i; j--)

        {

            if ((*(p + j - 1)).size() > (*(p + j)).size())  //相邻字符串长度反序时

            {

                Swap(*(p + j - 1), *(p + j));  //将这两个元素进行交换

                exchange = true;

            }

        }

        if (!exchange)  //本趟没有发生交换,结束排序算法

            break;

    }

}

//排序结果打印

template<typename T>

void Disp(int num, T* p)

{

    for (int i = 0; i < N; i++)

    {

        cout << p[i] << " ";

    }

    cout << endl;

}

运行结果截图:

心得与体会:

  1. 在平时写代码中,我较少地用到间址操作,而是用数组形式来写入数据、修改数据。在本次题目中,我在冒泡排序中用指针的间址操作来写,一开始还有点不习惯,但其实就是通过首地址加上移动单位,再添加间址运算符*
  2. 在设计代码过程中,我发现整数排序和字符串排序,它们的排序算法略微不同。整数排序中,我们仅需要比较两元素的大小,而在字符串排序中,我们需要比较两字符串的长度
  3. 我利用泛化程序设计中的函数模板来写整数、字符串的写入和排序结果的打印。这样子大大减少了代码量,增强了程序的扩展性。

2、 通过指针动态存储处理下面的问题:利用随机函数模拟产生300个1~12月出生的人数,统计本次运行得到的数据中,各个月的出生率是多少。

程序代码:

// 程序设计基础实验3 数组、结构体及指针

// 实验C 指针实验

// 问题描述:

/*2、通过指针和动态存储处理下面的问题:利用随机函数模拟产生300个1~12月出生的人数,

统计本次运行得到的数据中,各个月的出生率是多少。*/

#include<iostream>

#include<stdlib.h>  // 包含两个头文件,用于设置随机数

#include<time.h> 

#include<iomanip>  //用于格式控制的头文件

using namespace std;

int main()

{

    int* p_birthMonth = new int[12];  //动态分配一个包含12个整数的数组,用于存储每个月的出生人数

    srand(time(nullptr));  // 设置随机数种子

    

    //数组初始化

    for (int i = 0; i < 12; i++)

    {

        p_birthMonth[i] = 0;  //初始化每月出生人口为零

    }

    //模拟生成300个1~12月出生的人数

    for (int i = 0; i < 300; i++)

    {

        int birthMonth = 1 + rand() % (12 - 1 + 1);   //产生一个1~12之间的随机数,表示出生月份

        p_birthMonth[birthMonth - 1]++;  //对应月份的出生人口+1   注意:这里容易发生出错,月份为1存储于下标为0元素中

    }

    //计算各个月份的出生率

    for (int i = 0; i < 12; i++)

    {

        double birthMonthRate = (p_birthMonth[i] / 300.0) * 100;  //计算出生率

        cout << i + 1 << "月份的出生率为:" <<fixed << setprecision(2) << birthMonthRate << "%" << endl;  //打印出生率结果

    }

    delete[]p_birthMonth;  //释放动态分配的内存

    p_birthMonth = NULL;   //将指针变量置为空,清除其无意义的地址值

    return 0;

}

运行结果截图:

心得与体会:

1、在使用数组时,要把握好数组下标与某个变量之间的关系。例如,在本题中,数组下标与月份的关系为:下标 = 月份-1。这是在写程序中容易出错的。

最近更新

  1. TCP协议是安全的吗?

    2024-05-13 19:02:04       16 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-05-13 19:02:04       16 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-05-13 19:02:04       15 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-05-13 19:02:04       18 阅读

热门阅读

  1. 特殊类的设计与单例模式

    2024-05-13 19:02:04       14 阅读
  2. 网络工程师----第二十六天

    2024-05-13 19:02:04       12 阅读
  3. 计算机组成与结构 计算机基本原理 软设刷题

    2024-05-13 19:02:04       15 阅读
  4. 面试被问ThreadLocal要怎么回答?

    2024-05-13 19:02:04       11 阅读
  5. 蓝桥杯备战8.快乐的跳

    2024-05-13 19:02:04       12 阅读
  6. MySQL中的事务隔离级别

    2024-05-13 19:02:04       10 阅读
  7. 每个工作室都需要的10种插件类型

    2024-05-13 19:02:04       13 阅读