300字范文,内容丰富有趣,生活中的好帮手!
300字范文 > C语言程序设计第五版谭浩强课后答案 第六章习题答案

C语言程序设计第五版谭浩强课后答案 第六章习题答案

时间:2021-02-07 08:28:31

相关推荐

C语言程序设计第五版谭浩强课后答案 第六章习题答案

1. 用筛选法求100之内的素数

解析:这题的关键是要知道什么是筛选法,👉筛选法。

int main(){int i = 0, j = 0;int arr[100];//录入数字for (i = 0; i < 100; i++){arr[i] = i + 1;}//1不是素数,直接写0,或者在上一步就把0写进去。arr[0] = 0;//这一步是实现筛选法//筛选法实际上就是用后面的数字整除当前数字//如果后面的数字能够整除当前值,则将其排除//按照这样的步骤以次继续,直至到达范围边缘for (i = 0; i < 100; i++){for (j = i + 1; j < 100; j++){//这个if要注意,在第一轮筛选的时候已经把很多数字写0if (arr[j] != 0 && arr[i] != 0){//如果后面的数字可以整除当前值//说明后面的数字肯定不是素数//我这里说的整除和取模是一样的,都是余数为0if (arr[j] % arr[i] == 0){arr[j] = 0;}}}}//打印筛选后的数字for (i = 0; i < 100; i++){if (arr[i] != 0){printf("%d ", arr[i]);}}return 0;}

运行结果:

2. 用选择法对10个整数排序

解析:问题来了啥是选择法呢?👉选择排序法。

简单来说就是把最小值或者最大值标记出来,当比较结束后把标记值和首位(或者末位)做交换,通过多轮比较,排出想要的顺序。

//打印void print(int* arr,int sz){for (int i = 0; i <= sz; i++){printf("%d ", arr[i]);}printf("\n");}int main(){int i, j, pos;int arr[] = { 2,8,3,9,5,7,1,4,0,6 };int sz = sizeof(arr) / sizeof(arr[0])-1;print(&arr,sz);//这是自定义的打印函数,不是printf!!!for (i = 0; i <= sz; i++){pos = 0;//将标记置于第一位for (j = 1; j <= sz-i; j++)//比较位从第二位开始,sz-i是为了让范围缩小{if (arr[j] > arr[pos]){pos = j;//如果比较值比标记值大,便将比较值坐标赋值给标记坐标}}if (pos != sz-i)//比较完成后判断标记坐标是不是在边界{int temp = arr[pos];arr[pos] = arr[sz-i];arr[sz-i] = temp;}}print(&arr, sizeof(arr) / sizeof(arr[0]) - 1);//sz已经被改变了,要重新计算return 0;}

既然可以把最大值筛选出来,就可以把最小值筛选出来,如果两个一起进行效率会大很多。

3. 求一个3 X 3的整形矩阵对角线元素之和

解析:创建矩阵和创建数组是一样的,像这一题要创建3x3的整形矩阵,可以这样操作int arr[3][3];先行后列很简单。

int main(){int arr[3][3] = { {1,2,3},{4,5,6},{7,8,9} };int i, j;int right_sum = 0, left_sum = 0;for (i = 0; i <= 2; i++){for (j = 0; j <= 2; j++){if (i == j){left_sum += arr[i][j];}if (i == 2 - j){right_sum += arr[i][j];}}}printf("左对角线的数值为%d\n", left_sum);printf("右对角线的数值为%d\n", right_sum);return 0;}

运行结果:

4. 有一个已经排好序的数组,要求输入一个数后,按原来顺序的规律将它插入数组中

解析:这个题目有一种简单又粗暴的办法:把插入的数字放在数组末端,然后再做一次排序。

但是我觉得这个方法不好,我们应该换一个思路:首先我们将插入的数字和数组相比较,如果插入的数字比原来数组的数字小,就把数组数字的角标给定位下来,并把原来数组数字向后挪一位。

int main(){int i, j;int arr[10] = {1,2,3,4,5,6,7,8,9};int input = 0;int end = 8;//数组最后一位数字的角标就是8printf("请输入要插入的数据:>");scanf("%d", &input);printf("当前排列情况:>");for (i = 0; i < 9; i++){printf("%d ", arr[i]);}printf("\n");//如果插入的数字比原来数组的数字小//就把数组数字的角标给定位下来,并把原来数组数字向后挪一位。while (end >= 0 && input < arr[end]){arr[end + 1] = arr[end];end--;}arr[end + 1] = input;printf("插入排列情况:>");for (i = 0; i < 10; i++){printf("%d ", arr[i]);}printf("\n ");return 0;}

运行结果:

5. 将一个数组中的值按逆序重新存放。例如:原来顺序为8,6,5,4,1。要求改为1,4,5,6,8。

解析:这一题较上一题就简单多了,可以用简单的方法也可以用复杂的方法。

复杂的方法就是重新排序,十种排序方法你随便选择;

简单的方法就是数值交换:数组左右交换,当左坐标大于等于右坐标时停止;

int main(){//vs用的时C99标准,数组的定义必须为常量//如果用支持C11标准的编译器,这里可以用变量定义,实现灵活定义数组int arr[] = { 8,6,5,4,1 };//这个sz随意,可以自己写数值,不一定要计算int sz = sizeof(arr) / sizeof(arr[0]);int left = 0, right = sz - 1;//打印printf("初始序列:>");for (int i = 0; i < sz ; i++){printf("%d ",arr[i]);}printf("\n");//重新排序//数组左右交换,当左坐标大于等于右坐标时停止while (left < right){int temp = arr[left];arr[left] = arr[right];arr[right] = temp;left++;right--;}//打印printf("重排序列:>");for (int i = 0; i < sz; i++){printf("%d ", arr[i]);}printf("\n");return 0;}

运行结果:

6. 输出以下的杨辉三角(要求输出10行)

1 1 11 2 11 3 3 11 4 6 4 11 5 10 10 5 1……

解析:这题的关键在于知道什么是杨辉三角,杨辉三角的规律是什么。不知道还不点👉杨辉三角?解杨辉三角有几种方法:

暴力解法:直接找规律挨个计算并打印出来。(不推荐,效率奇低)

创建数组:上面给的打印示例不好看出规律,我们把他排序看看,如下图。

从这幅图中我们可以得到一些信息:

每个数等于它上方两数之和。

每行数字左右对称,由1开始逐渐变大。

第n行的数字有n项。

前n行共[(1+n)n]/2 个数。

好,根据以上信息我们可以开始写代码了。

#define N 10int main(){int i, j;int arr[N][N];printf("1\n");//第一行直接打印//把边界赋值为1for (i = 1; i < N; i++){arr[i][0] = 1;j = i;arr[i][j] = 1;}int aim = N;for (i = 1; i < N; i++){printf("1\t");//第一个1直接打印for (j = 1; j < i; j++){arr[i][j] = arr[i - 1][j - 1] + arr[i - 1][j];printf("%d\t",arr[i][j]);}printf("1\n");//最后一个1直接打印并换行}return 0;}

运行结果:

这种是简单粗暴的写法,只针对这一题,通用性不佳,而且打印出的结果没有空格美化。

我们可以做一些简单的美化工作让他好看点👉戳这里!

7. 输出"魔方阵"。所谓魔方阵是指这样的方阵,它的每一行、每一列和对角线之和均相等。

解析:找出一个二维数组中的鞍点,即该位置上的元素在该行上最大,在该列上最小,也可能没有鞍点。

鞍点是行上最大,列上最小的元素,因此对数组的第i元素进行如下操作:

1、找到该行上最大元素,用max标记,并标记该元素所在列colindex

2、找colindex列上最小的元素,用min标记,并标记该元素所在行号rowindex

3、如果max和min相等,并且最小的元素刚好是在第i行,则为鞍点

4、如果所有行找完了,没有输出则没有鞍点

#define ROW 3#define COL 3int main(){int i, j,max,min,flag = 0;int arr[ROW][COL];int rowindex = 0, colindex = 0;//寻找最大值的坐标for (int i = 0; i <= ROW - 1; i++){for (int j = 0; j <= COL - 1; j++){scanf("%d", &arr[i][j]);}}for (i = 0; i <= ROW - 1; i++){max = arr[i][0];for (j = 0; j <= COL - 1; j++){if (max < arr[i][j]){max = arr[i][j];colindex = j;}}min = arr[0][colindex];for (int i = 0; i <= ROW - 1; i++){if (arr[i][colindex] < min){min = arr[i][colindex];rowindex = i;}}if (min == max && i == rowindex){flag = 1;printf("鞍点的坐标为[%d,%d],值为%d", rowindex, colindex, arr[rowindex][colindex]);break;}}if (flag == 0){printf("没有鞍点");}return 0;}

运行结果:

9. 有15个数按由大到小顺序存放在一个数组中,输入一个数,要求用折半查找法找出该数是数组中第几个元素的值。如果该数不在数组中,则输出"无此数"。

解析:二分查找是七大查找中的一个,这种查找方法比较简单快捷,但是这种方法面对频繁更新、删除操作、无序的表较为无力。

二分法原理:(举例的数组按由大到小排列)

1、标记出数组的左右边界和中间坐标;

2、比较中间值与查询值得大小关系,如果中间值大于查询值则把中间值+1赋值给左边界,同理则把中间值+1赋值给右边界;

3、当中间值等于查询值时终止比较并输出结果;

4、当左边界大于有边界时则认为数组种不存在查找值,输出不存在;

int binner_find(int* arr, int sz, int num){int left = 0, right = sz - 1;int i, j;while (left <= right){int mid = (left + right) / 2;if (arr[mid] > num){left = mid+1;}else if (arr[mid] < num){right = mid-1;}else if (arr[mid] == num){return mid+1;}}return -1;}int main(){int arr[] = { 15,14,13,12,11,10,9,8,7,6,5,4,3,2,1 };int sz = sizeof(arr) / sizeof(arr[0]);int num = 0;printf("请输入要查找的数值:>");scanf("%d", &num);int mod = binner_find(&arr, sz, num);if (mod == -1){printf("无此数");}else{printf("找到了是第%d个元素",mod);}return 0;}

注:最后返回的mid+1是因为这一题要求找到查询值是数组中的第几个元素,按照算数排列的话这里的坐标就是mid+1。

运行结果:

10. 有一篇文章,共有3行文字,每行有80个字符。要求分别统计出其中英文大写字母、小写字母、数字、空格以及其他字符的个数。

解析:这题的难点在于如何遍历3X80的字符。

大概有两种方法:

1、getchar读取字符:利用getchar能够读取单一字符的特性,运用循环语句完成代码;

2、创建数组:创建数组,运用gets和循环遍历数组完成代码;

(1)运用getchar读取字符

/*getchar做法,getchar有一个特性:一次只能吞吐一个字符。基于这个特性我们就可以设计一个3X80的循环,一个一个逐字分析得出个字符的数量。*/int main(){char c;//创建一个字符变量来接收getchar的信息int capital = 0, minuscules = 0, numbe = 0, space = 0, other = 0;printf("请输入一篇文章(共3行文字,每行80个字符):>\n");for (int i = 0; i < 3; i++){for (int j = 0; j < 80; j++){c = getchar();if (c >= 'A' && c <= 'Z'){capital++;}else if (c >= 'a' && c <= 'z'){minuscules++;}else if (c >= '0' && c <= '9'){numbe++;}else if (c == ' '){space++;}else{other++;}}}printf("大写字母的个数:%d\n", capital);printf("小写字母的个数:%d\n", minuscules);printf("数字的个数:%d\n", numbe);printf("空格的个数:%d\n", space);printf("其他字符的个数:%d\n", other);return 0;}

(2)创建数组

int main(){char c[3][3];int i, j;int capital = 0, minuscules = 0, numbe = 0, space = 0, other = 0;for (i = 0; i < 3; i++){printf("请输入第%d行:>\n", i + 1);gets(c[i]);for (j = 0; j < 3 && c[i][j] != '\0'; j++){if (c[i][j] >= 'A' && c[i][j] <= 'Z'){capital++;}else if (c[i][j] >= 'a' && c[i][j] <= 'z'){minuscules++;}else if (c[i][j] >= '0' && c[i][j] <= '9'){numbe++;}else if (c[i][j] == ' '){space++;}else{other++;}}}printf("大写字母的个数:%d\n", capital);printf("小写字母的个数:%d\n", minuscules);printf("数字的个数:%d\n", numbe);printf("空格的个数:%d\n", space);printf("其他字符的个数:%d\n", other);return 0;}

注:这种方法在VS中会出现栈错误:Stack around the variable 'XXX' was corrupted.可能是编译器的问题。

👆这个图片就不放了,自己运行一下吧。

11. 输出以下图案:

* * * ** * * ** * * ** * * ** * * *

解析:难题做多了,做一个简单的题目。这题比较简单,我们可以通过观察得到每一行打印多打印两个空格,用for就可以轻松解决。

int main(){int i = 0, j = 0;for (i = 0; i < 5; i++){for (j = 0; j < i; j++){printf(" ");}printf("* * * *\n");}return 0;}

运行结果:

12. 有一行电文,以按下面规律译成密码:

A--->Z a--->zB--->Y b--->YC--->X c--->x

即第1个字母编程第26个字母,第i个字母编程第(26-i+1)个字母,非字母字符不变,要求编程序将密码译回原文,并输出密码和原文。

解析:这一题解题的关键是合理运用ASCII码,我们只要知道当前要转换的字母是26个字母中的N个字母,再把26-N加到要起始字母上就可以了。

int main(){char arr[9999] = { 0 };scanf("%s", &arr);int len = strlen(arr);for (int i = 0; i < len; i++){if (arr[i] >= 'a' && arr[i] <= 'z'){arr[i] = 'a' + 'z' - arr[i];}else if (arr[i] >= 'A' && arr[i] <= 'Z'){arr[i] = 'A' + 'Z' - arr[i];}}printf("%s", arr);return 0;}

运行结果:

13. 编一程序,将两个字符串连接起来,不要用strcat函数

解析:字符串和数组不一样,不能使用 “ = ” 赋值。这里提供两个思路:

1、创建数组,遍历赋值法:顾名思义,就是创建一个新的字符串,把原来的两个字符串遍历读取挨个赋值到新字符串中。

int main(){char arr1[9999] = { 0 };char arr2[9999] = { 0 };char arr3[9999] = { 0 };printf("请输入第一串字符:>");scanf("%s", &arr1);int len1 = strlen(arr1);printf("请输入第二串字符:>");scanf("%s", &arr2);int len2 = strlen(arr2);for (int i = 0; i < len1; i++){arr3[i] = arr1[i];}for (int i = 0; i < len2; i++){arr3[len1 + i] = arr2[i];}printf("拼接后的字符:>%s", arr3);return 0;}

运行结果:

2、指针拼接法:指针法和数组遍历原理基本相似,也是遍历两个字符串把不等于 ‘\0’ 的值的地址挨个赋值到新字符串的地址上。

void my_strcat(char* arr1, char* arr2, char* p){int i = 0;for (; *arr1 != '\0';){*p = *arr1;arr1++;p++;}for (; *arr2 != '\0';){*p = *arr2;arr2++;p++;}*p = '\0';}int main(){char arr1[9999] = { 0 };char arr2[9999] = { 0 };char arr3[9999] = { 0 };char* p = 0;p = arr3;printf("请输入第一串字符:>");scanf("%s", &arr1);printf("请输入第二串字符:>");scanf("%s", &arr2);my_strcat(arr1, arr2, p);printf("拼接后的字符:>%s", p);return 0;}

运行结果:

14. 编写一个程序,对两个字符串s1和s2进行比较,如果s1 > s2,输出一个整数;若s1 = s2,输出0;若s1 < s2,输出一个负数。不要用strcpy函数。两个字符串用gets函数读入。输出的正数或负数的绝对值应是相比较的两个字符串相对应字符的ASCII码的差值。例如,“A"和“C”相比,由于"A” < “C”,应输出负数,同时由于‘A’与‘C’的ASCII码差值为2,因此应输出"-2"。同理:“And”和"Aid"相比较,根据第2个字符比较结果,“n"比"i"大5,因此应输出"5”。

解析:这题题目看着很复杂也很长,但实际上这题只是运用了ASCII的知识。运用循环语句将字符串中的字符挨个对比,如果两个相等则继续比较,如果两个不相等则进行相减,并将ASCII导出。

int main(){int index = 0,ret = 0;char s1[9999] = { 0 };char s2[9999] = { 0 };printf("请输入第一串字符:>");gets(s1);printf("请输入第二串字符:>");gets(s2);//这里当s1[index] = s2[index]时,两个的差值应该是0,这里为了保证继续运行则对结果取非while (!(ret = s1[index] - s2[index]) && ('\0' != s1[index]) && ('\0' != s2[index])){++index;}printf("返回值:>%d", ret);return 0;}

运行结果:

15. 编写一个程序,将字符数组s2中的全部字符复制到字符数组s1中,不用strcpy函数。复制时,‘\0’也要赋值过去。’\0’之后的字符不复制。

解析:这题只是一个简单的的字符串赋值问题,和前面的13题一样,分两种方法:

1、创建数组遍历赋值法:创建一个新数组,把原来的字符串赋值到新数组;

int main(){char arr1[9999] = { 0 };char arr2[9999] = { 0 };printf("请输入第一串字符:>");scanf("%s", &arr1);int len1 = strlen(arr1);for (int i = 0; i < len1; i++){arr2[i] = arr1[i];}printf("复制后的字符串:>%s", arr2);return 0;}

运行结果:

2、指针法:遍历字符串把不等于 ‘\0’ 的值的地址挨个赋值到新字符串的地址上。

void my_strcat(char* arr1, char* p){int i = 0;for (; *arr1 != '\0';){*p = *arr1;arr1++;p++;}*p = '\0';}int main(){char arr1[9999] = { 0 };char arr2[9999] = { 0 };char* p = 0;p = arr1;printf("请输入第一串字符:>");scanf("%s", &arr1);my_strcat(arr1, p);printf("复制后的字符串:>%s", p);return 0;}

运行结果:

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。