华 中 科 技 大 学 C 语 言 课 程 实 验 报 告
@
目录实验1 表达式和标准输入与输出实验
1.1 实验目的
(1)熟练掌握各种运算符的运算功能,操作数的类型,运算结果的类型及运算过程中的类型转换,重点是C语言特有的运算符,例如位运算符,问号运算符,逗号运算符等;熟记运算符的优先级和结合性。
(2)掌握getchar, putchar, scanf 和printf 函数的用法。
(3)掌握简单C程序(顺序结构程序)的编写方法。
1.2 实验内容
1 源程序改错
下面给出了一个简单C语言程序例程,用来完成以下工作:
(1)输入华氏温度f,将它转换成摄氏温度c后输出;
(2)输入圆的半径值r,计算并输出圆的面积s;
(3)输入短整数k、p,将k的高字节作为结果的低字节,p的高字节作为结果的高字节,拼成一个新的整数,然后输出;
在这个例子程序中存在若干语法和逻辑错误。要求参照1.3和1.4的步骤对下面程序进行调试修改,使之能够正确完成指定任务。
1. #include<stdio.h>
2. #define PI 3.14159;
3. void main( void )
4. {
5. int f ;
6. short p, k ;
7. double c , r , s ;
8. /* for task 1 */
9. printf("Input Fahrenheit:") ;
10. scanf("%d", f ) ;
11. c = 5/9*(f-32) ;
12. printf( "\n %d (F) = %.2f (C)\n\n", f, c ) ;
13. /* for task 2 */
14. printf("input the radius r:");
15. scanf("%f", &r);
16. s = PI * r * r;
17. printf("\nThe acreage is %.2f\n\n",&s);
18. /* for task 3 */
19. printf("input hex int k, p :");
20. scanf("%x %x", &k, &p );
21. newint = (p&0xff00)|(k&0xff00)<<8;
22. printf("new int = %x\n\n",newint);
23.}
解答:
1)第2行的符号常量定义后不能有分号,正确形式为:#define PI 3.14159
2)第5行的f类型错误,正确形式为:double f ;
3)第10行的格式符错误,正确形式为:scanf("%lf",&f);
4)第 11 行 c 的类型为 double,正确形式为:c = 5.0/9 * (f-32) ;
5)第 12 行格式符错误,正确形式为:printf( "\n %.2lf (F) = %.2lf (C)\n\n ", f, c ) ;
6)第 15 行格式符错误,正确形式为:scanf("%lf",&r);
7)第 17 行printf用法错误,输出不应是地址,正确形式为:printf("\nThe acreage is %.2lf\n\n",s)
8)第 21 行使用位声明变量,且算法错误,正确形式为:int newint = (p&0xff00) | ((k&0xff00)>>8) ;
2 程序设计
(1)输入字符c,如果c是大写字母,则将c转换成对应的小写,否则c的值不变,输入Ctrl+Z程序结束。要求①用条件表达式;②字符的输入输出用getchar和putchar函数。程序应能循环接受用户的输入,直至输入Ctrl+Z程序结束。
(1)解答:
1.#include<stdio.h>
2.int main()
3.{
4. char c;
5. while((c=getchar())!=EOF)
6. {
7. if(c>='A'&&c<='Z')//检验范围
8. putchar(c+32);//根据ASCII表,大小写字母差值为32
9. else
10. putchar(c);
11. }
12. return 0;
13.}
(2)输入无符号短整数x,m,n(0 ≤m≤ 15, 1 ≤ n≤ 16-m),取出x从第m位开始向左的n位(m从右至左编号为0~15),并使其向左端(第15位)靠齐。要求:①检查m和n的范围;②x的值以十六进制输入,m和n以十进制输入;③结果以十六进制输出。
(2)解答:
1.#include <stdio.h>
2.int main() {
3. unsigned short x;
4. unsigned short m, n;
5. scanf("%hx%hd%hd", &x,&m,&n);
6. if(m>15||m<0||n<1||n>16-m)
7. {
8. printf("输入错误!");
9. }
10. else{
11.
12. unsigned short a = (x>>(m-1));//顶到最右边
13. unsigned short result = (a<<(15-n));//向左靠齐
14.
15. printf("%hx", result);}
16.
17. return 0;
18.}
(3)IP地址通常是4个用句点分隔的小整数(即点分十进制),但这些地址在机器中是用一个无符号长整型数表示的。例如3232235876,其机内二进制表示就是11000000 10101000 00000001 01100100,按照8位一组用点分开,该IP地址就写成192.168.1.100。
读入无符号长整型数表示的互联网IP地址,对其译码,以常见的点分十进制形式输出。要求循环输入和输出,直至输入Ctrl+Z结束。
(3)解答:
1.#include <stdio.h>
2.
3.int main()
4.{
5. int x;
6. while (scanf("%d", &x) != EOF) {
7.
8. int a = (x >> 24) & 0xFF; // 第一个八位
9. int b = (x >> 16) & 0xFF; // 第二个八位
10. int c = (x >> 8) & 0xFF; // 第三个八位
11. int d = x & 0xFF; // 第四个八位
12. printf("%d.%d.%d.%d\n", a, b, c, d);
13. }
14. return 0;
15.}
1.3 实验小结
在完成这次实验后,我获得了以下几点体会和经验:
1.重视细节,善于纠错: 在C语言中,细节非常重要。一个小小的语法错误或逻辑错误都可能导致程序无法正常工作。通过这次实验,我了解了各种常见错误的原因和报错显示,例如全半角逗号分号会报错未识别字符,scanf后面的变量忘记加&会报错C4477,#define后加分号可能导致后面变量被识别为指针,VS2022需要使用scanf_s以保证安全性等等。
2.输入输出函数的熟练使用: scanf 和 printf 是C语言中常用的输入输出函数。通过实验,我熟悉了几种常见格式字符的用法,和两个函数的使用方法
3.程序结构: 这个实验强调了顺序结构程序的编写。在实际编程中,理解程序的结构和流程对于正确完成任务非常重要。同时,实验还涉及了循环输入,通过实验,我了解了while的用法和EOF的概念,学会如何循环输入和结束输入,对程序的输入输出有了更深的了解。
4.流程图的画法:通过实验,我了解visio软件的基本使用,熟悉了用流程图表示程序结构,整理思路。
实验2 流程控制实验
2.1 实验目的
(1)掌握复合语句、if语句、switch语句的使用,熟练掌握for、while、do-while三种基本的循环控制语句的使用,掌握重复循环技术,了解转移语句与标号语句。
(2)练习循环结构for、while、do-while语句的使用。
(3)练习转移语句和标号语句的使用。
(4)使用集成开发环境中的调试功能:单步执行、设置断点、观察变量值。
2.2 实验内容及要求
1.程序改错
下面的实验2-1程序是合数判断器
(合数指自然数中除了能被1和本身整除外,还能被其它数整除的数),在该源程序中存在若干语法和逻辑错误。
要求对该程序进行调试修改,使之能够正确完成指定任务。
/* 实验2-1改错题程序:合数判断器*/
1.#include <stdio.h>
2.int main( )
3.{
4.int i, x, k, flag = 0;
5.printf("本程序判断合数,请输入大于1的整数,以Ctrl+Z结束\n");
6.while (scanf("%d", &x) !=EOF) {
7.for(i=2,k=x>>1;i<=k;i++)
8. if (!x%i) {
9. flag = 1;
10. break;
11. }
12.if(flag=1) printf("%d是合数", x);
13.else printf("%d不是合数", x);
14.}
15.return 0;
16.}
解答:
(1)错误修改:
3)第4行flag定义为0后在循环开始时没有归0,正确形式为:在第六行后加语句flag = 0;
2)第8行运算优先级错误,正确形式为:if (!(x % i))
3)第12行运算符错误,不应为赋值符,正确形式为:if (flag == 1)
2.程序修改替换
(1)修改实验2-1程序,将内层两出口的for循环结构改用单出口结构,即不允许使用break、goto等非结构化语句。
(1)解答:
程序等价为当flag=1后退出循环,可以在for循环中添加一个判断条件,
因此,题目(1)替换后的程序如下所示:
1.#include <stdio.h>
2.int main()
3.{
4. int i, x, k, flag = 0;
5. printf("本程序判断合数,请输入大于1的整数,以Ctrl+Z结束\n");
6. while (scanf("%d", &x) != EOF)
7. {
8. flag = 0;
9. for (i = 2, k = x >> 1; i <= k&&!flag; i++)
10. if (!(x % i)) {
11. flag = 1;
12. }
13. if (flag == 1) printf("%d是合数\n", x);
14. else printf("%d不是合数\n", x);
15. }
16. return 0;
17.}
(2)修改实验2-1程序,将for循环改用do-while循环。
(2)解答:
由于do-while循环先进行do操作再进行判断,循环开始前需先获取一次x的值,因此,题目(2)替换后的程序如下所示:
1.#include <stdio.h>
2.int main()
3.{
4. int i, x, k, flag = 0;
5. printf("本程序判断合数,请输入大于1的整数,以Ctrl+Z结束\n");
6. scanf("%d", &x);
7. do
8. {
9. flag = 0;
10. for (i = 2, k = x >> 1; i <= k; i++)
11. if (!(x % i)) {
12. flag = 1;
13. break;
14. }
15. if (flag == 1) printf("%d是合数\n", x);
16. else printf("%d不是合数\n", x);
17. } while (scanf("%d", &x) != EOF);
18. return 0;
19.}
(3)修改实验2-1程序,将其改为纯粹合数求解器,求出所有的3位纯粹合数。一个合数去掉最低位,剩下的数仍是合数;再去掉剩下的数的最低位,余留下来的数还是合数,这样反复,一直到最后剩下一位数仍是合数,这样的数称为纯粹合数。
(3)解答:
根据题意,写出两个辅助函数判断是否为纯粹合数,再遍历三位数,得到答案,因此,题目(3)替换后的程序如下所示:
1.#include <stdio.h>
2.int isHeshu(int x){//判断是否是合数
3. int i, k, flag; flag = 0;
4. for (i = 2, k = x >> 1; i <= k; i++)
5. if (!(x % i)) {
6. flag = 1;break; }
7. if (flag == 1) return 1;
8. else return 0;
9.}
10.int PureHeshu(int n){//判断是否是纯粹合数
11. int ret=0;
12. if (isHeshu(n))
13. { n /= 10;
14. if (isHeshu(n)) {
15. n /= 10;
16. if (isHeshu(n)) {
17. ret = 1; } } }
18. return ret;}
19.int main(){
20. for (int m = 100; m < 1000; m++)
21. { if (PureHeshu(m))
22. printf("%d ", m); }
23. return 0;}
3.程序设计
(1)假设工资税金按以下方法计算:x < 1000元,不收取税金;1000 ≤ x < 2000,收取5%的税金;2000 ≤ x < 3000,收取10%的税金;3000 ≤ x < 4000,收取15%的税金;4000 ≤ x < 5000,收取20%的税金;5000 ≤ x,收取25%的税金。(注意税金的计算按照阶梯计税法,比如,工资为4500,那么税金=10005% + 100010% + 100015% + 50120%)。编写一个程序,输入工资金额,输出应收取税金额度,要求分别用if语句和switch语句来实现。
(1)解答:
1)解题思路
1.输入x,根据实际情况,x声明为double
2.根据x的大小进行选择判断,计算税金
3.打印结果;
4.结束
2)源程序清单
/* if实现版本*/
1.#include <stdio.h>
2.int main()
3.{ double x, tax;
4. printf("请输入工资:");
5. scanf("%lf", &x);
6. if (x < 1000) tax = 0;
7. if (x >= 1000 && x < 2000) tax = (x+1 - 1000) * 0.05;
8. if (x >= 2000 && x < 3000) tax = 1000*0.05+(x+1-2000) * 0.1;
9. if (x >= 3000 && x < 4000) tax = 1000 * 0.05 + 1000*0.1+(x+1 - 3000) * 0.15;
10. if (x >= 4000 && x < 5000) tax = 1000 * 0.05 + 1000 * 0.1 + 1000*0.15+(x+1 - 4000) * 0.2;
11. if (x >= 5000) tax = 1000 * 0.05 + 1000 * 0.1 + 1000 * 0.15 +1000*0.2+(x+1 - 5000) * 0.25;
12. printf("\n应收税金%lf元\n", tax);
13.}
/* switch实现版本*/
1.#include <stdio.h>
2.int main()
3.{
1. double x, tax;
5. printf("请输入工资:");
6. scanf("%lf", &x);
7. int a =(int) x / 1000;
8. switch (a) {
9. case 0:tax = 0;
10. break;
11. case 1:tax = (x + 1 - 1000) * 0.05;
12. break;
13. case 2:tax = 1000 * 0.05 + (x + 1 - 2000) * 0.1;
14. break;
15. case 3:tax = 1000 * 0.05 + 1000 * 0.1 + (x + 1 - 3000) * 0.15;
16. break;
17. case 4:tax = 1000 * 0.05 + 1000 * 0.1 + 1000 * 0.15 + (x + 1 - 4000) * 0.2;
18. break;
19. default:tax = 1000 * 0.05 + 1000 * 0.1 + 1000 * 0.15 + 1000 * 0.2 + (x + 1 - 5000) * 0.25;
20. break;
21.}
22. printf("\n应收税金%lf元\n", tax);
23. return 0;
24.}
(2)输入一段以!结尾的短文(最多5行,每行不超过50个字符),要求将它复制到输出,复制过程中将每行一个以上的空格字符用一个空格代替。
(2)解答:
1.#include <stdio.h>
2.int main() {
3. char input[5][51]; char c;
4. int line = 0; int charCount = 0; int spaceCount = 0;
5. while ((c = getchar()) != '!' && line < 5){
6. if (c == ' ') {
7. spaceCount++; //空格计数
8. if (spaceCount <= 1) { //保证只有一个空格
9. input[line][charCount] = c;
10. charCount++;
11. }
12. }
13. else {
14. spaceCount = 0; //归零空格计数
15. input[line][charCount] = c; //将c存入数组
16. charCount++;
17. }
18. if (c == '\n') {
19. input[line][charCount] = '\0'; //添加终止符并换行
20. line++;
21. charCount = 0;
22. spaceCount = 0;
23. }
24. }
25. input[line][charCount] = '!'; //添加结尾
26. input[line][charCount + 1] = '\0';
27. for (int i = 0; i <= line; i++) {
28. printf("%s", input[i]); } //打印短文
29. return 0;
30.}
(3)打印如下的杨辉三角形。
1 /*第0行 */
1 1 /*第1行 */
1 2 1 /*第2行 */
1 3 3 1
1 4 6 4 1
1 5 10 10 5 1
1 6 15 20 15 6 1
1 7 21 35 35 21 7 1
1 8 28 56 70 56 28 8 1
1 9 36 84 126 126 84 36 9 1
第i行第j列位置的数据值可以由组合表示
根据以上公式,采用顺推法编程,输入最后一行的编号N(0<=N<=6),要求输出金字塔效果的杨辉三角形。
特别要注意空格的数目,一位数之间是3个空格,两位数之间有2个空格,3位数之间只有一个空格。第N行行首是N个空格。每行末尾是3个空格和换行。
(3)解答:
1) 解题思路
1.输入整数N
2.利用for循环打印N个空格,并用第二个for循环控制每行空格的数量比上一行少两个
3.利用递推关系求出coef
4.利用双层循环打印出杨辉三角
5.结束
2)源程序清单:
1. #include <stdio.h>
2.int main() {
3. int N;
4. scanf("%d", &N);
5. for (int i = 0; i <= N; i++) {
6. for (int a = 1; a <= N; a++) {
7. printf(" ");
8. }
9. for (int space = 1; space <= N - i; space++) {
10. printf(" ");
11. }
12. int coef = 1;
13. for (int j = 0; j <= i; j++) {
14. printf("%d", coef);
15. if (coef < 10)
16. printf(" ");
17. if (coef >= 10)
18. printf(" ");
19. coef = coef * (i - j) / (j+1);
20. }
21. printf("\n");
22. }
23. return 0;
24.}
(4)625这个数很特别,625的平方等于390625,其末3位也是625。请编程输出所有这样的3位数:它的平方的末3位是这个数本身。要求这些数字从小到大排列,每个数字单独占一行。
(4)解答:
1.#include <stdio.h>
2.#include <math.h>
3.int main()
4.{
5. for (int i = 100; i < 1000; i++)
6. {
7. int a = pow(i, 2);
8. if (a % 1000 == i)
9. {
10. printf("%d\n", i);
11. }
12. return 0;
13.}
2.3 实验小结
在本实验中,我探索了复合语句、if语句、switch语句,以及for、while、do-while等循环控制语句的使用,还了解了转移语句和标号语句的应用。此外,我还学习了如何使用集成开发环境(IDE)的调试功能,包括单步执行、设置断点以及观察变量值。在完成这次实验后,我获得了以下几点体会和经验:
1.善于纠错:在编写程序时,仍然经常会遇到语法错误,例如拼写错误、缺少分号、括号不匹配等。这些错误可以导致程序无法编译或运行。通过检查代码,查看IDE提供的错误消息来识别和纠正语法错误。
2.重视逻辑,学会调试:在程序中,尤其是使用循环可能会出现逻辑错误,导致程序的输出不符合预期,或陷入死循环。我们可以使用调试工具,例如设置断点、单步执行,观察程序的执行过程,和中间变量的值,判断错误原因。
3.善于选择合适结构:通过实验,我了解每种循环结构和选择结构的特点和用途,知道了while和do-while的区别,if和switch的区别,学会如何选择适合特定情况的循环结构。
4.更多样结构的流程图画法:通过实验,我熟悉visio软件的基本使用,知道了如何用流程图表示循环结构和选择结构整理思路。
实验3 函数与程序结构实验
3.1实验目的
(1)熟悉和掌握函数的定义、声明;函数调用与参数传递,函数返回值类型的定义和返回值使用。
(2)熟悉和掌握不同存储类型变量的使用。
(3)练习使用集成开发环境中的调试功能:单步执行、设置断点、观察变量值。
3.2实验内容
1.程序改错题
下面是计算s=1!+2!+3!+…+n!的源程序(n<20)。在这个源程序中存在若干语法和逻辑错误。要求对该程序进行调试修改,使之能够输出如下结果:
k=1 the sum is 1
k=2 the sum is 3
k=3 the sum is 9
……
k=20 the sum is 2561327494111820313
/实验3-1改错题程序:计算s=1!+2!+3!+…+n!/
1.#include <stdio.h>
2.int main(void)
3.{
4. int k;
5. for(k=1;k<=20;k++)
6. printf("k=%d\tthe sum is %ld\n",k,sum_fac(k));
7. return 0;
8.}
9.long sum_fac(int n)
10.{
11. long s=0;
12. int i,fac;
13. for(i=1;i<=n;i++)
14. fac*=i;
15. s+=fac;
16. return s;
17.}
解答:
(1)错误修改:
1)第3行未声明sum-fac函数,正确形式为:
long long sum_fac(int n);
2)第9行的函数返回值类型出错,正确形式为:
long long sum_fac(int n);
3)第11行s的数据类型出错,正确形式为:long long s = 0;
4)第12行fac的数据类型出错且未初始化,正确形式为:
long long fac = 1;
2.程序修改替换题
(1)根据将实验3-1改错题程序中sum_fac函数修改为一个递归函数,用递归的方式计算。
解答:
替换后的程序如下所示:
1.#include <stdio.h>
2.int main(void)
3.{
4. long long sum_fac(int n);
5. int k;
6. for (k = 1; k <= 20; k++)
7. printf("k=%d\tthe sum is %lld\n", k, sum_fac(k));
8. return 0;
9.}
10.long long sum_fac(int n)
11.{
12. long long s = 0;
13. long long i, fac = 1;
14. for (i = 1; i <= n; i++) {
15. fac *= i;
16. }
17. s += fac;
18. if (n == 1)
19. return s;
20. else
21. return s + sum_fac(n - 1);
22.}
(2)下面是计算e^x麦克劳林展开的源程序,其中x是浮点数,n是整数。从键盘输入x和n,然后计算s的值。修改该程序中的sum和fac函数,使之计算量最小。
/实验3-2程序修改替换第(2)题程序:根据公式计算 s/
1.#include<stdio.h>
2.double mulx(double x,int n);
3.long fac(int n);
4.double sum(double x,int n)
1.{
5. int i;
6. double z=1.0;
7. for(i=1;i<=n;i++)
8. {
9. z=z+mulx(x,i)/fac(i);
10. }
11. return z;
12. }
13. double mulx(double x,int n)
2.{
14. int i;
15. double z=1.0;
16. for(i=0;i<n;i++)
17. {
18. z=z*x;
19. }
20. return z;
21. }
22. long fac(int n)
3. {
23. int i;
24. long h=1;
25. for(i=2;i<=n;i++)
26. {
27. h=h*i;
28. }
29. return h;
30. }
31. int main()
32. {
33. double x;
34. int n;
35. printf("Input x and n:");
36. scanf("%lf%d",&x,&n);
37. printf("The result is %lf:",sum(x,n));
38. return 0;
39. }
解答:
采用静态数据类型优化,修改后的程序如下所示:
1.#include <stdio.h>
2./* 计算s=1+x+x2/2!+x3/3! */
3.double mulx(double x)
4.{
5. static double z = 1.0;
6. z *= x;
7. return z;
8.}
9.long fac(int n)
10.{
11. static long f = 1;
12.//静态局部变量,静态局部变量使用static修饰符定义,
13.//即使在声明时未赋初值,编译器也会把它初始化为0。且静态局部变量存储于进程的
14.//全局数据区,即使函数返回,它的值也会保持不变。
15. f *= n;
16. return f;
17.}
18.double sum(double x, int n)
19.{
20. int i;
21. double z = 1.0;
22. for (i = 1; i <= n; i++)
23. {
24. z = z + mulx(x) / fac(i);
25. }
26. return z;
27.}
28.int main() {
29. double x;
30. int n;
31. printf("Input x and n:");
32. scanf("%lf%d", &x, &n);
33. printf("The result is %lf:", sum(x, n));
34. return 0;
35.}
3.跟踪调试题
下面是计算fabonacci数列前n项和的源程序,现要求单步执行该程序,在watch窗口中观察Ik,sum,n值。具体操作如下:
(1)设输入5,观察刚执行完“scanf("%d",&k);”语句时,sum、k的值是多少?
(2)在从main函数第一次进入fabonacci函数前的一刻,观察各变量的值是多少?返回后光条停留在哪个语句上?
(3)在从main函数第一次进入fabonacci函数后的一刻,观察光条从main函数“sum+=fabonacci(i);”语句调到了哪里?
(4)在fabonacci函数内部单步执行,观察函数的递归执行过程。体会递归方式实现的计算过程是如何完成数计算的,并特别注意什么时刻结束递归,然后直接从第一个return语句返回到了哪里?
(5)在fabonacci函数递归执行过程中观察参数n的变化情况,并回答为什么k、sum在fabonacci函数内部不可见?
/实验3-3跟踪调试题程序:计算fabonacci数列前n项和/
1.#include<stdio.h>
2.int main(void)
3.{
4. int i,k;
5. long sum=0,fabonacci(int n);
6. printf("Inut n:");
7. scanf("%d",&k);
8. for(i=1;i<=k;i++){
9. sum+=fabonacci(i);
10. printf("i=%d\tthe sum is %ld\n",i,sum);
11. }
12. return 0;
13.}
14.long fabonacci(int n)
15.{
16. if(n==1 || n==2)
17. return 1;
18. else
19. return fabonacci(n-1)+fabonacci(n-2);
20.}
解答:
(1)sum,k的值分别是0和5。
(2)如图,sum,k,i的值分别为0,5,1,光条在sum+=fabonacci(i);语句前。
(3)光条调到了fabonacci函数体的开始,如图所示:
![](file://C:/Users/muke/Documents/Gridea/post-images/1700494376523.png)
(4)观察递归可发现,当n=1或2时,函数直接返回1,当n>=3时,函数调用自身两次,分别计算fabonacci(n-1) 和 fabonacci(n-2),若fabonacci(n-1) 和 fabonacci(n-2)中n-1或n-2>=3,函数会继续调用自身,直到n=1或2。当结束时,光条回到sum += fabonacci(i);处,如图:
![](file://C:/Users/muke/Documents/Gridea/post-images/1700494405575.png)
(5)设输入3,n的值经历了从1-2-3-2-3-1-3的转变,符合上一问中所解释的递归调用过程。定义在函数内部的变量称为局部变量(Local Variable),它的作用域仅限于函数内部, 离开该函数后就是无效的,k,sum定义在main函数内,只在 main 函数内部可见。fabonacci 函数只能访问自己的参数 n,而不能访问 main 函数中的局部变量 k 和 sum。
![](file://C:/Users/muke/Documents/Gridea/post-images/1700494463644.png)
4.程序设计
(1)编程验证歌德巴赫猜想:任何一个大于等于4的偶数都是两个素数之和。要求设计一个函数,接受形参n,以“n=n1+n2”的形式输出结果,若有多种分解情况,取n1最小的一个输出。
例如:n=6,输出“6=3+3”。
main函数循环接收从键盘输入的整数n,如果n是大于或等于4的偶数,调用上述函数进行验证。
(1)解答:
1) 算法流程如图3.9所示
![](file://C:/Users/muke/Documents/Gridea/post-images/1700494520909.png)
2)源程序清单
1.#include<stdio.h>
2.#include<math.h>
3.int isPrime(int x)//素数
4.{
5. int ret = 1;
6. int i;
7. if (x == 1 || (x % 2 == 0 && x != 2))
8. ret = 0;
9. for (i = 3; i < sqrt(x); i += 2)
10. {
11. if (x % i == 0)
12. {
13. ret = 0;
14. break;
15. }
16. }
17. if (ret == 1)
18. return ret;
19.}
20.void gedebahe(int n)//哥德巴赫猜想的函数和输出
21.{
22.
23. for (int i = 2; i <= n / 2; i++)
24. {
25. if (isPrime(i) && isPrime(n - i))
26. {
27. printf("%d=%d+%d\n", n, i, n - i);
28. return;
29. }
30. }
31.}
32.
33.int main()
34.{
35. int n;
36. while (scanf("%d", &n) != EOF)
37. {
38. gedebahe(n);
39. }
40. return 0;
41.}
3)测试
(a) 测试数据:
表3-1 编程题1的测试数据
测试用例 程序输入 理论结果
用例1 48 48=5+43
用例2 90 90=7+83
用例3 10 10=3+7
(b) 对应测试数据的运行结果截图
![](file://C:/Users/muke/Documents/Gridea/post-images/1700494616388.png)
2)完全数(Perfect number),又称完美数或完备数,特点是它的所有真因子(即除了自身以外的约数,包括1)之和恰好等于它本身。例如6=1+2+3,28=1+2+4+7+14等。
编程寻找10000以内的所有完全数。
要求设计一个函数,判定形参n是否为完全数,如果是,返回1,否则返回0。在main函数中调用该函数求10000以内的所有完全数,并以完全数的真因子之和的形式输出结果,例如“6=1+2+3”。程序输出中,每个完全数单独占一行。
(2)解答:
1) 算法流程如图3.11所示
![](file://C:/Users/muke/Documents/Gridea/post-images/1700494638114.png)
2)源程序清单
1.#include <stdio.h>
2.int wanshu(int n)
3.{
4. int sum = 0;
5. for (int i = 1; i <= n / 2; i++)
6. {
7. if (n % i == 0) { //找到一个因子
8. sum += i;
9. }
10. }
11. if (sum == n) //如果两者相等
12. {
13. return 1;
14. }
15. else
16. {
17. return 0;
18. }
19.}
20.
21.int main() {
22. for (int num = 1; num <= 10000; num++)
23. {
24. if (wanshu(num))
25. {
26. printf("%d=", num);
27. for (int i = 1; i <= num / 2; i++) {
28. if (num % i == 0) {
29. printf("%d", i);
30. if (i != num / 2) {
31. printf("+");
32. }
33. }
34. }
35. printf("\n");
36. }
37. }
38. return 0;
39.}
3)测试
对应测试数据的运行结果截图
![](file://C:/Users/muke/Documents/Gridea/post-images/1700494667269.png)
(3)自幂数是指一个n位数,它的每个位上的数字的n次幂之和等于它本身。水仙花数是3位的自幂数,除此之外,还有4位的四叶玫瑰数、5位的五角星数、6位的六合数、7位的北斗星数、8位的八仙数等。
编写一个函数,判断其参数n是否为自幂数,如果是,返回1;否则,返回0。要求main函数能反复接收从键盘输入的整数k,k代表位数,然后调用上述函数求k位的自幂数,输出所有k位自幂数,并输出相应的信息,例如“3位的水仙花数共有4个153,370,371,407”。当k=0时程序结束执行。
(3)解答:
1) 算法流程如图3.13所示。
![](file://C:/Users/muke/Documents/Gridea/post-images/1700494714778.png)
2)源程序清单
1. #include <stdio.h>
2.#include <math.h>
3.int shuixianhua(int n) {
4. int t = n;
5. int sum = 0;
6. int d = 0;
7. while (t != 0)
8. {
9. d++;
10. t /= 10;
11. }
12. t = n;
13. while (t != 0)
14. {
15. int a = t % 10;
16. sum += pow(a, d);
17. t /= 10;
18. }
19. if (sum == n)
20. return 1;
21. else
22. return 0;
23.}
24.int main()
25.{
26. int arr[10];
27. int k;
28. while (1)
29. {
30. scanf("%d", &k);
31. if (k == 0) {
32. break;
33. }
34. int count = 0;
35. switch (k)
36. {
37. case 3:
38. printf("%d位的水仙花数共有", k);
39. break;
40. case 4:
41. printf("%d位的四叶玫瑰数共有", k);
42. break;
43. case 5:
44. printf("%d位的五角星数共有", k);
45. break;
46. case 6:
47. printf("%d位的六合数共有", k);
48. break;
49. case 7:
50. printf("%d位的北斗星数共有", k);
51. break;
52. case 8:
53. printf("%d位的八仙数共有", k);
54. break;
55. default:
56. printf("%d位的数共有", k);
57. break;
58. }
59. for (int i = pow(10, k - 1); i < pow(10, k); i++)
60. {
61. if (shuixianhua(i))
62. {
63. arr[count] = i;
64. count++;
65. }
66. }
67. printf("%d个", count);
68. for (count = count - 1; count >= 0; count--)
69. {
70. printf("%d", arr[count]);
71. if (count != 0)
72. {
73. printf(",");
74. }
75.
76. }
77. printf("\n");
78. }
79. return 0;
80.}
3)测试
(a) 测试数据:
表3-2 编程题3的测试数据
测试用例 程序输入 理论结果
用例1 3 3位的水仙花数共有4个407,371,370,153
用例2 4 4位的四叶玫瑰数共有3个9474,8208,1634
用例3 5 5位的五角星数共有3个93084,92727,54748
(b) 对应测试数据的运行结果截图
![](file://C:/Users/muke/Documents/Gridea/post-images/1700494773905.png)
3.3 实验小结
在这次上机实验中,我们旨在熟悉和掌握函数的定义、声明,函数调用与参数传递,函数返回值类型的定义和返回值使用,同时了解不了同存储类型变量的使用。此外,我们练习了使用集成开发环境的调试功能,包括单步执行、设置断点、观察变量值,并借此观察函数递归的过程,以下是我在本次实验中遇到的问题和收获。
1.熟悉了函数的使用:通过实验,我学习了函数的定义,声明,返回值类型和使用,在跟踪调试过程中,我了解的递归的过程,并知道了其缺点,通过调试功能观察到变量在函数调用,递归过程中的变化,对计算机有了更深的了解。
2.纠错能力得到提升:在改错题中,我意识到数据类型错误,却忘记了printf输出中格式符的变化,通过实验,锻炼了我思维的周密性。
3.重视数学与编程相结合:本次实验的程序设计题均为数学相关问题,在实验过程中,经常不知道如何确定循环的终止条件,这时需要借助数学只是判断,如完数一定是偶数,可确定for循环中i<=n/2。
4.了解了算法的优化:通过程序修改替换题,我学会了利用静态数据类型优化算法,减少计算量。在水仙花数题中,通过摸索我知道了可以用数组储存后面需要用到的变量,避免了重复的运算。本次实验对算法思维有一定帮助。
实验4 编译预处理实验
4.1实验目的
(1)掌握文件包含、宏定义、条件编译和assert宏的使用;
(2)练习使用集成开发环境中的调试功能:单步执行、设置断点、观察变量值。
(3)熟悉多文件编译技术
4.2实验内容
1.程序改错
下面是用宏来计算平方差、交换两数的源程序.在这个源程序中存在若干错误,要求对该程序进行调试修改,使之能够正确完成指定任务。
/实验4-1改错与跟踪调试题程序:计算平方差、将换两数/
#include<stdio.h>
#define SUM a+b
#define DIF a-b
#define SWAP(a,b) a=b,b=a
int main()
{
int a,b;
printf("Input two integers a, b:");
scanf("%d%d", &a,&b);
printf("\nSUM=%d\n the difference between square of a and square of b is:%d",SUM, SUM*DIF);
SWAP(a,b);
printf("\nNow a=%d,b=%d\n",a,b);
return 0;
}
2.程序修改替换
下面是用函数实现求三个数中最大数、计算两浮点数之和的程序。在这个源程序中存在若干语法和逻辑错误。
要求:(1)对这个例子程序进行调试修改,使之能够正确完成指定任务;
(2)用带参数的宏替换函数max,来实现求最大数的功能。
/实验4-2程序修改替换题程序/
#include<stdio.h>
int main(void)
{
int a, b, c;
float d, e;
printf("Input three integers:");
scanf("%d %d %d",&a,&b,&c);
printf("\nThe maximum of them is %d\n",max(a,b,c));
printf("Input two floating point numbers:");
scanf("%f %f",&d,&e);
printf("\nThe sum of them is %f\n",sum(d,e));
return 0;
}
int max(int x, int y, int z)
{
int m=z;
if (x>y)
if(x>z) m=x;
else
if(y>z) m=y;
return m;
}
float sum(float x, float y)
{
return x+y;
}
3.跟踪调试
下面程序利用R计算圆的面积s,以及面积s的整数部分。现要求:
(1)修改程序,使程序编译通过且能运行;
(2)单步执行。进入函数integerl_fraction时,watch窗口中x为何值?在返回main时, watch窗口中i为何值?
(3)修改程序,使程序能输出面积s值的整数部分(要求四舍五入),不会输出错误信息assertion failed。
/实验4-3跟踪调试题程序利用R计算圆的面积s/
#define R
int main(void)
{
float r, s;
int s_integer=0;
printf ("Input a number: ");
scanf("%f",&r);
#ifdef R
s=3.14159*r*r;
printf("Area of round is: %f\n",s);
s_integer=integer_fraction(s);
assert((s-s_integer)<0.5);
printf("The integer fraction of area is %d\n", s_integer);
#endif
return 0;
}
int integer_fraction(float x)
{
int i=x;
return i;
}
4.程序设计
(1)三角形的面积是,其中,a,b,c为三角形的三边,要求编写程序用带参数的宏来计算三角形的面积。定义两个带参数的宏,一个用来求s,另一个用来求area。
2)用条件编译方法来编写程序。输入一行英文字符序列,可以任选两种方式之一输出:一为原文输出;二为变换字母的大小写后输出。例如小写‘a’变成大写‘A’,大写‘D’变成小写‘d’,其他字符不变。用#define命令控制是否变换字母的大小写。例如,#define CHANGE 1 则输出变换后的文字,若#define CHANGE 0则原文输出。
(3)假设一个C程序由file1.c和file2.c两个源文件及一个file.h头文件组成,file1.c、file2.c和file.h的内容分别如下所述。试编辑该多文件C程序,补充file.h头文件内容,然后编译和链接。然后运行最后生成的可执行文件。
/源文件file1.c的内容/
#include "file.h"
int x,y; /* 外部变量的定义性说明 */
char ch; /* 外部变量的定义性说明 */
int main(void)
{
x=10;
y=20;
ch=getchar();
printf("in file1 x=%d,y=%d,ch is %c\n",x,y,ch);
func1();
return 0;
}
/*源文件file2.c的内容为:*/
#include "file.h"
void func1(void)
{
x++;
y++;
ch++;
printf("in file2 x=%d,y=%d,ch is %c\n",x,y,ch);
}
标签:函数,int,sum,程序,C语言,实验,printf,软件,实验报告
From: https://www.cnblogs.com/losyi/p/18375810