计算与人工智能概论-问题求解、科学计算与AI应用方法 课件 第8章 结构体_第1页
计算与人工智能概论-问题求解、科学计算与AI应用方法 课件 第8章 结构体_第2页
计算与人工智能概论-问题求解、科学计算与AI应用方法 课件 第8章 结构体_第3页
计算与人工智能概论-问题求解、科学计算与AI应用方法 课件 第8章 结构体_第4页
计算与人工智能概论-问题求解、科学计算与AI应用方法 课件 第8章 结构体_第5页
已阅读5页,还剩65页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

计算与人工智能概论问题求解、科学计算与AI应用方法第8章结构体信息科学与工程学院任务1:自定义类型描述炮弹坐标

任务2:将基本参数封装进结构体

任务3:将炮弹轨迹存入结构数组

任务4:根据不同的要求计算轨迹

任务5:将轨迹计算功能设计为成员函数

目录任务1:自定义类型描述炮弹坐标回顾前面章节的程序通过两个独立的浮点型变量x和y分别表示炮弹在某一时刻的水平和垂直坐标。将原本具有紧密联系的坐标信息拆分为两个独立的变量,割裂了横纵坐标之间的整体性与逻辑关联,不利于数据的统一管理与后续扩展怎么解决这个问题——引入结构体任务1:自定义类型描述炮弹坐标任务描述本任务要求使用C语言中的结构体(struct)机制,定义一个名为Position的自定义数据类型,用于将横坐标和纵坐标封装为一个有机整体。该结构体包含两个成员变量,分别表示x和y坐标值。同时,需要修改原有的坐标计算函数,使其返回类型为Position,从而在函数调用后直接获得一个完整的坐标点1、结构体的定义2、结构体变量3、结构体变量的使用结构体的定义与使用任务1:自定义类型描述炮弹坐标1、结构体的定义在C语言中,使用关键字struct来定义结构体。结构体的定义语法如下:结构体的定义与使用任务1:自定义类型描述炮弹坐标struct结构体名{

数据类型

成员1;

数据类型

成员2;...};structPosition{doublex;doubley;};2、结构体变量定义结构体后声明该类型的变量结构体的定义与使用任务1:自定义类型描述炮弹坐标structPosition{doublex;doubley;};structPositionpoint1,point2;也可以在定义结构体的同时声明变量:structPosition{doublex;doubley;}point1,point2;2、结构体变量还可以使用typedef为结构体定义别名,简化变量声明:typedefstruct{doublex;doubley;}Position;Positionpoint;Position就可以直接作为数据类型使用,不再需要struct关键字

结构体的定义与使用任务1:自定义类型描述炮弹坐标3、结构体变量的使用结构体变量可以像普通变量一样进行赋值、访问和操作。访问结构体成员使用点号(.)运算符,格式为:结构体变量名.成员名

point.x=3.0;point.y=4.0;结构体的定义与使用任务1:自定义类型描述炮弹坐标也可以在定义结构体变量时进行初始化:Positionpoint={3.0,4.0};结构体变量之间也可以进行整体赋值:Positionpoint1={3.0,4.0};Positionpoint2=point1;//将point1的值复制给point2结构体的定义与使用任务1:自定义类型描述炮弹坐标结构体在实际编程中非常有用,特别是在处理具有多个属性的数据时,如学生信息、图形坐标、日期时间等。例如,定义一个表示学生的结构体:typedefstruct{charname[50];intage;doublescore;}Student;Studentstu1={"张三",20,88.5};这样可以将学生的多个信息组织在一起,提高代码的可读性和可维护性。任务1:自定义类型描述炮弹坐标任务描述定义一个名为Position的自定义数据类型,该结构体包含两个成员变量,分别表示x和y坐标值。修改原有的坐标计算函数,使其返回类型为Position,从而在函数调用后直接获得一个完整的坐标点。具体实现?任务1:自定义类型描述炮弹坐标代码实现00#include<stdio.h>01#include<math.h>02#definePI3.1415926503#defineg9.804typedefstruct{05doublex;06doubley;07}Position;08PositionComputePos(doublev0,doubletheta,doublet){09Positionpos;10pos.x=v0*cos(theta)*t;//计算炮弹的横坐标11pos.y=v0*sin(theta)*t-0.5*g*t*t;//计算炮弹的纵坐标12returnpos;13}14intmain(){15doublev0=50.0;//初速度m/s16doubletheta=45.0*(PI/180.0);//角度弧度17doublet;//时间18doublet_max=(2.0*v0*sin(theta))/g;//计算炮弹的落地时间;19for(t=0;t<=t_max;t+=0.1){20Positionpos=ComputePos(v0,theta,t);//计算炮弹的坐标21printf("炮弹在时间%.2lf秒时的坐标为:(%.2f,%.2f)\n",t,pos.x,pos.y);22}23return0;24}任务1:自定义类型描述炮弹坐标

