C程序设计(谭浩强第五版)第六章习题精解
4.有一个已经排好序的数组,要求输入一个数后,按原来顺序的规律 将它插入数组中
5.将一个数组中的值按逆序重新存放。例如:原来顺序为8,6,5,4,1。 要求改为1,4,5,6,8。
7.输出"魔方阵"。所谓魔方阵是指这样的方阵,它的每一行、每一列 和对角线之和均相等。例如:
8.找出一个二维数组中的鞍点,即该位置上的元素在该行上最大,在该列上最小,也可能没有鞍点。
9. 有15个数按由大到小顺序存放在一个数组中,输入一个数,要求 用折半查找法找出该数是数组中第几个元素的值。如果该数不在数组 中,则输出"无此数"。
10.有一篇文章,共有3行文字,每行有80个字符。要求分别统计出 其中英文大写字母、小写字母、数字、空格以及其他字符的个数。
12.编一程序,将两个字符串连接起来,不要用strcat函数
14.编写一个程序,将字符数组s2中的全部字符复制到字符数组s1 中,不用strcpy函数。复制时,‘\0’也要赋值过去。'\0'之后的字符不 复制。
第六章:利用数组处理批量数据
-
用筛选法求100之内的素数
A解题思路
筛选法:
首先定义一个整形数组,存放1-100的数字
当发现其中一个数不是素数时,将其标记为0
循环结束后将未被标记为0的数输出即可。
B代码部分
#include<Stdio.h>
void main()
{
int a[100];
int i,j;
for (i = 0; i < 100; i++)
{
a[i] = i + 1;//赋初值
for (j = 2; j < a[i]; j++)
if (a[i] % j == 0)
a[i] = 0;
if (a[i] != 0)
printf("%d是素数\n", a[i]);
}
}
C执行结果
2.用选择法对10个整数排序
A解题思路
只需记住选择排序核心代码即可:
for(i=0;i<10;i++)
for(j=i+1;j<10;j++)
if (a[i] > a[j])
{
int tmp = a[i];
a[i] = a[j];
a[j] = tmp;
}
B代码部分
#include<Stdio.h>
int i, j;
void sort(int a[])
{
for(i=0;i<10;i++)
for(j=i+1;j<10;j++)
if (a[i] > a[j])
{
int tmp = a[i];
a[i] = a[j];
a[j] = tmp;
}
}
void main()
{
int a[10];
printf("请输入10个需要排序的整数:\n");
for (i = 0; i < 10; i++)
scanf("%d", &a[i]);
sort(a);
printf("使用选择法拍完序后为:\n");
for (i = 0; i < 10; i++)
printf("%d ", a[i]);
}
C执行结果
3.求一个3 X 3的整形矩阵对角线元素之和
A解题思路
先输入一个3*3的矩阵
第一个对角线是行和列都相同
第二个对角线是行从0-2,列为2-行。
算出后相加即可。
B代码部分
#include<stdio.h>
void main()
{
int i, j;
int a[3][3];
printf("请输入一个3行3列的整形矩阵:\n");
for (i = 0; i < 3; i++)
for (j = 0; j < 3; j++)
scanf("%d", &a[i][j]);
int sum1 = 0, sum2 = 0;
for (i = 0; i < 3; i++)
{
sum1 += a[i][i];
sum2 += a[i][2 - i];
}
printf("两个对角线的和为:%d", sum1 + sum2);
}
C执行结果
4.有一个已经排好序的数组,要求输入一个数后,按原来顺序的规律 将它插入数组中
A解题思路
先输入1个数给x
End变量是指数组的最后一个元素的下标-1,
当end>0且当前数>x时,就将该数移动到其后面一个元素
循环结束后,将该位置补上输入的数即可
B代码部分
#include<stdio.h>
void main()
{
int x;
int a[10] = { 1,2,3,4,5,6,7,9,10 };
printf("请输入一个数:");
scanf("%d", &x);
int end = 8;
while (end >= 0 && a[end] > x)
{
a[end + 1] = a[end];
end--;
}
a[end+1] = x;
for (x = 0; x < 10; x++)
printf("%d ", a[x]);
}
C执行结果
5.将一个数组中的值按逆序重新存放。例如:原来顺序为8,6,5,4,1。 要求改为1,4,5,6,8。
A解题思路
本题采用第一个和最后一个数进行交换,然后再逐次往里遍历,直到最左边的数大于等于最右边的数时,不再发生数据交换。
B代码部分
#include<stdio.h>
void main()
{
int s[5];
int x = sizeof(s)/4;
int i;
printf("请输入%d个值:", x);
for (i = 0; i < x; i++)
scanf("%d", &s[i]);
int left = 0, right = x-1;
while (left < right)//用于进行数据交换
{
int tmp = s[left];
s[left] = s[right];
s[right] = tmp;
left++;
right--;
}
printf("倒着拍完序的数组为:");
for (i = 0; i < x; i++)
printf("%d ", s[i]);
}
C执行结果
6.输出一下的杨慧三角(要求输出10行)
A解题思路
仔细观察杨慧三角可以看到: 第0列和对角线上的数据全部为1,其余位置上的数据为上一行正对数据与上一行正对前一个数据之和。
比如: a[4][2] = a[3][2] + a[3][1]
得出公式:a[i][j] = a[i - 1][j] + a[i - 1][j - 1];
B代码部分
#include<stdio.h>
void main()
{
int i, j,a[10][10];
for(i=0;i<10;i++)
for (j = 0; j <= i; j++)
{
if(i==j||j==0)
a[i][j] = 1;//第0列和对角线上的数据全部为1
}
for (i = 0; i < 10; i++)
for (j = 0; j <= i; j++)
{
if(a[i][j]!=1)
a[i][j] = a[i - 1][j] + a[i - 1][j - 1];//其余位置上的数据为上一行正对数据与上一行正对前一个数据之和。
}
for (i = 0; i < 10; i++)//输出
{
for (j = 0; j <= i; j++)
printf("%-5d", a[i][j]);
printf("\n");
}
}
C执行结果
7.输出"魔方阵"。所谓魔方阵是指这样的方阵,它的每一行、每一列 和对角线之和均相等。例如:
8 1 6
3 5 7
4 9 2
A解题思路
首先我们来了解一下魔方阵的生成方法:
1.先把第0行中间置为1.
2.下一个元素放在当前元素的上一行,下一列。
x = a[i - 1][j + 1]
3.如果上一行,下一列已有元素,则下一个元素存放在当前列的下一行。
x = a[i + 1][j]
4.把矩阵看成是回绕的(像个球卷起来那样)
if i<0 i = 最后一行
if j>size j = 0
最后大家可以直接去看代码部分,基本上每一步我都标注了相关注释,程序易读性很高。
B代码部分
#include<stdio.h>
void main()
{
int n;//用于表示魔方阵的阶数
printf("请输入一个3-100之间的奇数,用于做魔方阵的阶数:");
scanf("%d", &n);
int a[100][100] = { 0 };//先定义一个阶数最大为100的未赋值的魔方阵。
int row, col;//定义两个变量用于存放魔方阵的行和列
int prerow, precol ;//定义两个变量用来存放当前行和列的值
row = 0;
col = n / 2;
a[row][col] = 1;//1.先把第0行中间的元素置为1.
int i, j;
for (i = 2; i <= n * n; i++)//因为已经赋值了一个1,所以i从2开始,需要赋值n*n-1次
{
row--;
col++;//2.下一个元素放在当前元素的上一行,下一列。
if (row < 0)
row = n - 1;//如果行是第-1行,就把他换成最后一行
if (col >= n)
col = 0;//如果列到达了-1列(也就是超过了最后一列),就将其置为第1列
//4.这两句的功能是把矩阵看成是回绕的(像个球卷起来那样)
if (a[row][col] != 0)//3.如果上一行,下一列已有元素,则下一个元素存放在当前列的下一行。
{
row = prerow + 1;//prerow是当前行+1就是下一行。
col = precol;//precol是当前列,不用变化。
}
a[row][col] = i;//这句代码是给魔方阵赋值的唯一语句,经过上面的3个if条件后,到这里进行相应的赋值。
prerow = row;
precol = col;//记录下来当前行和列的值
}
for (i = 0; i < n; i++)//用于输出已赋值后的n阶魔方阵
{
for (j = 0; j < n; j++)
printf("%-4d", a[i][j]);
printf("\n");
}
}
C执行结果
8.找出一个二维数组中的鞍点,即该位置上的元素在该行上最大,在该列上最小,也可能没有鞍点。
A解题思路
例子:
9 6 8 70
10 23 55 66
15 67 4 69
其中66为鞍点并且唯一。
鞍点:即该位置上的元素在该行上最大,在该列上最小,也可能没有鞍点。
B代码部分
#include<stdio.h>
void main()
{
int a[3][4] = { {9,6,8,70},{10,23,55,66},{15,67,4,69} };
int i, j,k;
int max;
int j2;
int flat = 0;//标志变量,0代表没有找到,1代表找到了
for (i = 0; i < 3; i++)
{
max = a[i][0];
for (j = 0; j < 4; j++)//先找出该行上最大的值
{
if (max < a[i][j])
{
max = a[i][j];
j2 = j;//找到该行上最大元素后记录下当前所在列的下标
}
}
for (k = 0; k < 3; k++)//判断max是不是该列最小值,不是就退出这个循环
{
if (a[k][j2] < max)
{
break;
}
}
if (k == 3)//如果上面的循环正常结束,说明k=3,就是找到鞍点了,输出即可
{
printf("找到鞍点了,是:%d", max);
flat = 1;
}
}
if (flat == 0)
{
printf("没有找到鞍点!");
}
}
C执行结果
9. 有15个数按由大到小顺序存放在一个数组中,输入一个数,要求 用折半查找法找出该数是数组中第几个元素的值。如果该数不在数组 中,则输出"无此数"。
A解题思路
首先定义一个有序数组
输入要查找的数
定义函数使用二分查找方式找出该数的位置
二分查找核心代码:
while (left <= right)
{
int mid = (left + right) / 2;
if (a[mid] == x)
{
printf("找到了,该数为数组中第%d个元素。", mid + 1);
break;
}
else if (a[mid] > x)
right = mid - 1;
else if (a[mid] < x)
left = mid + 1;
}
4.如果循环正常结束,也就是left>right输出无此数。
B代码部分
#include<stdio.h>
void find(int a[], int x,int r)
{
int left = 0;
int right =r;
while (left <= right)
{
int mid = (left + right) / 2;
if (a[mid] == x)
{
printf("找到了,该数为数组中第%d个元素。", mid + 1);
break;
}
else if (a[mid] > x)
right = mid - 1;
else if (a[mid] < x)
left = mid + 1;
}
if (left > right)
printf("无此数!");
}
void main()
{
int a[15] = { 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14};
int r = sizeof(a) / 4 - 1;//用于计算整型数组下标最大值,此步骤无法在函数里计算。
printf("请输入要查找的数》:");
int x;
scanf("%d", &x);
find(a, x,r);
}
C执行结果
10.有一篇文章,共有3行文字,每行有80个字符。要求分别统计出 其中英文大写字母、小写字母、数字、空格以及其他字符的个数。
A解题思路
定义一个3行80列的字符型数组用于存放3行文字,每行有80个字符。
使用gets函数输入这3行文字
使用双重for循环进行遍历,外层用于遍历行数,内层用于遍历每行有多少字符。
根据所求值定义相应的变量和条件,计算完后进行输出即可。
B代码部分
#include<stdio.h>
void main()
{
char str[3][80] = { 0 };//共有3行文字,每行有80个字符。
int i;
for (i = 0; i < 3; i++)//输入这3行文字
{
printf("请输入第%d行文字:", i + 1);
gets(str[i]);
}
//英文大写字母、小写字母、数字、空格以及其他字符的个数
int big, small, num, speace, other;
big = small = num = speace = other = 0;
int j=0;
for(i=0;i<3;i++)
for (j = 0; str[i][j]; j++)//双重循环进行遍历
{
if (str[i][j] >= 'A' && str[i][j] <= 'Z')
big++;
else if (str[i][j] >= 'a' && str[i][j] <= 'z')
small++;
else if (str[i][j] >= '0' && str[i][j] <= '9')
num++;
else if (str[i][j] == ' ')
speace++;
else
other++;
}
printf("英文大写字母:%d、小写字母:%d、数字:%d、空格:%d,其他字符:%d", big, small, num, speace, other);
}
C执行结果
10.输出以下图案:
* * * *
* * * *
* * * *
* * * *
* * * *
A解题思路
观察发现,此图案有5行,每行都有* * * *
找出规律,第二行比第一行多2个空格在前面,第3行比第二行多2个空格在前面...
使用双重循环进行输出
外层循环用于控制输出的行数
内层循环用于控制输出的空格数
B代码部分
#include<stdio.h>
void main()
{
int i, j;
for (i = 0; i < 5; i++)//外层循环用于控制输出的行数
{
for (j = 0; j < i; j++)//内层循环用于控制输出的空格数
{
printf(" ");
}
printf("* * * *\n");
}
}
C执行结果
11.有一行电文,以按下面规律译成密码:
-
>Z a->z
-
B->Y b->y
-
C->X c->x
-
…。
即第1个字母编程第26个字母,第i个字母编程第(26-i+1)个字母,非字母字符不变,要求编程序将密码 译回原文,并输出密码和原文。
A解题思路
首先我们根据题目给出的规律得出以下编码公式:
26-(ch-’A/a’)-1
26是一共26个字母,(ch-’A/a’)是指从A/a开始数是正数第几个数,这样26-(ch-’A/a’)就等于与之相对应的倒数第几个数,为什么要-1?因为数组下标是从0开始,为了防止转变后下标越界,我们需要-1保持平衡。
编码和解码规则相同,将所给密码的每个字符区分大小写然后代入公式,注意,因为这个公式算出的是由正数第几个转变为倒数第几个,所以我们如果想正常输出的话还需要在其前面加上起始数A/a
得出最终公式为:
大写str='A'+(26 - (str- 'A') - 1);小写str='a'+ (26 - (str[i] - 'a') - 1);
B代码部分
#include<stdio.h>
void main()
{
char str[128] = { 0 };
printf("请输入一串密码:");
gets(str);
printf("你输入的密码为:%s\n", str);
int i=0;
while (str[i])
{
if (str[i] >= 'A' && str[i] <= 'Z')
str[i] = 'A'+(26 - (str[i] - 'A') - 1);
else if (str[i] >= 'a' && str[i] <= 'z')
str[i] ='a'+ (26 - (str[i] - 'a') - 1);
i++;
}
printf("破译后的原文为:%s", str);
}
C执行结果
12.编一程序,将两个字符串连接起来,不要用strcat函数
A解题思路
首先遍历到第一个字符串的末尾
将第二个字符串的第一个值开始赋值到第一个字符串的最后一个值+1处,如此往后
赋值完成后给第一个字符串加上’\0’结束符
将第一个字符串输出即可。
B代码部分
#include<stdio.h>
void mystrcat(char str1[], char str2[])
{
int i, j;
for (i = 0; str1[i]; i++)
;
for (j = 0; str2[j]; j++)
str1[i++] = str2[j];
str1[i] = '\0';
puts(str1);
}
void main()
{
char str1[123] ="abcd";
char str2[123] = "efg";
printf("请输入两个字符串:\n");
gets(str1);
gets(str2);
mystrcat(str1, str2);
}
或者下面这个是不赋值结束符的表示,代码更少一些,不过没有上面那个易懂。
void mystrcat(char str1[], char str2[])
{
int i, j;
for (i = 0; str1[i]; i++)
;
for (j = 0; str1[i++] = str2[j]; j++)
;
puts(str1);
}
void main()
{
char str1[123] ="abcd";
char str2[123] = "efg";
mystrcat(str1, str2);
}
C执行结果
13.编写一个程序,将两个字符串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"。
A解题思路
1,输入2个字符串
2.逐个遍历这两个字符串相对应的每个元素,如果相等继续判断下一个
3.遇到不相等的元素直接返回差值即可。
B代码部分
#include<stdio.h>
void mystrcmp(char s1[], char s2[])
{
int i=0;
while (s1[i]||s2[i])
{
if (s1[i] - s2[i] == 0)
i++;
else
{
printf("%d", s1[i] - s2[i]);
break;
}
}
}
void main()
{
char s1[10], s2[10];
gets(s1);
gets(s2);
mystrcmp(s1, s2);
}
C执行结果
14.编写一个程序,将字符数组s2中的全部字符复制到字符数组s1 中,不用strcpy函数。复制时,‘\0’也要赋值过去。'\0'之后的字符不 复制。
A解题思路
1,输入2个字符串
2,使用循环逐个遍历并复制,
3,当遇到第二个字符串的结束符时停止复制,且此时结束符也复制到第一个字符串中了。
B代码部分
#include<stdio.h>
void mystrcpy(char s1[], char s2[])
{
int i=0,j=0;
while (s1[i++] = s2[j++]);
}
void main()
{
char s1[12], s2[12];
gets(s1);
gets(s2);
mystrcpy(s1, s2);
puts(s1);
}
C执行结果