C++程序设计实践样例
更新时间:2024-04-30 23:25:01 阅读量: 综合文库 文档下载
C++程序设计实践教材
第一章 程序设计同步实验指导
实验一 Visual C++集成开发环境(IDE)入门
一、实验目的
1. 初步学会使用 Visual C++集成开发环境:①进入和退出;②菜单、工具 栏的使用;③用户窗口区的划分:workspace, scource file, message。
2. 初步了解调试程序方法。
二、实验内容
1. 范例:Visual C++控制台应用程序设计步骤。
作为学习面向对象的 C++的第一步,学习的重点是算法,必须避免用户图形 界面的干扰,这时可采用控制台应用程序进行练习。控制台应用程序创建一个窗 口模拟 DOS 进行输入输出。
下面是一个控制台应用程序实例,该程序要求用户从键盘输入 3 个整数, 然后按照从小到大的顺序在屏幕上输出。
[步骤一] 进入和退出 Visual C++集成开发环境
启动并进入 Visual C++集成开发环境有至少有三种方法:
⑴ 在开始菜单上,选择程序,然后选择 Microsoft Visual Studio 6.0组,再选 择 Microsoft Visual C++6.0,如图 1.1。
⑵ 在桌面上创建 Microsoft Visual C++6.0 的快捷方式,直接双击该图标; ⑶ 如果已经创建了 VC 的某种工程,双击该工程的 dsw(Develop Studio Workshop)文件图标,也可进入集成开发环境,并打开该工程。
选择 File|Exit 菜单,退出集成开发环境。
图 1.1 进入 Visual C++ 集成开发环境
[步骤二] 创建一个控制台应用程序工程。
⑴ 入 VC 环境后,选择 File|New 菜单,弹出 New 对话框,在 Projects 页面 选择 Win32 Console Application 工程类型,在 Project name 编辑框输入工程名 Exp1_1,在 Location 编辑框输入工程路径 E:\\ projects\\ Exp1_1,如图 1.2 所示, 按 OK 按钮。
1
第一章 控制台应用程序
图 1.2 New Project 页面,创建新的应用程序
图 1.3 Win 32 Console Application Step 1 of 1
2
C++程序设计实践教材
⑵ 随后的 Win 32 Console Application Step 1 of 1 中,参见图 1.3,选择 an empty project,按 Finish 按钮。
⑶ 现 Project Information 框,如图 1.4。显示创建了一个空的控制台应用程 序,且没有任何文件被添加到新工程中,此时,工程创建完成。
图 1.4 New Project Information 窗口
[步骤三] 程序的编辑、编译、建立、执行。
⑴ 选择 File|New 菜单项,在 New 对话框的 Files 页面选择 C++ Source File, 输入文件名 Exp1_1.cpp,选中 Add to Project 复选框,如图 1.5,按 OK 按钮,打 开了源文件编辑窗口。输入以下源代码。
#include
int main(){
int a,b,c; int max,min;
3
第一章 控制台应用程序
cout<<\请输入三个不等整数:\\n\ cin>>a>>b>>c; if(a>b){
max = a; min = b; } else {
max = b; min = a; } if(c>max)
else return 0; }
cout< else if(c //B行 //A行 图 1.5 创建新的 C++源文件 4 *对于已经存在的源文件,选择 Project|Add to Project| Files?菜单项,在随后 C++程序设计实践教材 打开的插入文件对话框中选择待添加文件,按 OK 添加进工程。 ⑵ 选择 Build|Compile 菜单项,即可编译源文件 Exp1_1.cpp,系统会在 Output 窗口给出 Error(错误)信息以及 Warning(警告)信息。当所有 Error 改正后,得到目 标文件(Exp1_1.obj)。 编译器在 Output 窗口给出语法错误和编译错误信息。 语法错误(Error)处理:鼠标双击错误信息可跳转到错误源代码处进行修改, 一个语法错误可能引发系统给出很多条 Error 信息,因此,发现一个错误并修改 后最好重新编译一次,以便提高工作效率; 警告信息(Warning)处理:一般是触发了 C\\C++的自动规则,如将一个浮点型 数据给整型变量赋值,需要系统将浮点型数据自动转换为整型,此时小数部分会 丢失,因而系统给出警告信息。警告信息不会影响程序执行,本例可以通过强制 类型转换去掉警告信息。 ⑶ 选择 Build|Build 菜单项,链接并建立工程的 EXE 文件,得到可执行文件 Exp1_1.exe。这时编译器可能会给出链接错误。 链接错误(Linking Error)处理:链接时可能产生错误,原因可能是所需要的 库文件或目标文件缺少,或程序中调用的 Extern 函数没有定义等,只要补充相 应文档再重新建立即可。 ⑷ 选择 Build|Execute 菜单项,执行工程文件,会出现一个类似 DOS 操作系 统的窗口,光标闪烁等待输入,按要求输入三个不等的整数后按 Enter 键,屏幕 上由大到小输出这三个整数如图 1.6。 图 1.6 例 1_1 运行结果 [步骤四] 程序的程序的调试简介 运行程序,可能会发现程序没有编译错误,也能执行,但执行的结果不对, 此时,除了仔细分析源程序,还可借助调试工具进行跟踪调试。 例如,在例 1_1 程序中 B 行处出错,在 else 后多加一个分号: ? else ; {max = b; min = a;} 用 88, 45, 67 这组数据测试,发现输出结果为 67 45 88,结果不对。下面介 绍调试过程。 首先在源程序中可能出现错误的行上设置断点,方法是将光标移至该行,然 后按 F9 键,或选择工具栏上的手形按钮(再按一次取消断点),此时该行左侧出 现一个红色圆点,断点设置成功,如图 1.7 在 A 行设置断点。 选择 Build | Start Debug | Go?菜单命令(也可选择 Build 工具栏上的 Go 图 标 ),程序执行到断点处停止,这时选择 View|Debug Windows 子菜单的 Watch 和 Variables 两个菜单项,打开监视和变量窗口观察变量值(Watch 和 Variables 窗口 的详细介绍见 VisualC++ 6.0 集成开发环境介绍中菜单的 View 菜单介绍),分析 查找出错原因。 在 Watch 窗口加入 max 和 min 两个变量,进行监视。Watch 窗口的每一行 可显示一个变量,左栏显示变量名,双击它可进行编辑;右栏显示变量值。单步 5 ),尽管 a>b, 在执行了 if 后面的 执行按 F10(不跟踪进函数)或 F11(跟踪进函数内 {max = a; min = b;}后,仍然执行了{max = b; min = a;}。当程序执行到箭头所指 处时,max=45, min=88,如图 1.7,与预期结果不相符,说明程序的流程有问题。 此时再仔细分析源程序,发现问题出在 else 后多余的分号。 第一章 控制台应用程序 图 1.7 Visual C++ 集成开发环境及程序的调试 调试过程中 Variables 窗口动态显示各变量值随程序执行而变化的结果。在 学习到面向对象程序设计后,若程序中有类的对象,Variables 窗口的 this 页面可 显示当前 this 指针所指向对象的各个值。 修改源程序,再执行,反复调试,当程序中所有问题都得到改正后,得到正 确的执行结果。 实验二 简单的 C++程序设计 1. 简单程序设计,掌握 C++程序基本结构。 一、实验目的 2. 掌握 C++ 基本数据类型与运算符。 3. 熟悉输入输出方法。 二、实验内容 1. 范例:要求实现输入两个整数,将它们交换后输出。 [分析] 交换两个整数,一般方法是用一个中间变量,经过几次赋值实现; [过程] 6 C++程序设计实践教材 ①首先在资源管理器中,在用户盘(硬盘)创建自己的文件夹,如可以自己 的学号为名建立文件夹。 ②进入 VC 环境,选择 File|New 菜单,弹出 New 对话框,在 Projects 页面 选择 Win32 Console Application 工程类型,在 Project name 编辑框输入工程名 Exp2_1,路径选择自己的文件夹,按 OK 按钮。 ③在随后的 Application Wizard 中选择 an empty project,按 Finish 按钮。 ④选择 File|New 菜单项,在 New 对话框的 Files 页面选择 C++ Source File, 输入文件名 Exp2_1.cpp,选中 Add to Project 复选框,按 OK 按钮,打开了源文 件编辑窗口,输入以下源代码。 #include int a=-3,b=7,temp; cout<<\ temp=a; a=b; b=temp; cout<<\ return 0; } [分析二](可选) 第二种方法采用按位异或,任一位与 0 异或保持不变, 而与 1 异或后翻转(0 变 1,1 变 0)。 v1=a; v2=b; //原 v1 为 a,v2 为 b v1=v1^ v2; //即 V1 为 a^ b,V2 保持不变 v2=v1^ v2; //即 v2=a^ b^ b=a v1=v1^ v2; //即 v1=a^ b^ a=b,交换成功 #include int a=-3,b=7,temp; cout<<\ a=a^b; b=a^b; a=a^b; cout<<\ return 0; } [实验要求] ① 仔细阅读程序,掌握程序结构,找到程序的数据定义部分和操作部分, 辨识各部分功能,注意输入输出语句的使用; ② 按照正确的步骤进入 VC 环境,在自己创建的工程中录入上述源程序, 注意书写格式,养成良好的编程习惯;消除语法错误,编译链接程序; 7 第一章 控制台应用程序 ③ 运行程序,输入数据观察结果,并进行测试。 ④ 用位运算符重新运行程序并对比运行结果。(可选) 2. 编写程序:输入球的半径,分别计算球的表面积、体积和质量,假设球 的密度为 7.8,输出计算结果。 4 3 [提示] 球表面积计算公式 s?? 4?r ,球体积计算公式 v???????r 。 3 2 注意输入输出形式,要求输入前应有提示性输出,如\ of the Ball?\,注意变量名的定义,最好能望文生义,如 Radius,Volume,Weight 等; 整数相除取整,注意在计算公式中使用正确的变量数据类型。 3. 范例:要求用 sizeof 运算符计算 C++中 char, short, int, long, float, double 等 基本数据类型所占字节数,并按以下格式输出。 sizeof(char)= 1 byte sizeof(short) = 2 bytes sizeof(int) = 4 bytes ? 再将计算结果以表格形式输出。 char short int ? 1 2 4 最后将计算结果保存在数组中,再按表格形式输出。 #include int size[6]; cout<<\ cout<<\ cout<<\ cout<<\ cout<<\ cout<<\ cout<<\ cout<<\ cout<<\ cout<<\ cout<<\ cout<<\ size[0]=sizeof(char); size[1]=sizeof(short); size[2]=sizeof(int); //字节数存入整型数组 //表格方式输出 8 C++程序设计实践教材 size[3]=sizeof(long); size[4]=sizeof(float); size[5]=sizeof(double); cout<<\ //再用数组以表格方式输出 cout<<\ cout<<\ cout<<\ cout<<\ cout<<\ return 0; } 4. 范例:演示 C++输入输出易出错的几个地方: ①采用 cin 输入将会跳过空白字符(包括空格,制表,backspace 和回车等)。 如果要求把从键盘上输入的所有字符,包括空白字符,都作为输入字符赋给字符 变量,必须使用函数:cin.get(字符变量),但这时如前面曾有输入,会读入不是 希望获取的数字输入结束的回车符。 ②向一个字符数组中输入字符串时,应该使用函数:getline(字符数组,字符 数量) 。这时如前面曾有输入,会读入输入结束的回车符,形成空串。 ③ 当使用老的头文件 #include char a[20]; int i; cout<<\请输入以下包含空格的字符串:It's a book.\ cin>>a[0]>>a[1]>>a[2]>>a[3]>>a[4]>>a[5]>>a[6]>>a[7]>>a[8]>>a[9]; a[10]='\\0'; cout<<\保存的是:\ cout<<\请重输一遍:\ cin.get(a[0]);cin.get(a[1]);cin.get(a[2]);cin.get(a[3]); cin.get(a[4]);cin.get(a[5]);cin.get(a[6]);cin.get(a[7]); cin.get(a[8]);cin.get(a[9]);cin.get(a[10]);cin.get(a[11]); cin.get(a[12]);cin.get(a[14]); a[15]='\\0'; cout<<\保存的是:\ cout< cout<<\注意:a[0]放上次输入结束的回车符,a[14]放本次结束的回车符, 各自产生一个换行。\ cout<<\请输入8进制整数:0750\ cin>>i; 9 第一章 控制台应用程序 cout<<\输入的数用十进制表示是:\ cout< cout<<\请输入16进制整数:0xff\ cin>>i; cout<<\输入的数用十进制表示是:\ cout< cout<<\用cin.getline()吸收0后的字符:\ cin.getline(a,18); cout< cout<<\改用显式指定类型,输入8进制数750:\ cin>>oct>>i; cout<<\输入的数用十进制表示是:\ cout< cout<<\输入的数用8进制表示是:\ cout< cout<<\请输入16进制整数:ff\ cin>>hex>>i; cout<<\输入的数用十进制表示是:\ cout< cout<<\请输入字符串:This is a cat.\ cin.getline(a,18); cout< cout<<\没有机会输入。读了上次输入数字时的回车,输出一个空串。 现在可输入了:\ cin.getline(a,18); cout< //指明8进制输出以后一直有效 [实验要求]读懂程序,理解程序中演示的输入输出中易出错的情况。 实验三 分支结构程序设计 一、实验目的 流程控制语句用于实现基本程序结构,是程序设计基础。要求掌握: 1. 条件语句的使用。 2. 开关语句的使用。 二、实验内容 1. 范例:输入一个整数,判断数的奇偶性后输出结果。 [分析] 判断一个数是否为偶数,只要判断它是否能被 2 整除,用除法取余。 n%2 为 0,则 n 为偶数,否则,为奇数。 10 C++程序设计实践教材 #include int input; cout<<\ cin>>input; if(input%2) cout<<\ \ //如果能被 2 整除,是偶数 else } cout<<\ \ //否则是基数 return 0; 形式中,奇数的末位为 1,偶数末位为 0。可以用整数 n 与 1 进行按位与运算: [分析二] (可选) 判断一个数的奇偶,只需判断最后一位,在二进制表示 n&1 为非 0(真),则是奇数,为 0(假),则是偶数。 在上面程序中,将 if 判断的条件改为 n&1 即可,其它部分不用修改。 #include int input; cout<<\ if(n&1) cout<<\ \ //如果能被 2 整除,是偶数 cin>>input; else cout<<\ \ //否则是基数 return 0; } [测试数据] 345 680 -34 -23.5(有意用非整数测试) 分别用以上各数作为输入数据,测试程序,分析程序结果,并进行记录。 2. 范例:编程求一元二次方程 ax2+bx+c=0 的根。包括以下判断和结果:若 输入 a=0,给出提示;若?>0,输出两个不等实根;若?=0,输出两个相等实根; 若?<0,输出两个复数根。 [程序] 根据以上要求,编写下列源程序,请与主教材例 2.8 作对比。 #include double a,b,c; double delta,x1,x2; int sign; cout << \一元二次方程 a*x*x+b*x+c=0\\n\ cout<<\输入三个系数a(a!=0), b, c:\ cin>>a>>b>>c; cout<<\ if(a==0){ 11 第一章 控制台应用程序 cout<<\二次项系数为0,不是一元二次方程\ exit(0); delta=b*b-4*a*c; } if(delta==0){ cout<<\方程有两个相同实根:\ cout<<\ } if(delta>0) sign=1; else { else sign=0; delta=sqrt(fabs(delta)); x1=-b/(2*a); x2=delta/(2*a); if(sign){ cout<<\方程有两个不同实根:\ cout<<\ } else{ //delta<0 cout<<\方程无实根!有两个不同复数根:\ cout<<\ } } return 0; } 3.编写程序:输入一门课程的成绩,若高于 90 分,输出\若高于 80 而低于 90,输出\ 高于 70 而低于 80,输出\ 高于 60 而低 于 70,输出\ 否则,输出\。用 if-else 嵌套和 switch 语句两 种方法实现。 [注意] if-else 嵌套使用时,注意 else 子句总与其最近的 if 配对;对数据划 分区间时,注意关系和逻辑表达式的正确书写。注意 if-else 与 switch 的区别与联 系,switch 特适合某个整型或字符型表达式的值与一组常量匹配的情况。 4. 编写程序:输入一个数,判断是否是 3 或 7 的倍数,可分四种情况输出: 1) 是 3 的倍数,但不是 7 的倍数; 2) 不是 3 的倍数,是 7 的倍数; 3) 是 3 的倍数,也是 7 的倍数; 4) 既不是 3 的倍数,也不是 7 的倍数; 实验四 循环结构程序设计 1. 循环控制语句用于实现循环程序结构,要求掌握三种循环结构 while、 一、实验目的 do-while、for 的区别与联系,如何相互转换,并能正确使用。 12 C++程序设计实践教材 2. 掌握与循环语句相关的 break 和 continue 语句的使用。 二、实验内容 1. 范例:输入正整数 n,求 n 的阶乘。 [分析] n!=1?2?3?????n,因此可以从 1 开始,由 1!乘以 2 得到 2!,再乘以 3 得到 3!??????,以此推出 n!。 [程序] #include int n,i; double result=0; //result是结果 cout<<\请输入正整数:\ cin>>n; if(n<1){ cout<<\输入错误!\ return 1; } result=1; for(i=2;i<=n;i++) result*=i; cout< 2. 范例:输入若干字符,统计其中数字字符,白字符和其它字符的个数,输入 EOF 结束。 [分析] 要统计若干字符,需用循环反复输入,读入数据后用 switch 语句判断字 符的种类;要统计三种字符数,需定义三个用于计数的变量 nDigit,nWhite,nOther 并首先置 0;读入字符用 cin.get()函数,在这里,用 while 循环比较合适。白字符 指空格键,tab 键和回车键。EOF 表示 End of File,其值为-1,从键盘输入(ctrl+z) 即可。这里采用重载的 int cin.get()函数,它返回的是整型数,所以能返回 EOF。 [程序] #include char c; int nWhite, nOther, nDigit; nWhite = nOther = nDigit = 0; c=cin.get(); while(c!=EOF){ switch (c){ case '0': case '1': case '2' :case '3' :case '4': case '5': case '6': case '7' :case '8': case '9': 13 第一章 控制台应用程序 nDigit++; break; case ' ': case '\\n': case '\\t': nWhite++; break; default: nOther++; break; } c=cin.get(); //读入下一字符 } cout<<\ cout<<\ cout<<\ return 0; } [思考] ①如果要分别统计数字 0~9 各数字出现的次数,怎样才能有效地实现? ②如果要统计输入的一段文字中出现的行数、单词数和字符数,又如何有效实 现? ③本例采用的是什么算法? 3. 编写程序:约瑟夫(Josephus)问题:n 个人围坐成一圈,从 1 开始顺序编 号;游戏开始,从第一个人开始由 1 到 m 循环报数,报到 m 的人退出圈外, 问最后留下的那个人原来的序号。 [分析] 本题首先要定义一个数组,其元素个数为 n。n 定义为常变量,以便定义 数组。数组元素的值标识该人是否出局,1 在圈内,0 出局。值为 0 的元素不参 加报数。可用一个整型数 k 做计数器,采用倒计数,记录留下的人数。 [提示]数组是线性排列的,而人是围成圈的,用数组表示要有一种从数组尾部跳 到其头部的技巧,即下标加 1 除以 n 求余数。 4. 范例:将输入的小写字母转换为大写字母。 [提示]由 ASCII 码表可以看出,大写英文字母的 ASCII 码值在 65 至 90 之间,小写英 文字母的 ASCII 码值在 97 至 122 之间,每一个英文字母的大写和小写的 ASCII 码相差 32 (以上均为十进制)。 #include char str[100]; int i = 0; cout << \ cin.getline(str,100); do{ if (str[i]<'a'||str[i]>'z') continue; //条件可有多种写法,也可不用continue 14 C++程序设计实践教材 str[i]-= 32; }while ( str[++i]!='\\0'); cout << \ return 0; } [思考]但当用户输入一个空串,即用户开始输入时就以 Enter 键结束, string[0] 中就是表征输入串结束的'\\0'字符。由于是 do_while 循环,所以肯定 要进入循环,在循环结束前由 i++ 使 i 的值修改为 1,使得循环体完成后的判断 是对 string[1] 进行,从而跳过对 string[0] 中的串结束符'\\0'判断, 导致在这 种所谓\边界\的情况中,程序不能正确运行。怎样修改?考虑两种方法。 程序的质量指标和算法的质量指标一样,包括程序的正确性、可读性、健壮 性以及高的执行效率和低的存储空间要求。正确性是指对于各种合法的输入,即 使是苛刻的带有刁难性的输入数据也能够得到满足规格要求的结果,这其中就包 括应当能处理各种边界情况。 5. 编程:设计一个程序,输入某天是几月几日,要求算出这一天是本年的 第几天。 [分析] 要算出某天是当年的第几天,应该将当年中本月之前所有月的天数 相加,再加上本月的天数。但这里有一个闰年问题,二月是一个特殊月,如该年 是闰年,则二月有 29 天,否则,便是 28 天,所以,还必须给出年份。 [提示] 判断某年是闰年的条件是:该年号能被 4 整除但不能被 100 整除, 或者能被 400 整除的是闰年。如,1996,2000 是闰年,但 1800 不是闰年。 实验五 常用算法:枚举法 递推法 迭代法 一、实验目的 掌握常用算法:枚举法,递推法、迭代法。 二、实验内容 a 1. 编程求和:s=a+aa+aaa+?+aa?a,其中 a 是 1~9 中的一个数字。 [提示] 令各项为 b0,b1,b2,?bn 则 b0 = a b1 = b0*10+a b2 = b1*10+a? 即每一项是为前一项乘以 10 加 a,递推得到各项并求和。 2. 编程求出所有的\水仙花数\,所谓\水仙花数\是指一个三位数, 其 各位数字的立方和等于该数本身,例如 153 是一个\水仙花数\,因为 153= 3 3 1 +5 +3 。采用枚举法。 3 3. 范例:设函数 f(x)定义在区间[a,b]上,f(x)连续且满足 f(a)*F(b)<0,求 f(x) 在[a,b]上的根。采用割线法,迭代公式为: xi+1 = x i+( x i-1- x i)/(f(x i)-f(x i-1))*f(x i) 其代换规律为:首先用两端点函数值的绝对值较大者的对应点作为 x i-1,较小者 n 个 作为 x i,即如果|f(a)|<|f(b)|,则 x i-1?a,x i?b。用迭代公式得出 x i+1,f(x i+1)。 15 第一章 控制台应用程序 ⊿ x =( x i-1- x i)/(f(x i)-f(x i-1))*f(x i) 当⊿ x (x i+1,f(x i+1))代替(x i,f(x i)),继续迭代。 求解方程:x*lg(x)=1 的实根的近似值,误差不超过 0.01。 [提示]令 f(x)=x*lgx-1,则 f(2)?-0.398<0,而 f(3)?0.431>0,根在 2 与 3 之间。 #include double a=2,b=3,ep=0.001; int main(){ int maxit,j; double x1,x2,temp,f1,f2,dx; f1=a*log10(a)-1; f2=b*log10(b)-1; if(f1*f2>=0){ cout<<\初值错!\ return 0; } if(fabs(f1) x1=a; x2=b; } else{ x1=b; x2=a; temp=f1; f1=f2; f2=temp; } for(j=1;j<=max;j++){ dx=(x1-x2)*f2/(f2-f1); cout< f2=x2*log10(x2)-1; cout<<'\\t'< cout<<\方程的根为:\ return 0; 16 误差定义为: C++程序设计实践教材 } } cout<< \迭代次数过多!\ return 1; } 4. 范例: 0 到 4 五个数字,组成五位数,每个数字用一次,但十位和百位 不能为 3(当然万位不能为 0),输出所有可能的五位数。 #include int i,j,k,l,m,count=0; for(i=1;i<=4;i++){ for(j=0;j<=4;j++){ if(j==i) continue; for(k=0;k<=4;k++){ if(k==3||k==i||k==j) continue; for(l=0;l<=4;l++){ if(l==3||l==i||l==j||l==k) continue; for(m=0;m<=4;m++){ if(m==i||m==j||m==k||m==l) continue; cout< if(count%5==0) cout< return 0; } 穷举法采用循环语句,对须剔除的情况,应在循环体内用条件语句实现,并 使用 continue 语句,不可用 break。如果放在循环条件中,必然出错。 实验六 文本文件简单应用 一、实验目的 1. 学会将程序运行的结果存入文本文件。 2. 学会从文本文件读取数据,进行运算。 二、实验内容 1. 范例:修改实验五中的第二题,求出水仙花数后不是在屏幕上显示而是 存入文本文件。请在退出程序后,用记事本打开该文本文件,查看结果。 [格式] (1) 说明一个文件流对象(内部文件)。文件流类型 ifstream 支持从输入文件中提 取数据的操作。而文件流类型 ofstream 完成数据写入输出文件中的各种操作。 ifstream ifile; ofstream ofile; //定义输入文件,ifile 为文件名,可用任意标识符 /定义/输出文件,ofile 为文件名,可用任意标识符 特别注意:输入文件用于读,输出文件用于写。 (2) 打开文件。 ifile.open(\ //引号中的\为磁盘文件路径名 ofile.open(\ 在文件流对象和磁盘文件名之间建立联系。 17 第一章 控制台应用程序 (3) 对文件进行读写操作。可用 C++的提取运算符(>>)和插入运算符(<<)进 行。也可以用读字符的 get()和读字符串的 getling()等函数。用输出文件(如 ofile) 代替 cout,输入文件(如 ifile)代替 cin。 (4) 关闭文件。 ifile.close(); ofile.close(); 关闭文件时,系统把与该文件相关联的文件缓冲区中的数据写到磁盘文件 中,保证文件的完整;同时把磁盘文件名与文件流对象之间的关联断开,可防止 误操作修改了磁盘文件。 #include int k=100,l,m,n,count=0; ofstream ofile; ofile.open(\ ofile<<\水仙花数有:\ do{ l=k/100; n=k; //百位 //个位 //定义输出文件 m=(k-l*100-n)/10; if(k==l*l*l+m*m*m+n*n*n){ ofile< if(count%5==0) ofile< //关闭文件 2. 范例:编程从上题生成的文本文件读取水仙花数,并显示在屏幕上。 #include char ch[256]; ifstream ifile; ifile.open(\ cout<<\文件内容:\ do{ ifile.getline(ch,255); cout< //由文件读入数据 //屏幕显示 //定义输入文件 18 C++程序设计实践教材 }while(ifile.eof()==0); ifile.close(); return 0; } //当读到文件结束时,ifile.eof()为真 //关闭文件 注意:在读到文件结束符前,先读了一个空串,所以输出多了一空行。 2 2 3. 编写程序求 500 以内的勾股弦数。即满足 c =b +a 的三个数,要求 b>a。 2 将所有符合要求的组合存入文本文件。 4. 编写程序从上题建立的文本文件中读取 500 以内的勾股弦数,并显示在 屏幕上。 实验七 函数的基本概念 一、实验目的 函数是 C++程序的基本组成模块,要求熟练掌握: 1. 函数的定义及调用。 2. 函数参数的传递(传值),形参、实参的关系,函数声明。 3. 理解局部变量的意义。 二、实验内容 1. 范例:将教材中【例 2.12】改为用函数实现,编写一个用迭代法求平方 根的函数。 [分析] 写一个通用的求平方根的函数,参数(形参)为待求根的数,返回值为 该数的平方根。由于平方数不可能为负,因此在主调函数中,设置一个判断输入 数正负的操作,为正则用该数(实参)调用求平方根函数,为负输出错误信息。 [程序] #include double sroot(double a); int main(){ double x, a; cout <<\ cin >>a; if(a<0) else{ x=sroot(a); //调用求平方根函数 cout <<\ cout<<\ //求平方根函数原型声明 } } double sroot(double a){ double x = a/2; return 0; 19 第一章 控制台应用程序 while(fabs((x-a/x)/2)>1e-7) x=(x+a/x)/2; return (x); } 2. 范例:在按值传递中,被调函数执行时,形式参数得到了实在参数的一 个副本,这样调用函数可以向被调函数单方向传递数据。但在被调函数中不能对 实在参数本身操作。C++/C 对数组参数传递拷贝的是数组的起始地址,而不是拷 贝数组本身,所以操作是在原数组上进行。下面是传递数组的一个简单例子 #include char name[4] = \ cout < void change_it(char c[4]){ strcpy(c, \ return; } // Output ABC // Output XYZ 3 .设计一个简单的计算器程序,从键盘输入\ 5\代表表达式\,程序 读入运算符和数据,调用 Calculate 函数,根据运算符进行+,-,*,/四则运算。要求 能反复执行这一过程,直到用户输入#符号作为运算符。 函数原型已给出如下: double add(double, double); //加+ double minus(double, double); //减- double multi(double, double); //乘* double div(double, double); //除/ double Calculate(double,double,char); //运算符作为字符数据读入 4. 设计一个求两个数最大公约数的通用函数,算法不限,要求能反复输入 数据并输出其最大公约数。 *可用枚举法,从两数中的小者开始试,逐步减小,直到找到最大公约数。 实验八 函数的递归算法 一、实验目的 1. 掌握函数的嵌套调用、递归调用。 2. 掌握递归法编程。 20 C++程序设计实践教材 二、实验内容 1. 函数嵌套调用是在被调用的函数内再调用其它函数,而递归调用是在被 调函数内调用自身。嵌套调用的层数没有限制,而递归调用函数必须包含使递归 终止的语句。 m 范例:求组合数,C n??? n!/(m!(n?? m)!) [分析] 求组合数要用到求阶乘,将求阶乘定义为一个函数,在求组合数的 函数中嵌套调用阶乘函数。由于 n!=n*(n-1)!,求阶乘是一个典型的递归算法,在 此用递归方法实现。 #include long com(int ,int), fac(int); int main(){ int m,n; cout<<\ cin>>m>>n; if(m<=n) cout<<\ else cout<<\ return 0; //函数声明 } com(int i,int j){ long long cmb; cmb= fac(j)/(fac(i)*fac(j-i)); return cmb; } long fac(int i){ long fcl; if(i==0||i==1) fcl =1; else fcl = i*fac(i-1); return fcl; } // att:B //使递归结束的语句 //递归调用 // att: A //在com函数内嵌套调用fac函数 这里因阶乘极易溢出,n 最大取 12,否则运算中溢出。 [注意] 在函数内定义局部变量时,变量名不应与函数名相同,在 A 行处, 不可定义变量名为 com,在 B 处,不可为 fac;还有一种常见错误如下: long fac(int i){ if(i==0||i==1) fac(i) =1; else fac(i) = i*fac(i-1); return fac(i); } 编译这样的程序,会出现\的错误,这是为什么? 2. 用欧几里德算法计算两个数的最大公约数,分别用递推(while 循环实现) 和递归两种方法实现。并计算两个数的最小公倍数。 [提示] 欧几里德算法参见教材【例 2.21】 21 第一章 控制台应用程序 C ? n!/(m!(n?? m)!) =(n*(n-1)*?*(n-m+1))/m! m n 3. 修改第一题,使其不易溢出。考虑到: =(n/1)*(n-1)/2* ?*(n-(m-2))/(m-1)* (n-(m-1))/m= C 可以用递归的方法计算。 这里 n 可以用到 40。 m-1 n*(n-(m-1))/m 实验九 函数的重载和变量的作用域 一、实验目的 1. 了解内联函数、重载函数、带缺省参数函数的定义及使用。 2. 作用域概念,变量的存储类型及它们之间的差别。 3. 掌握程序的多文件组织。 4. 掌握编译预处理内容,理解带参数宏定义与函数的区别。(可选) 二、实验内容 1. 重载函数允许不同的函数使用相同的名字,这使得完成类似任务可以使 用相同函数名。 范例:编写几个计算面积的函数,分别计算圆、矩形、梯形和三角形的面积, 计算边长为 1 的正方形及其内切圆、内接等腰三角形和等腰梯形面积。 函数原型如下: double area(double radius=0); //圆面积,参数为半径,缺省参数 0,表示点面积 double area(double a, double b); //计算矩形面积,参数为长和宽 double area(double a, double b, double h); //计算梯形面积,参数为两底和高 double area(double a, double b, double c, int); //三角形,参数为三边长,int 型参数起标示作用,以区别于梯形, 不参加计算 图 1.8 计算不同 图形面积 程序如下: #include double area(double radius=0); double area(double a, double b); double area(double a, double b, double h); double area(double a, double b, double c, int); int main(){ cout<<\ cout<<\ cout<<\ 22 C++程序设计实践教材 cout<<\ cout<<\ return 0; } double area(double radius) {//带缺省参数的函数 return PI*radius*radius; } double area(double a, double b){ return a*b; } double area(double a, double b, double h){ return (0.5*(a+b)*h); } double area(double a, double b, double c, int){ double s=0.5*(a+b+c); return sqrt(s*(s-a)*(s-b)*(s-c)); } 2. 编程:将上题以多文件方式组织,在 area.h 中声明各个 area 函数原型, 在 area.cpp 中定义函数,然后在 Exp9_2.cpp 中包含 area.h,定义 main 函数并执 行。 注意:using namespace std; 只能说明一次,或者说只能在一个文件中说明。 3. 范例:作用域:全局变量、局部变量和静态局部变量的应用。 分析并 写出下列程序的执行结果,然后输入计算机执行,比较分析结果与执行结果。 #include static int a = 5; a+=c; cout< void funb(int a){ a= b; cout< void func(){ int c=0; cout< funa(a); funb(b); funa(b); func(); 23 第一章 控制台应用程序 cout< 4. 编程:分别以宏和函数形式求某个数的绝对值,并编程调用它们。内联 (inline)函数虽然以函数形式定义,但在调用时相当于宏,将代码直接替换函 数调用表达式,不需调用栈操作,可以节省栈空间和函数调用的时间开销;但要 求函数代码简单,没有复杂语句。(可选) [思考] 这两种方法各有什么特点,当考虑到不同数据类型时,哪种方法更合适? 为什么 C++不提倡用宏? 5. 希望对不同类型的数据完成相似功能时往往采用函数重载的方法。例如 要在程序中用不同的格式输出不同类型的数据,可以编制多个同名的 output() 函数,这些函数的参数类型互不相同,对不同的参数设计不同的输出格式。 编程:使用函数重载技术编程实现自动适应字符串、整数和实数的输出。 实验十 类与对象的基本概念 一、实验目的 类是 C++扩展数据类型,可以封装不同类型的数据成员和函数成员,类是面 向对象程序设计的基础。本次实验内容包括面向对象的基本概念、构造函数与析 构函数,从实际问题抽象出类等,通过实验要求: 1. 掌握面向对象的基本概念,类的定义方法。 2. 掌握类成员的访问权限及访问类成员的方法。 3. 掌握内联函数和缺省函数。 4. 掌握构造函数与析构函数的意义及使用方法。 二、实验内容 1. 范例:集合是具有同一属性(共性)而又能互相区别(个性)的多个成 员汇集起来的整体,构成集合的每个成员称为集合的元素,元素间没有顺序关系。 例如,所有的大写英文字母是一个集合,它包括 26 个元素:A、B、?、Z。不 包含任何元素的集合称为空集合。 [实验要求] 自定义一个集合类 set,采用数组存放集合的元素。自定义集合运算 包括: 1) 判断元素 elem 是否为集合 set 的元素。 2) 为集合添加一个元素 elem。 3) 从集合中删除一个元素 elem。 4) 复制一个集合,其元素与原集合完全一样。 5) 显示集合中的所有元素。 6) 求两个集合中相同的元素,即求两个集合的交集。 7) 求两个集合中所有的元素,即求两个集合的并集。 8) 判断两集合包含的元素是否完全相同。 9) 判断一个集合是否被包含在另一个集合之中,即是否为另一个集合的子集。 24 C++程序设计实践教材 [程序] #include const int maxnum=20; enum ErrCode{noErr,overflow}; class set{ char elements[maxnum]; int num; public: set(){num=0;} bool Member(char); ErrCode AddElem(char); void RmvElem(char); void Copy(set); bool Equal(set); void print(); void Intersect(set,set); //求本集合与第一参数所指出的集合的交,并存入第二参数所指出的集合中 ErrCode Union(set,set); //求本集合与第一参数所指出的集合的并,并存入第二参数所指出的集合中 bool Contain(set); //判断本集合是否包涵实参指出的集合中所有的元素 //判断元素elem是否为本集合的成员 //将新元素elem加入本集合 //将元素elem从该集合中删去 //将本集合中的所有元素拷贝到实参指出的集合中去 //判断两集合各自包涵的元素是否完全相同 //显示本集合的所有元素 }; bool set::Member(char elem){ int i; for(i=0;i if(elements[i]==elem) return true; return false; } ErrCode set::AddElem(char elem){ int i; for(i=0;i if(elements[i]==elem) return noErr;//集合中已有elem,不重复加入 if(num elements[num++]=elem; return noErr; } else return overflow; } void set::RmvElem(char elem){ int i; for(i=0;i if(elements[i]==elem){ //数组已满 25 第一章 控制台应用程序 for(;i } void set::Copy(set s){ int i; for(i=0;i bool set::Equal(set s){ int i; if(num!=s.num) return false; for(i=0;i if(s.Member(elements[i])) return false; return true; //有元素不同 //元素个数不同 } void set::print(){ cout<<\集合的元素包括:\ int i; for(i=0;i } void set::Intersect(set s1,set s2){ int i,j; s2.num=0; for(i=0;i for(j=0;j if(elements[i]==s1.elements[j]){ s2.elements[s2.num++]=elements[i]; break; } } ErrCode set::Union(set s1,set s2){ int i; s1.Copy(s2); for(i=0;i if(s2.AddElem(elements[i])==overflow) return overflow; return noErr; } bool set::Contain(set s){ int i; for(i=0;i if(!Member(s.elements[i])) return false; 26 C++程序设计实践教材 return true; } int main(){ int i; char ch[30]={'A','B','C','D','E','F','G','H','I','J','K','L','M','N', 'O','P','Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d'}; set s,s1,s2,s3,s4; ErrCode b; for(i=0;i<10;i++){ b=s.AddElem(ch[i]); b=s1.AddElem(ch[2*i]); b=s2.AddElem(ch[3*i]); } cout<<\ cout<<\ cout<<\ s.print(); s1.print(); s2.print(); s.Intersect(s1,s3); b=s.Union(s1,s4); cout<<\ cout<<\ s3.print(); s4.print(); if(s3.Contain(s4)) cout<<\ else cout<<\ if(s4.Contain(s3)) cout<<\ else cout<<\ if(s3.Equal(s4)) cout<<\ else cout<<\ for(i=6;i<10;i++){ s.RmvElem(ch[i]); s1.RmvElem(ch[i]); s2.RmvElem(ch[i]); } cout<<\删除部分元素后:\ cout<<\ cout<<\ cout<<\ return 0; } s.print(); s1.print(); s2.print(); 2. 编程:建立一个分数类。分数类的数据成员包括分子和分母,操作包括 显示、输入、约分、通分、比较、加、减、乘、除、求相反数。分数类定义如下: class fraction{ int above; int below; void reduction(); //分子 //分母 //约分 27 第一章 控制台应用程序 void makeCommond(fraction); //通分 public: fraction(int=0,int=1); fraction add(fraction); fraction sub(fraction); fraction mul(fraction); fraction div(fraction); fraction reciprocal(); bool epual(fraction); bool lessThan(fraction); void display(); void input(); }; //构造函数 //两分数相加 //本分数减去实参分数 //两分数相乘 //本分数除以实参分数 //求倒数 //等于运算 //小于运算 //显示分数 //输入分数 bool greaterThan(fraction); //大于运算 完成所有成员函数并进行检验。 实验十一 引用与拷贝构造函数 一、实验目的 1. 掌握引用概念及应用,引用作函数参数。 2, 学会编写与应用拷贝构造函数。 二、实验内容 1. 范例:编写一个函数,其原型为:void Index(int a[], int n,int & sub),其功 能是,在大小为 n 的数组 a 中,查找某个数 sub,若找到,将其下标存放在 sub 中,若没找到,将-1 存放在 sub 中,在主调函数中通过判断值来判断数组中是否 有该数。在这里,sub 是引用类型的参数,但起返回值的作用。 #include void Index(int a[], int n,int & sub); int main(){ int b[25]={2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97}; int n=25,sub; cout<<\输入小于100的正整数:\ cin>>sub; Index(b,n,sub); if(sub!=-1) cout<<\所在元素下标为:\ else cout<<\未找到。\ cout<<\再输入小于100的正整数:\ cin>>sub; Index(b,n,sub); if(sub!=-1) cout<<\所在元素下标为:\ else cout<<\未找到。\ return 0; 28 C++程序设计实践教材 } void Index(int a[], int n,int & sub){ int i,k=sub; sub=-1; for(i=0;i if(a[i]==k){ sub=i; break; } } 2. 范例(可选):一个声明为返回引用的函数,还可以用在赋值号的左边, 即这种函数调用本身是一个左值。 【程序】 #include index(3) = 16; for(int i=0;i<5;i++) cout << index(i)<<' '; cout< int& index(int i){ return array[i]; } [注意] 由于函数 index()是返回引用的类型,所以该函数调用可以作为一个左值, 程序的表达式 index(3)=16 将 16 赋给左边的函数调用,由于该函数调用返回对 array[3] 的引用,所以可以将 array[3]赋新值。该程序运行的结果将使得整型数 组 array 中的各元素值变为: 2,4,6,16,10。 3. 范例:为矩形类定义拷贝构造函数。矩形类见主教材例 4.2。 在 rect.h 中类 rect 定义中加: Rectangle(Rectangle & rec); 在rect.cpp中添加: Rectangle::Rectangle(Rectangle & rec){ left=rec.left; top=rec.top; right=rec.right; bottom=rec.bottom; }//拷贝构造函数 在 main()函数中添加: Rectangle rect2(rect1); 29 第一章 控制台应用程序 cout<<\由拷贝构造函数生成的rect2:\ rect2.Show(); 这里的拷贝构造函数是缺省的按成员语义定义的,只作为一个练习,可以不 写,系统会自动提供。 4. 编程:将实验十的集合类和分数类的集合类型或分数类型参数改为引用, 并添加拷贝构造函数。 实验十二 运算符重载 一、实验目的 1. 掌握运算符重载为成员函数的方法。 2. 理解友元函数和友元类。 3. 掌握运算符重载为友元函数的方法。 4. 使用静态数据成员。 二、实验内容 1. 范例:为主教材例题 4.2 的 Rectangle 类增加加减复合赋值和加减运算符 重载函数。加减复合赋值语义定义为固定长方形的左上角,对右下角的坐标进行 加减运算,使新矩形的长宽为原两矩形长宽之和或差,对加和减复合赋值定义为 成员函数。两个矩形加减运算定义为友元函数。 class Rectangle { int left, top ; int right, bottom; public: Rectangle(int l=0, int t=0, int r=0, int b=0); ~Rectangle(){}; //析构函数,在此函数体为空 void Assign(int l, int t, int r, int b); void SetLeft(int t){ left = t;} // 以下四个函数皆为内联成员函数 void SetRight( int t ){ right = t;} void SetTop( int t ){ top = t;} void SetBottom( int t ){ bottom = t;} void Show(); void operator +=(Rectangle&); void operator -=(Rectangle&); friend Rectangle operator+(Rectangle &, Rectangle&); friend Rectangle operator-(Rectangle &, Rectangle&); }; //将上述内容保存为rect.h #include Rectangle::Rectangle(int l , int t, int r, int b) { left = l; top = t; right = r; bottom = b; 30 C++程序设计实践教材 } // 构造函数,带缺省参数,缺省值为全0,在声明中指定 void Rectangle::Assign(int l, int t, int r, int b){ left = l; top = t; right = r; bottom = b; } void Rectangle::Show(){ cout<<\ cout<<\ }//当用.h头文件时,不用endl输出次序可能出错 void Rectangle::operator+=(Rectangle& rect){ int x = rect.right - rect.left; int y = rect.bottom - rect.top; right += x; bottom += y; } void Rectangle::operator-=(Rectangle& rect){ int x = rect.right - rect.left; int y = rect.bottom - rect.top; right -= x; bottom -= y; } Rectangle operator- ( Rectangle &rect1, Rectangle& rect2){ //矩形相减,从rect1中减去rect2的长度和宽度 rect1 -= rect2; return rect1; } Rectangle operator+ ( Rectangle &rect1, Rectangle& rect2){ //矩形相加,从rect1中加上rect2的长度和宽度 rect1 += rect2; return rect1; } // 将上述内容保存为rect.cpp #include Rectangle rect; cout<<\初始rect:\ rect.Show(); rect.Assign(100,200,300,400); cout<<\赋值后rect:\ rect.Show(); Rectangle rect1(0,0,200,200); cout<<\初始rect1:\ 31 第一章 控制台应用程序 rect1.Show(); rect+=rect1; cout<<\与rect1相加后的rect:\ rect.Show(); rect-=rect1; cout<<\减去rect1后的rect:\ rect.Show(); Rectangle rect2; rect2 = rect+rect1; cout<<\与rect1相加所得rect2:\ rect2.Show(); rect2 = rect-rect1; cout<<\减去rect1所得rect2:\ rect2.Show(); return 0; } // 将上述内容保存为Exp12_1.cpp [要求] 建立工程,录入上述程序,改变数据实验之。 [注意] 缺省的按语义定义的赋值运算符,不必用户定义,系统自动提供。 2. 编程:修改上题,要求如下: (1)将加减运算重载为成员函数; (2) 为矩形类再增加一个静态数据成员 Counter,统计共产生了多少个矩形对象。 为 Counter 添加定义、赋初值及随程序运行而变化的代码,并在 main 函数中对 其输出。注意静态数据成员应该有定义性说明。 3. 阅读与理解:介绍 MFC 中的 CRect 类、CSize 和 CPoint 类。(可选) 介绍 CRect 之前需了解 Windows 的 RECT 结构,其定义如下: typedef struct tagRECT { LONG left; LONG top; LONG right; LONG bottom; } RECT; 它定义了一个矩形的左上角和右下角的坐标,在应用 Windows API 开发应用 程序时,用 RECT 结构表示矩形,tagRECT 是 RECT 结构一个不太常用的名字。 可以用下列方法定义并初始化一个 RECT 结构: RECT rctA; rctA.left = 20; rctA.top = 30; rctA.right = 180; rctA.bottom = 230; 或者 RECT rctB = {20,30,180,230}; 32 C++程序设计实践教材 由于 MFC 是用面向对象方法设计的,引入了 CRect 类表示矩形,它类似于 RECT 结构,并封装了和矩形操作相关的 API 函数,包含了对 CRect 对象或 RECT 结构进行操作的成员函数,对 CRect 的成员函数来说,二者是可互换的。 注意,CRect 类是从 RECT 结构派生的,所以,RECT 的数据成员在 CRect 类中也是可访问的。CRect 的数据成员中,最好使 left 小于 right,top 小于 bottom, 得到一个正常的矩形。如果不是这样,CRect 的某些成员函数会得到错误结果, 但可以调用 CRect::NormalizeRect()函数对矩形进行处理,如果 left 小于 right,该 函数交换 left 和 right,如果 top 小于 bottom,交换 top 和 bottom。 与这一对矩形类型类似的,还有 CPoint 类与 POINT 结构,CSize 类与 SIZE 结构。 typedef struct tagPOINT { LONG x; LONG y; } POINT; POINT 结构定义了一个点的 X 和 Y 坐标。 CPoint 是 MFC 中表示点的类,派生自 POINT 结构,封装了对 CPoint 和 POINT 进行操作的函数,主要是一些运算符函数。 typedef struct tagSIZE { int cx; int cy; } SIZE; SIZE 结构定义了一个矩形的长度和宽度,也表示一个相对位置或相对坐标。 CSize 类与 SIZE 结构类似,可用于 RECT 应用的任何场合。它派生自 RECT 结 构,并封装了对二者进行操作的函数,主要是一些运算符函数。 下面是一些应用实例: // four-integers are left, top, right, and bottom CRect rect(0, 0, 100, 50); ASSERT(rect.Width() == 100); ASSERT(rect.Height() == 50); // Initialize from RECT stucture RECT sdkRect; sdkRect.left = 0; sdkRect.top = 0; sdkRect.right = 100; sdkRect.bottom = 50; CRect rect2(sdkRect); CRect rect3(&sdkRect); ASSERT(rect2 == rect); ASSERT(rect3 == rect); // from a point and a size CPoint pt1(0, 0); CSize sz1(100, 50); CRect rect4(pt1, sz1); ASSERT(rect4 == rect2); // by reference // by address 33 第一章 控制台应用程序 // from two points CPoint rightBottom (100, 50); CRect rect5(pt1, rightBottom); ASSERT(rect5 == rect4); CSize szEmpty(); CSize szPointA(10, 25); SIZE sz; sz.cx = 10; sz.cy = 25; CSize szPointB(sz); POINT pt; pt.x = 10; pt.y = 25; CSize szPointC(pt); CPoint ptObject(10, 25); CSize szPointD(ptObject); DWORD dw = MAKELONG(10, 25); CSize szPointE(dw); [提示] ASSERT 是一个诊断宏,其参数是一个逻辑表达式。求其参数值,如果为 零,向调试窗口输出一个诊断信息并终止程序执行,如果为非零,则该宏什么事 也不做。 表 1.1 是 CRect 的主要成员函数。 表 1.1 CRect 类主要成员函数 Width Height Size TopLeft BottomRight CenterPoint SetRect CopyRect EqualRect NormalizeRect OffsetRect 计算 CRect 的宽度 计算 CRect 的高度 计算 CRect 的大小,返回 CSize 对象 返回 CRect 左上角的 CPoint 对象 返回 CRect 右下角的 CPoint 对象 返回 CRect 的中心点 设置 CRect 的尺寸 拷贝参数 CRect 对象 判断 CRect 是否与给定矩形相等 使 CRect 的尺寸正常化 按给定量偏移 CRect SubtractRect Operators operator = operator == 矩形相减,尺寸可能不正常 CRect 的重载赋值运算符 CRect 重载两矩形是否相等运算符 34 C++程序设计实践教材 第一章 程序设计同步实验指导 operator != operator += operator -= operator &= operator |= operator + operator - operator & operator | CRect 重载两矩形是否不相等运算符 添加偏移到 CRect 或扩展 CRect 减少 CRect 偏移或缩小 CRect CRect 取 CRect 与定矩形的交 CRect 取 CRect 与定矩形的并 添加偏移到 CRect 或扩展 CRect ,然后返回结果 CRect 对象 减少 CRect 偏移或缩小 CRect ,并返回结果 CRect 对象 创建 CRect 与给定矩形的公共部分(交集)并返回结果 CRect 对象 创建 CRect 与给定矩形的合并部分(并集)并返回结果 CRect 对象 4. 参考题 3 内容,编程使用 MFC 的简单数据类型,并设计数据测试这些类, 用数据形式(而不是图形)输出测试结果(如输出点的坐标,输出矩形的左上角 坐标等)。包含 afxwin.h 头文件。(可选) 在控制台或基于 Win32 的应用程序中使用 MFC 类,应在创建工程后,为工 程设置使用 MFC,方法如下: (1)选择 Project|Settings?菜单,打开 Project Settings 对话框,在 General 页面, Microsoft foundation Classes 列表框中,将缺省值 Not Using MFC 改为 Use MFC in a Static Library 或 Use MFC in a Shared DLL,如图 1.9; 图 1.9 为 Win32 或 Console Application 设置使用 MFC 类 (2)重新 Build 应用程序并执行。 5. 改善分数类,将比较、加、减、乘、除改为重载的运算符。 实验十三 数组与多维数组 一、实验目的 35 第一章 控制台应用程序 1. 熟练应用数组与多维数组。 2. 数组作为函数参数的函数定义及调用方法。 二、实验内容 1. 范例:求一个 3×4 矩阵中的最大元素,将求矩阵中的最大元素的过程定 义为一个函数。函数的第一个参数是矩阵本身,第二个参数是第一维的大小。这 种方法的优点是使函数具有通用性,即无论一个矩阵的第一维是多大,只要该矩 阵的第二维是 4 个元素,都可用该函数求最大元素;也可用该函数求一个矩阵 开始几行中的最大元素。 #include int max_value(int array[][4], int k); int main(){ int a[3][4] = {{1,3,6,7},{2,4,6,8},{15,17,34,12}}; cout << max_value(a,3)<<'\\n'; return 0; } int max_value(int array[][4], int n){ int i,j, max = array[0][0]; for(i = 0; i < n; i++) for(j = 0; j < 4; j++) if (array[i][j] > max) max = array[i][j]; return (max); } C++/C 语言的这种处理数组参数地址的方法,缺点在于即使给出了最高维 的大小,编译程序也不会检查数组传递中最高维的大小的潜在错误。试一试在运 行时,先进的计算机系统会不会发现错误?可以在程序中故意出界。 2. 范例:分别编写实现下列字符数组处理的函数,用数组作为参数: 1) char* trim(char s[]) 删除字符串 s 的尾部空格 2) char* leftstring(char s1[], char s2[], int n) 得到指定字符串 s1 中前 n 个字符的子串 s2 3) int index(char s1[], char s2[]) 检查字符串 s2 是否为字符串 s1 的子串,根据查找结果返回 s2 在 s1 中的开始 位置,不成功返回 -1 #include void leftstring(char s1[], char s2[], int n); int index(char s1[], char s2[]); int main(){ 36 C++程序设计实践教材 第一章 程序设计同步实验指导 char str1[]=\ int n; \ cout<<\包含尾部空格的串str1:\长度为:\ trim(str1); cout<<\无尾部空格的串str1:\长度为:\ leftstring(str1,str3,3); cout<<\串str3:\长度为:\ cout<<\串str2为:\ n=index(str1,str2); if(n!=-1) cout<<\串str1包含子串str2,从第\字符开始(由0开始计数)。\ else cout<<\串str1不包含子串str2\ return 0; } void trim(char s[]){ int i=0; while(s[i]!='\\0') i++; i--; while(s[i]==' ') s[i--]='\\0'; } leftstring(char s1[], char s2[], int n){ void int i; for(i=0;i } int index(char s1[], char s2[]){ bool b=0; int i,j,n=-1,n1=strlen(s1),n2=strlen(s2); for(i=0;i if(s1[i]==s2[0]){ b=1; for(j=1;j if(s1[i+j]!=s2[j]){ b=0; break; } } } if(b==1) {n=i;break;} } return n; } 3. 编程:使用递归和非递归两种方法编写函数 itoa0(int n, char s[],int b),将 整数 n 转换为以 b 为基(例如以 16 为基的十六进制)的数字字符数组。 37 第一章 控制台应用程序 实验十四 指针与数组 一、实验目的 数组在处理同类型的多个数据问题时非常有效,是 C++的重要数据类型。指 针是 C++最灵活最有特色的部分,没有熟练掌握指针,则不能说学会了 C++。但 指针的教学必须有重点,重点放在数组与指针之间的密切关系。通过实践要求掌 握: 1. 指针的定义和使用。 2. 指针与数组的相互关系。 3. 数组或指针作为函数参数的函数定义及调用方法。 4. C 字符串与运算。 5. 标准 string 串。 二、实验内容 1. 范例:判断用户输入的 C 字符串是否为\回文\,所谓\回文\是指顺读和反 读都一样的串,例如串 12321、madam。 #include char carray[SIZE]; int i,len, is_palindrome = 1; cout << \ input a striing ..\\n\ cin.get(carray, SIZE); len = strlen(carray); for (i=0;i if (carray[i] != carray[len-1-i]){ is_palindrome = 0; break; } } if (is_palindrome) cout<<\ else cout<<\ return 0; } [实验要求] 重新定义回文为:滤去所有非字母字符(包括空格)后,不考虑字 母的大小写,从左向右和从右向左读都一样的词或短语,下面是两个回文的例子: Madam, I'm adam Golf, No Sir, prefer prison flog! 编程:编写一个程序,判断输入的字符串是否为回文。并使用指针形式访问 数组元素。 2. 范例:将实验十三题 1 的函数参数分别改用二级指针和一级指针完成。(可 38 C++程序设计实践教材 第一章 程序设计同步实验指导 选) #include int max_value(int (*array)[4], int k);//二级指针 int max_value1(int *arr,int n);//一级指针 int main(){ int a[3][4] = {{1,3,6,7},{2,4,6,8},{15,17,34,12}}; int*b=(int*)a; cout << max_value(a,3)<<'\\n'; cout << max_value1(b,3*4)<<'\\n'; return 0; } int max_value(int (*array)[4], int n){ int i,j, max = array[0][0]; for(i = 0; i < n; i++) for(j = 0; j < 4; j++) if (array[i][j] > max) max = array[i][j]; return (max); } int max_value1(int *arr, int n){ int i, max = arr[0]; for(i = 0; i < n; i++) if (arr[i] > max) max = arr[i]; return (max); } 3. 范例:按一定的规则可以将一个字符串经加密转换为一个新的串,例如 加密的简单方法是当为'a'~'y'的小写字母时用后一个字母代替前一个字母,其 中'z'变换为'a',其他字符时不变。例如: 原串为 This is a secret code! 加密后的串为 Tijt jt b tfdsfu dpef! 编写一个程序对输入串加密,输出加密前和加密后的串,再将加密后的字符串解 密输出。 #include while(*s!='\\0'){ if(*s>96&&*s<122) *s=*s+1; else if(*s==122) *s='a';//注意else不可少,否则当字符为y时,先变为z,再变为a s++; } } 39 第一章 控制台应用程序 void desecret(char* s){ while(*s!='\\0'){ if(*s>97&&*s<123) *s=*s-1; else if(*s==97) *s='z';//注意else不可少,否则当字符为b时,先变为a,再变为z s++; } } int main(){ char st[]=\ cout< 编程:自己另设计一个带密钥的加密算法,例如密钥是一个常数,字符串加 密的方法是将每个字符的 ASCII 码值加上该常数,然后对 128 求模。编写程序, 以密钥将输入的字符串加密输出,再以相同的密钥,将加密字符串解密输出。 4. 编程:重新编写实验十三题 2 的字符串处理函数,用指针作为参数(可 选): 1) char* trim(char *s) 删除字符串 s 的尾部空格 2) char* leftstring(char *s1, char *s2, int n) 得到指定字符串 s1 中前 n 个字符的子串 s2 3) int index(char *s1, char *s2) 检查字符串s2是否为字符串s1的子串,根据查找结果返回s2在s1中的开始位 置,不成功返回 -1 5. 编程:使用标准字符串 string,实现常见的串运算。注意这里 string 是类 (class)。 实验十五 模板 一、实验目的 1. 掌握函数模版的编写方法。 2. 掌握类模版的定义和使用的方法。 二、实验内容 1. 编程:建立求数组元素中最小值的函数模板。 2. 范例:将实验十的集合类改造为模板类,集合元素可以是字符、整数、 枚举类型等等。 40
正在阅读:
C++程序设计实践样例04-30
2021年部编版一年级下册语文笔画练习(精选15道)07-27
经济学原理对应练习 2905-02
医疗器械生产质量管理规范涉及的程序文件与记录(整理).docx04-20
浅谈行动导向法在高职课程教学中的运用03-24
父母作文之写父母对自己的爱的作文提纲11-08
不让小组合作学习流于形式05-31
2012年中考英语作文写作复习系列(1)06-16
- 多层物业服务方案
- (审判实务)习惯法与少数民族地区民间纠纷解决问题(孙 潋)
- 人教版新课标六年级下册语文全册教案
- 词语打卡
- photoshop实习报告
- 钢结构设计原理综合测试2
- 2014年期末练习题
- 高中数学中的逆向思维解题方法探讨
- 名师原创 全国通用2014-2015学年高二寒假作业 政治(一)Word版
- 北航《建筑结构检测鉴定与加固》在线作业三
- XX县卫生监督所工程建设项目可行性研究报告
- 小学四年级观察作文经典评语
- 浅谈110KV变电站电气一次设计-程泉焱(1)
- 安全员考试题库
- 国家电网公司变电运维管理规定(试行)
- 义务教育课程标准稿征求意见提纲
- 教学秘书面试技巧
- 钢结构工程施工组织设计
- 水利工程概论论文
- 09届九年级数学第四次模拟试卷
- C++
- 程序设计
- 实践
- 2018年度岗位升级考核公共班练习题
- DIN 材料牌号 CuAL10Fe5Ni5-C-GS
- JAVA习题4
- 自考法制史历年试题答案
- 医药淀粉项目可行性研究报告 - 图文
- 食品用纸包装生产许可实施细则 - 图文
- 培养学生良好的听课习惯
- 专业技术人员继续教育《诚信建设题库及答案》 (准确度高)
- 2015-2016学年第二学期小学一二年级体育与健康教案
- 2016苏教版语文必修四第2专题《一滴眼泪换一滴水》word导学案
- 180个高考常考的词性转换词
- 实验八 旋转圆盘电极法测定电极过程动力学参数-肖时英
- 2011年工作总结2012年工作打算(11月28日)
- 最新人教版小学语文六年级下册第6课北京的春节
- 打印 化学式与化合价习题和答案-人教版初三化学第四单元课题4
- 基于KPI的部门绩效指标选取(华夏基石)
- 微型桩(钢管桩)专项施工方案
- 国测管字(2009)13号_国家测绘局关于印发测绘资质管理规定和测绘
- 部编版二年级语文上册《语文园地三》教案
- 重读有重感:英国作家萨克雷的《名利场》