任务2:将基本参数封装进结构体

任务3:将炮弹轨迹存入结构数组

任务4:根据不同的要求计算轨迹

任务5:将轨迹计算功能设计为成员函数

目录任务2:基本参数封装到结构体任务描述具体要求是:1定义Position结构体用于表示炮弹的坐标;2定义另一个新的结构体类型(例如命名为ShellState),用于封装炮弹的所有状态信息,包括初速度v0、发射角度theta(单位为度)、当前时间t、当前坐标pos(即Position类型的成员),将原本作为函数参数传入的多个独立变量,统一为一个ShellState类型的结构体变量(或其指针);3修改坐标计算函数,使其接收ShellState类型的参数(或指针),并根据其中的v0、theta和t计算出对应的坐标值,保存在结构体的pos成员中;4函数可以返回更新后的结构体变量,或者通过指针修改传入的结构体,实现状态的更新;5最后在主函数中创建ShellState类型的变量,调用函数并输出计算后的坐标信息。1、结构体的嵌套2、结构指针结构的嵌套与结构指针任务2:基本参数封装到结构体1、结构体的嵌套单一结构体往往无法满足复杂数据模型的表达需求,为了更真实、更完整地描述现实世界中的对象和关系,C语言允许将一个结构体作为另一个结构体的成员,这种机制称为结构的嵌套。结构的嵌套是指在一个结构体中包含另一个结构体类型的成员。结构的嵌套与结构指针任务2:基本参数封装到结构体1、结构体的嵌套结构的嵌套与结构指针任务2:基本参数封装到结构体定义了一个表示坐标点的结构体Position:typedefstruct{doublex;doubley;}Position;可以定义另一个结构体ShellState,它包含了Position类型的成员pos,用于表示炮弹的当前坐标:

typedefstruct{doublev0;//初速度doubletheta;//发射角度(弧度)doublet;//当前时间(秒)Positionpos;//当前坐标}ShellState;1、结构体的嵌套结构的嵌套与结构指针任务2:基本参数封装到结构体typedefstruct{doublev0;//初速度doubletheta;//发射角度(弧度)doublet;//当前时间(秒)Positionpos;//当前坐标}ShellState;访问嵌套结构体成员时,使用连续的点号(.)操作符:

ShellStatestate;state.pos.x=100.0;state.pos.y=50.0;2、结构指针结构的嵌套与结构指针任务2:基本参数封装到结构体ShellState结构体为例:typedefstruct{doublev0;doubletheta;doublet;Positionpos;}ShellState;声明一个结构体变量和一个指向它的指针:ShellStatestate;ShellState*ptr=&state;要访问state中的成员v0,可以使用点号操作符:state.v0=50.0;但如果使用指针ptr,就必须使用->操作符:ptr->v0=50.0;等价于:(*ptr).v0=50.0;2、结构指针当结构体较大时,作为函数参数进行值传递会导致较大的性能开销,因为整个结构体都会被复制一份。为了提高效率,C语言中通常使用结构指针来操作结构体变量。结构指针是指向结构体类型的指针变量。结构的嵌套与结构指针任务2:基本参数封装到结构体指针变量->成员名ptr->member等价于:(*ptr).member代码实现任务2:基本参数封装到结构体00#include<stdio.h>01#include<math.h>02#definePI3.1415926503#defineg9.804typedefstruct{05doublex;06doubley;07}Position;08typedefstruct{09doublev0;10doubletheta;11doublet;12Positionpos;//pos是一个指向Position的指针13}ShellState;14voidComputePos(ShellState*pstate){15pstate->pos.x=pstate->v0*cos(pstate->theta)*pstate->t;//横坐标16pstate->pos.y=pstate->v0*sin(pstate->theta)*pstate->t-0.5*g*pstate->t*pstate->t;//纵坐标17}18intmain(){19ShellStatestate;20state.v0=50.0;//初速度m/s21state.theta=45.0*(PI/180.0);//角度弧度22doublet_max=(2.0*state.v0*sin(state.theta))/g;//计算炮弹的落地时间;23for(doublet=0;t<=t_max;t+=0.1){24state.t=t;//设置当前时间25ComputePos(&state);//计算炮弹的坐标26printf("炮弹在时间%.2lf秒时的坐标为:(%.2f,%.2f)\n",state.t,state.pos.x,state.pos.y);27}28return0;29}任务1:自定义类型描述炮弹坐标

任务2:将基本参数封装进结构体

任务3:将炮弹轨迹存入结构数组

任务4:根据不同的要求计算轨迹

任务5:将轨迹计算功能设计为成员函数

目录任务3:将炮弹轨迹存入结构数组任务描述在第6章的任务1中,程序使用两个独立的一维数组分别存储炮弹在不同时间点的横坐标和纵坐标。这种方式虽然能够实现对弹道轨迹的基本记录和访问,但将原本具有内在联系的坐标信息分散在两个不同的数组中,不利于数据的统一管理和逻辑表达,也降低了程序的可读性和扩展性。本任务在此基础上提出改进要求,使用C语言中的结构体机制,设计一个元素类型为Position的数组,用于统一存储炮弹在多个时间点的坐标信息。其中,Position类型是一个包含x和y两个成员的结构体,能够完整地表示一个二维坐标点。最后,用循环遍历该数组并输出轨迹信息。任务3:将炮弹轨迹存入结构数组结构数组定义与使用1、结构数组的定义2、结构数组的遍历3、用指针遍历结构数组任务3:将炮弹轨迹存入结构数组结构数组定义与使用1、结构数组的定义构数组的定义方式与基本数据类型的数组类似,只是其元素类型为结构体。定义结构数组前定义结构体类型。先定义表示坐标的结构体:typedefstruct{doublex;doubley;}Position;然后定义一个包含100个元素的Position类型数组:Positiontrajectory[100];这表示定义了一个名为trajectory的结构数组,它最多可以保存100个坐标点。任务3:将炮弹轨迹存入结构数组结构数组定义与使用1、结构数组的定义结构数组的定义为统一存储和操作具有相同结构的数据提供了便利,是处理轨迹、记录、表格等数据的有效方式。结构数组每个元素都可以像普通结构体变量一样进行访问和赋值。例如:trajectory[0].x=10.0;trajectory[0].y=5.0;任务3:将炮弹轨迹存入结构数组结构数组定义与使用2、结构数组的遍历结构数组的遍历是指通过循环依次访问数组中的每一个结构体元素,常用于批量处理数据通过一个for循环,计算并存储炮弹在不同时刻的坐标Positiontrajectory[100];doublev0=50.0,theta=M_PI/4,g=9.8;for(inti=0;i<100;i++){doublet=i*0.1;//每0.1秒计算一次trajectory[i].x=v0*cos(theta)*t;trajectory[i].y=v0*sin(theta)*t-0.5*g*t*t;}任务3:将炮弹轨迹存入结构数组结构数组定义与使用3、指针遍历结构数组除了使用下标访问结构数组,还可以使用结构指针来遍历数组,这种方式在处理大型结构体数组时效率更高,也更符合C语言的底层操作风格。//使用指针遍历结构数组Position*p=&trajectory[0];for(inti=0;i<100;i++){printf("t=%.1f秒:x=%.2f米,y=%.2f米\n",i*0.1,p->x,p->y);p++;//指针移动到下一个结构体元素}任务3:将炮弹轨迹存入结构数组具体设计设计一个Position类型的数组positions,直接作为ShellState结构体的成员,用于集中存储炮弹在不同时刻的坐标数据,而将初速度和发射角度作为结构体中仅需存储一次的成员变量。这样可以避免重复存储,提高内存使用效率,同时保持良好的程序结构。(1)定义结构体Position,包含以下成员:doublex:炮弹的横坐标;doubley:炮弹的纵坐标;doublet:对应的时间(单位为秒);(2)定义结构体ShellState,包含以下成员:doublev0:炮弹的初速度;doubletheta:发射角度(单位为弧度);intcount:表示轨迹点的总数;Positionpositions[100]:用于存储炮弹在不同时刻的坐标信息;(3)程序通过结构体ShellState统一管理炮弹的运动参数和轨迹数据;(4)使用函数ComputePos计算每个时间点的坐标和时间,并将结果依次存入positions数组;(5)最后程序遍历positions数组,输出完整的弹道轨迹信息,包括时间、横坐标和纵坐标。

任务3:将炮弹轨迹存入结构数组程序流程程序的功能:通过结构数组记录炮弹在不同时刻的坐标,并输出完整的弹道轨迹信息。Step1:定义物理常量PI和g,分别表示圆周率和重力加速度;Step2:定义结构体类型Position,包含三个成员x、y和t,表示炮弹在某一时刻的坐标和时间;Step3:定义结构体类型ShellState,包含初速度v0、发射角度theta、时间步数count,以及一个Position类型的数组positions[100],用于存储轨迹点;Step4:定义函数ComputePos,接收一个ShellState类型的指针和当前时间t,根据物理公式计算炮弹在该时刻的坐标,并将结果保存到positions数组中;Step5:在main函数中初始化ShellState结构体变量,设置初速度v0和发射角度theta,并将其转换为弧度制;Step6:根据物理公式计算炮弹的总飞行时间t_max,并确定时间步长为0.1秒,从而计算出轨迹点总数count;Step7:使用循环依次调用ComputePos函数,计算并保存每个时间点的坐标和时间到positions数组中;Step8:再次使用循环遍历positions数组,依次输出每个时间点的t、x和y值;Step9:最后输出记录的总时间点数count,表示炮弹飞行的总时间步数。任务3:将炮弹轨迹存入结构数组代码实现#include<stdio.h>#include<math.h>#definePI3.14159265#defineg9.8#defineMAX_POINTS100//最大轨迹点数//定义表示坐标的结构体,并增加时间ttypedefstruct{doublex;doubley;doublet;//时间}Position;//定义炮弹状态结构体,包含轨迹数组typedefstruct{doublev0;//初速度doubletheta;//发射角度(弧度制)intcount;//轨迹点数量Positionpositions[MAX_POINTS];//轨迹坐标数组}ShellState;//计算某一时刻的坐标并保存到结构体数组中voidComputePos(ShellState*pstate,doublet){if(pstate->count<MAX_POINTS){//确保不超过最大轨迹点数pstate->positions[pstate->count].x=pstate->v0*cos(pstate->theta)*t;//计算炮弹的横坐标pstate->positions[pstate->count].y=pstate->v0*sin(pstate->theta)*t-0.5*g*t*t;//计算炮弹的纵坐标pstate->positions[pstate->count].t=t;//保存当前时间pstate->count++;}}intmain(){ShellStateshell;shell.v0=50.0;//初速度shell.theta=45.0*(PI/180.0);//发射角度转换为弧度shell.count=0;//初始化轨迹点数为0doublet=0.0;//当前时间doublet_max=(2.0*shell.v0*sin(shell.theta))/g;//总飞行时间

//循环计算每个时间点的坐标while(t<=t_max&&shell.count<MAX_POINTS){ComputePos(&shell,t);t+=0.1;//时间步长为0.1秒}//输出所有轨迹点for(inti=0;i<shell.count;i++){printf("炮弹在时间%.2lf秒时的坐标为:(%.2lf,%.2lf)\n",shell.positions[i].t,shell.positions[i].x,shell.positions[i].y);}printf("轨迹点总数为%d\n",shell.count);return0;}任务1:自定义类型描述炮弹坐标

任务2:将基本参数封装进结构体

任务3:将炮弹轨迹存入结构数组

任务4:根据不同的要求计算轨迹

任务5:将轨迹计算功能设计为成员函数

目录任务4:根据不同的要求计算轨迹任务描述功能需求:(1)程序应支持两种发射模式:按角度发射:用户指定初速度和发射角度,程序根据物理公式计算炮弹的轨迹;按最大射程发射:用户指定一个期望的射程(即炮弹落地时的水平距离),程序自动设定发射角度为45°(此时射程最大),并据此反推出所需的初速度,再计算弹道轨迹;(2)在程序中,应能方便地设置发射模式,并根据该模式进行相应的参数解析和轨迹计算;(3)程序仍使用结构数组来统一存储炮弹在不同时刻的轨迹信息,每个数组元素应能记录当前轨迹点所使用的发射模式及相关参数;(4)最后,程序应能遍历结构数组,输出每个轨迹点的时间和坐标信息,并标明其所属的发射模式。任务4:根据不同的要求计算轨迹枚举(enum)和联合(union)在C语言中,枚举(enum)和联合(union)是两种重要的复合数据类型,它们虽然不像结构体那样广泛使用,但在特定场景下具有不可替代的作用。枚举用于定义一组具有命名的整型常量,适用于表示有限的状态或选项。联合则是一种特殊的结构体,多个成员共享同一块内存空间,适用于需要节省内存或根据运行状态动态选择数据类型的场景。任务4:根据不同的要求计算轨迹枚举(enum)枚举的定义枚举是一种用户自定义的数据类型,其变量只能取一组预定义的整型值。这些值通常用于表示状态、模式、选项等具有固定集合的值。枚举的定义格式如下:enum枚举名{

枚举常量1,

枚举常量2,...};enumColor{RED,GREEN,BLUE};RED的默认值为0,GREEN为1,BLUE为2enumColor{RED=1,GREEN=2,BLUE=4};也可以为枚举常量显式赋值:任务4:根据不同的要求计算轨迹枚举(enum)枚举的使用枚举变量的声明和使用方式与基本数据类型类似:enumColorc=RED;if(c==GREEN){printf("颜色是绿色\n");}为了提高代码的可读性,通常使用typedef将枚举类型定义为新的类型名:typedefenum{BY_ANGLE,BY_MAX_RANGE}LaunchMode;这样可以直接声明变量:LaunchModemode=BY_ANGLE;任务4:根据不同的要求计算轨迹联合(union)联合的定义联合(Union)是一种复合数据类型,其所有成员共享同一块内存空间。这意味着,在某一时刻,联合只能保存其中一个成员的值。联合的定义格式如下:union联合名{

数据类型成员1;

数据类型成员2;...};unionData{inti;doublef;charstr[20];};i、f和str共享同一块内存空间,其大小等于最大成员的大小任务4:根据不同的要求计算轨迹联合(union)联合的使用联合变量的声明方式如下:unionDatadata;data.i=10;printf("data.i=%d\n",data.i);//输出10data.f=3.14;printf("data.f=%f\n",data.f);//输出3.14printf("data.i=%d\n",data.i);//输出不确定值1374389535,因为f覆盖了i的内存可以看到,当对一个成员赋值后,再次对另一个成员赋值,会导致前一个成员的值被覆盖。任务4:根据不同的要求计算轨迹枚举和联合实现两种发射模式任务4要求对炮弹轨迹模拟程序进行功能扩展,使其支持两种发射模式,并根据当前模式计算相应的弹道轨迹。为了清晰地表达发射模式并高效地管理模式相关的参数,可以引入枚举和联合这两种数据结构。1.使用枚举描述发射模式2.使用联合描述发射参数任务4:根据不同的要求计算轨迹枚举和联合实现两种发射模式1.使用枚举描述发射模式任务4中要求程序支持两种发射模式:按角度发射(BY_ANGLE):用户指定初速度和发射角度;按最大射程发射(BY_MAX_RANGE):用户指定一个期望的射程,程序自动设定发射角度为45°,并反推出所需的初速度。为了清晰地表达这两种模式,可以使用枚举类型来表示:typedefenum{BY_ANGLE,//按角度发射BY_MAX_RANGE//按最大射程发射}LaunchMode;任务4:根据不同的要求计算轨迹枚举和联合实现两种发射模式2.使用联合描述发射参数按角度发射:需要初速度v0和发射角度theta;按最大射程发射:需要最大射程range,而发射角度固定为45°,初速度根据射程反推得出。为了统一管理这些参数,可以设计一个联合类型:typedefunion{doubletheta;//发射角度(弧度)doublerange;//最大射程}LaunchParam;任务4:根据不同的要求计算轨迹枚举和联合实现两种发射模式3.在ShellState结构体中使用typedefstruct{

LaunchModemode;//发射模式LaunchParamparam;//模式相关参数doublev0;//初速度

doubletheta;//实际发射角度intcount;//轨迹点数量Positionpositions[MAX_POINTS];//轨迹数组}ShellState;任务4:根据不同的要求计算轨迹枚举和联合实现两种发射模式3.在ShellState结构体中使用在初始化结构体时,根据当前模式设置联合成员的值,例如:shell.mode=BY_ANGLE;在轨迹计算函数中,根据发射模式选择联合中的参数:if(shell.mode==BY_ANGLE){shell.theta=shell.param.theta;}elseif(shell.mode==BY_MAX_RANGE){shell.v0=sqrt(shell.param.range*g);//根据最大射程反推初速度shell.theta=PI/4.0;//自动设置为45度}任务4:根据不同的要求计算轨迹程序流程Step1:定义物理常量PI和g,分别表示圆周率和重力加速度;Step2:定义结构体类型Position,包含三个成员x、y和t,表示炮弹在某一时刻的横坐标、纵坐标和时间;Step3:定义枚举类型LaunchMode,包含两个枚举常量:BY_ANGLE(按角度发射)和BY_MAX_RANGE(按最大射程发射);Step4:定义联合类型LaunchParam,包含两个成员:theta(发射角度)和range(最大射程),用于根据当前发射模式存储不同的参数;Step5:定义结构体类型ShellState,包含以下成员:-LaunchModemode:当前发射模式;-LaunchParamparam:发射模式相关的参数(使用联合);-doublev0:炮弹的初速度;-intcount:记录轨迹点的总数;-Positionpositions[100]:用于存储炮弹在不同时刻的坐标和时间信息;Step6:定义函数ComputePos,接收一个ShellState类型的指针,根据当前发射模式选择参数并计算该时刻的坐标,将结果保存到positions数组中;Step7:在main函数中初始化ShellState结构体变量,设置发射模式(如BY_ANGLE或BY_MAX_RANGE),并根据模式设置对应的参数(角度或射程);Step8:根据物理公式计算炮弹的总飞行时间t_max,并确定时间步长为0.1秒,从而计算出轨迹点总数count;Step9:使用循环依次调用ComputePos函数,计算并保存每个时间点的坐标和时间到positions数组中;Step10:再次使用循环遍历positions数组,依次输出每个时间点的t、x、y以及当前轨迹点所使用的发射模式(如“按角度发射”或“按最大射程发射”);Step11:最后输出记录的总时间点数count,表示炮弹飞行的总时间步数。任务4:根据不同的要求计算轨迹代码实现//定义表示坐标的结构体,包含时间ttypedefstruct{doublex,y,t;}Position;//定义发射模式的枚举类型typedefenum{BY_ANGLE,//按角度发射BY_MAX_RANGE//按最大射程发射}LaunchMode;//定义发射参数的联合类型typedefunion{doubletheta;//发射角度(弧度)doublerange;//最大射程(米)}LaunchParam;//定义炮弹状态结构体,包含发射模式、参数和轨迹数组typedefstruct{LaunchModemode;//当前发射模式LaunchParamparam;//模式相关参数(使用联合)doublev0;//初速度(m/s)doubletheta;//实际发射角度(弧度),用于轨迹计算intcount;//轨迹点数量Positionpositions[MAX_POINTS];//轨迹坐标数组}ShellState;任务4:根据不同的要求计算轨迹代码实现//计算某一时刻的坐标并保存到结构体数组中voidComputePos(ShellState*pstate,doublet){if(pstate->count>=MAX_POINTS)return;//防止数组越界//根据发射模式设置实际的v0和thetaif(pstate->mode==BY_ANGLE){pstate->theta=pstate->param.theta;//v0已在main中设置}elseif(pstate->mode==BY_MAX_RANGE){//最大射程公式:R=v0^2/g=>v0=sqrt(R*g)pstate->v0=sqrt(pstate->param.range*g);pstate->theta=PI/4.0;//45度,射程最大}//计算当前时刻的坐标pstate->positions[pstate->count].x=pstate->v0*cos(pstate->theta)*t;pstate->positions[pstate->count].y=pstate->v0*sin(pstate->theta)*t-0.5*g*t*t;pstate->positions[pstate->count].t=t;pstate->count++;}任务4:根据不同的要求计算轨迹代码实现intmain(){ShellStateshell;shell.count=0;//初始化轨迹点数量//========================//示例1:按最大射程发射//========================shell.mode=BY_MAX_RANGE;shell.param.range=100.0;//用户期望射程为100米shell.v0=0;//初速度将在ComputePos中计算doublet=0.0;//先调用一次ComputePos设置v0和thetaComputePos(&shell,0.0);//计算总飞行时间doublet_max=(2.0*shell.v0*sin(shell.theta))/g;//循环计算轨迹点while(t<=t_max&&shell.count<MAX_POINTS){ComputePos(&shell,t);t+=0.1;}//输出轨迹信息printf("===发射模式:按最大射程发射(目标射程%.2lf米)===\n",shell.param.range);for(inti=0;i<shell.count;i++){printf("时间%.2lf秒:坐标(%.2lf,%.2lf)\n",shell.positions[i].t,shell.positions[i].x,shell.positions[i].y);}printf("共记录%d个轨迹点。\n\n",shell.count);任务4:根据不同的要求计算轨迹代码实现//========================//示例2:按角度发射//========================//重置状态ShellStateshell2;shell2.mode=BY_ANGLE;shell2.param.theta=60.0*(PI/180.0);//60度shell2.v0=40.0;//初速度40m/sshell2.count=0;t=0.0;//获取初始参数ComputePos(&shell2,0.0);t_max=(2.0*shell2.v0*sin(shell2.theta))/g;while(t<=t_max&&shell2.count<MAX_POINTS){ComputePos(&shell2,t);t+=0.1;}//输出轨迹信息printf("===发射模式:按角度发射(%.1lf°,%.1lfm/s)===\n",shell2.param.theta*180.0/PI,shell2.v0);for(inti=0;i<shell2.count;i++){printf("时间%.2lf秒:坐标(%.2lf,%.2lf)\n",shell2.positions[i].t,shell2.positions[i].x,shell2.positions[i].y);}printf("共记录%d个轨迹点。\n",shell2.count);return0;}任务1:自定义类型描述炮弹坐标

任务2:将基本参数封装进结构体

任务3:将炮弹轨迹存入结构数组

任务4:根据不同的要求计算轨迹

任务5:将轨迹计算功能设计为成员函数

目录任务5:将轨迹功能设计为成员函数任务描述创建一个Shell类,该类应包含所有与炮弹轨迹计算相关的属性和方法。将坐标计算、轨迹计算和轨迹输出等功能封装到类的成员函数中,以提高代码的复用性和可维护性。确保新设计的类能够支持任务4中的两种发射模式,并能正确地根据不同的发射模式进行参数解析和轨迹计算。任务5:将轨迹功能设计为成员函数C++类1.什么是类与对象类(class)是一种用户自定义的数据类型,用于描述具有相同属性和行为的一类事物。例如,“炮弹”可以看作一类事物,它们都有初速度、发射角度、飞行轨迹等共同特征。在C++中,可以定义一个Shell类来表示这类事物。对象(object)是类的具体实例。就像“汽车”是一个类别,而某一辆具体的轿车就是它的实例。在程序中,我们通过类创建对象,每个对象都拥有类中定义的属性和方法。对象在语言层面的表现形式就是变量。任务5:将轨迹功能设计为成员函数C++类1.什么是类与对象classShell{private://私有成员变量:仅类内部可访问doublev0;//初速度doubletheta;//发射角度(弧度)intcount;//轨迹点数量Positionpositions[100];public://公有成员函数:对外提供的接口voidcomputePos(doublet);voidcalculateTrajectory();voidoutputTrajectory();};定义了一个名为Shell的类。private区域用于保护数据,防止外部随意修改;public区域是类的接口,允许外部调用其功能。任务5:将轨迹功能设计为成员函数C++类2.对象的定义与使用定义类之后,就可以创建该类的对象。对象的定义方式类似于基本数据类型的变量声明:Shellshell;//定义一个Shell类的对象shell创建对象后,就可以通过“对象名.成员名”的方式访问其公有成员函数:shell.v0=50.0;//若v0为public(不推荐)shell.theta=PI/4.0;//若theta为public(不推荐)shell.calculateTrajectory();//调用成员函数计算轨迹shell.outputTrajectory();//调用函数输出结果出于数据安全考虑,通常将数据成员设为private,通过公有函数(如setV0()、setTheta())进行设置,这体现了“封装”的思想。任务5:将轨迹功能设计为成员函数C++类3.成员函数的定义与调用成员函数是类中定义的函数,用于操作类的数据。它们可以在类内部直接定义,也可以在类外部实现。外部定义时需使用作用域解析运算符::指明所属的类。//在类外部定义computePos函数voidShell::computePos(doublet){positions[count].x=v0*cos(theta)*t;positions[count].y=v0*sin(theta)*t-0.5*g*t*t;positions[count].t=t;count++;}该函数通过类的对象调用时,可直接访问该对象的数据成员(如v0、theta等),无需额外传入。任务5:将轨迹功能设计为成员函数C++类4.构造函数:对象的初始化每次创建对象时,希望它能自动具备合理的初始状态。C++提供了构造函数(constructor)来完成这一任务。构造函数与类同名,没有返回类型,在对象创建时自动执行。classShell{public://构造函数:初始化对象状态Shell(){v0=50.0;theta=PI/4.0;//默认45度count=0;}//其他成员函数...};这样,每当执行Shellshell;时,对象shell就会自动以初速度50m/s、45°角发射的默认参数初始化,避免了手动设置的繁琐和错误。任务5:将轨迹功能设计为成员函数C++类5.C++标准库简介C++标准库是C++语言的重要组成部分,它提供了一套功能强大、类型安全的工具集,极大地提升了开发效率和代码质量。下面几个库是任务5将要使用的库:(1)<iostream><iostream>是C++的输入输出库,核心是流(stream)概念。std::cout(字符输出流)和std::endl(换行并刷新)是其常用组件。与C语言的printf相比,cout使用<<操作符进行数据插入,无需格式化字符串,类型检查在编译时完成,避免了格式符与参数不匹配的运行时错误。例如:std::cout<<"速度:"<<50.0<<"m/s"<<std::endl;上面的语句将输出“速度:50.0m/s”。(2)<cmath><cmath>提供了丰富的数学函数,是<math.h>的C++版本。它声明了sin、cos、tan、sqrt(平方根)、pow(幂运算)等函数,所有函数都位于std命名空间下。这些函数支持多种浮点数类型(float,double),编译器会自动选择最匹配的重载版本,使用起来既方便又安全。(3)<string><string>库定义了std::string类,用于管理可变长度的字符串。相比C语言的字符数组,std::string自动处理内存分配与释放,支持“+”操作符进行字符串拼接,并能直接与cout配合输出,彻底避免了缓冲区溢出等常见安全问题。例如:std::stringmode="按角度发射";std::cout<<mode<<std::endl;任务5:将轨迹功能设计为成员函数封装为了提升程序的模块化程度和可维护性,可将炮弹的所有属性和操作封装在一个名为Shell的C++类中。该类不仅包含描述炮弹状态的数据(如初速度、发射角度、发射模式、轨迹点数组等),还将与炮弹行为相关的功能设计为类的成员函数。(1)坐标计算功能设计为私有成员函数computePosition(doublet)。(2)轨迹计算功能设计为公有成员函数calculateTrajectory()。(3)轨迹输出功能设计为公有成员函数outputTrajectory()任务5:将轨迹功能设计为成员函数封装(1)坐标计算功能设计为私有成员函数computePosition(doublet)。该函数接收当前时间t作为参数,根据当前的发射模式(按角度或按最大射程)自动解析参数(如初速度和发射角度),并利用物理公式计算该时刻的横纵坐标和高度,然后将结果存入轨迹数组。将其设为私有函数,是因为坐标计算是轨迹生成过程中的内部细节,不应被外部直接调用。//私有成员函数:计算某一时刻的坐标voidcomputePosition(doublet){

if(count>=MAX_POINTS)return;positions[count].x=v0*cos(theta)*t;positions[count].y=v0*sin(theta)*t-0.5*g*t*t;

positions[count].t=t;

count++;}任务5:将轨迹功能设计为成员函数封装(2)轨迹计算功能设计为公有成员函数calculateTrajectory()。该函数负责控制整个轨迹的生成过程。它首先根据当前发射模式和参数确定总飞行时间,然后以固定时间步长循环调用computePosition函数,逐步填充轨迹数组,并记录轨迹点总数。该函数作为核心逻辑的入口,对外提供统一的调用接口。//公有成员函数:计算完整轨迹voidcalculateTrajectory(){//根据模式确定实际的v0和thetaif(mode==BY_ANGLE){theta=param.theta;//v0已由用户设置或构造函数初始化}elseif(mode==BY_MAX_RANGE){v0=sqrt(param.range*g);//由最大射程反推初速度theta=PI/4.0;//45度时射程最大}count=0;//重置计数器doublet=0.0;doublet_max=(2.0*v0*sin(theta))/g;//总飞行时间//循环计算轨迹点while(t<=t_max&&count<MAX_POINTS){computePosition(t);t+=0.1;//时间步长0.1秒}}任务5:将轨迹功能设计为成员函数封装(3)轨迹输出功能设计为公有成员函数outputTrajectory()。该函数遍历已生成的轨迹数组,依次输出每个时间点的时刻、坐标信息,并标明当前轨迹所使用的发射模式(如“按角度发射”或“按最大射程发射”)。通过封装输出逻辑,使结果显示部分与计算逻辑分离,便于修改输出格式或添加图形化功能。

//公有成员函数:输出轨迹信息std::stringgetModeString()const{return(mode==BY_ANGLE)?"按角度发射":"按最大射程发射";}voidoutputTrajectory()const{std::stringmodeStr=getModeString();std::cout<<"===发射模式:"<<modeStr<<"==="<<std::endl;for(inti=0;i<count;i++){std::cout<<"时间"<<positions[i].t<<"秒:"<<"坐标("<<positions[i].x<<","<<positions[i].y<<")"<<std::endl;}std::cout<<"共记录"<<count<<"个轨迹点。"<<std::endl<<std::endl;}};任务5:将轨迹功能设计为成员函数程序流程程序的功能:通过定义C++类Shell,将炮弹的状态数据和轨迹计算、输出等功能封装在一起,实现对两种发射模式下弹道轨迹的模拟与展示。Step1:定义物理常量PI和g,分别表示圆周率和重力加速度;Step2:定义结构体Position,包含三个成员x、y和t,用于表示炮弹在某一时刻的坐标和时间;Step3:定义枚举类型LaunchMode,包含BY_ANGLE和BY_MAX_RANGE两个常量,表示两种发射模式;Step4:定义联合类型LaunchParam,包含theta(发射角度)和range(最大射程)两个成员,用于根据模式存储不同参数;Step5:定义C++类Shell,其私有成员包含发射模式mode、参数联合param、初速度v0、实际发射角度theta、轨迹点计数count和Position类型的数组positions[100];Step6:在类的公有部分声明成员函数:构造函数Shell()用于初始化默认参数,calculateTrajectory()用于生成完整轨迹,outputTrajectory()用于输出轨迹信息;Step7:在类外部或内部实现calculateTrajectory()函数:根据当前模式确定初速度和发射角度,计算总飞行时间,循环调用私有函数computePosition填充轨迹数组;Step8:在main函数中创建Shell类的对象shell;Step9:设置对象的发射模式(如shell.mode=BY_MAX_RANGE)和对应参数(如shell.param.range=100.0);Step10:调用对象的calculateTrajectory()成员函数,计算并生成完整的弹道轨迹;Step11:调用对象的outputTrajectory()成员函数,输出所有轨迹点的时间、坐标及发射模式信息;Step12:程序结束,返回0。任务5:将轨迹功能设计为成员函数任务扩展任务5使用C++类成功实现了炮弹轨迹的计算与封装。然而,如果需要模拟不同物理模型的抛射体(如不考虑空气阻力的炮弹、受恒定风力影响的火箭、或在不同星球重力下的卫星),它们的运动方程可能不同,但整体的模拟流程(初始化、计算轨迹、输出结果)是高度相似的。任务5:将轨迹功能设计为成员函数C++模版类

1.C++模板类的定义和使用方法模板类是一种“类的生成器”,它不针对特定类型,而是使用模板参数(可以是类型或常量)来定义通用结构。编译器会根据实际提供的参数,在编译时实例化出具体的类。定义模板类使用template关键字:template<typenameT>classMyContainer{private:Tdata;public:MyContainer(Tvalue):data(value){}voidprint(){std::cout<<data<<std::endl;}};使用时,需在类名后指定具体类型:MyContainer<int>intBox(10);//创建存储int的容器MyContainer<double>dblBox(3.14);//创建存储double的容器模板类使得代码具有极高的通用性和可复用性,是实现“泛型编程”的核心工具。任务5:将轨迹功能设计为成员函数C++模版类

2.用模板类设计任务5的方法可以将Shell类改造为模板类,使其能适配不同的物理计算策

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

最新文档

评论

0/150

提交评论