C程序设计(谭浩强第五版)第七章习题精解。C语言课后习题解析。C语言考研,C语言专升本,C语言期末考试,初学C语言,程序设计基础,编程题必备。C语言第四章:选择结构程序设计编程题解析。

C程序设计(谭浩强第五版)第章习题精解

第七章 :用函数实现模块化程序设计目录:

1、写两个函数,分别求两个整数的最大公约数和最小公倍数,用主函数调用这两个函数,并输出结果。两个整数由键盘输人。

2.求方程 ${ax}^2+bx+c=0$的根,用3个函数分别求当: $b^2- 4ac$大于0、等于0和小于0时的根并输出结果。从主函数输入a,b,c 的值。

3.写一个判素数的函数,在主函数输人一个整数,输出是否为素数的信息。

4.写一个函数,使给定的一个3X3的二维整型数组转置,即行列互换。

5.写一个函数,使输人的一个字符串按反序存放,在主函数中输入和输 出字符串。

6.写一个函数,将两个字符串连接。

7.写一个函数,将一个字符串中的元音字母复制到另一字符串,然后输 出。

8.写一个函数,输人一个4位数字,要求输出这4个数字字符,但每两 个数字间空一个空格。如输人1990,应输出“1 9 9 0”。

9.编写一个函数,由实参传来一个字符串,统计此字符串中字母、数 字、空格和其他字符的个数,在主函数中输人字符串以及输出上述的 结果。

10.写一个函数,输人一行字符,将此字符串中最长的单词输出。

11.写一个函数,用“起泡法”对输人的10个字符按由小到大顺序排列。

13.用递归方法求n阶勒让德多项式的值,递归公式为

14.输人10个学生5门课的成绩, 分别用函数实现下列功能:

①计算每个学生的平均分;

②计算每门课的平均分;

③找出所有50个分数中最高的分数所对应的学生和课程;

④计算平均分方差

15.写几个函数: ①输人10个职工的姓名和职工号; ②按职工号由小到大顺序排序,姓名顺序也随之调整; ③要求输人一个职工号,用折半查找法找出该职工的姓名,从主函数输人要查找的职工号,输出该职工姓 名。

16.写一个函数,输人一个十六进制数,输出相应的十进制数。

17.用递归法将一个整数n转换成字符串。例如,输人483,应输出字 符串”483”。n的位数不确定,可以是任意位数的整数。

18.给出年、月、日,计算该日是该年的第几天。


第七章 :用函数实现模块化程序设计

1、写两个函数,分别求两个整数的最大公约数和最小公倍数,用主函数调用这两个函数,并输出结果。两个整数由键盘输人。

A解题思路

  1. 使用辗转相除法进行求最大公约数:

  2. 首先确保第一个数最大

  3. 然后循环条件为第二个数不等于0,循环体内为先求第一个数对第二个数的余数

  4. 然后第一个数等于第二个数,第二个数等于余数

  5. 如此往复,循环结束后第一个数中存放的值即为最大公约数

  6. 最小公倍数等于这俩数的乘积除以最大公约数

B代码部分

#include<stdio.h>

int max(int m, int n)

{

int r;

if (m < n)//先确保m中存储的为最大数

{

int c = m;

m = n;

n = c;

}

while (n)//辗转相除法求最大公约数

{

r = m % n;

m = n;

n = r;

}

return m;

}

void min(int s1, int s2)

{

printf("最小公倍数为:%d", s1 / s2);//输出最小公倍数

}

void main()

{

int m, n;

printf("请输入2个整数:");

scanf("%d %d", &m, &n);

int s1 = m * n;

int s2=max(m, n);//最大公约数

printf("最大公约数为:%d\n", s2);

min(s1, s2);

}

C执行结果

2.求方程 ${ax}^2+bx+c=0$的根,用3个函数分别求当: $b^2- 4ac$大于0、等于0和小于0时的根并输出结果。从主函数输入a,b,c 的值。

A解题思路

根据图上的公式转为c语言的数学代码即可,在使用sqrt函数时记得要引用math.h函数库。

B代码部分

#include<stdio.h>

#include<math.h>

float disc;//定义全局变量判别式

float x1, x2;

float p, q;

void greater(int a, int b)//大于0的情况

{

x1 = (-b + sqrt(disc)) / 2 * a;

x2 = (-b - sqrt(disc)) / 2 * a;

}

void equal(int a, int b)//等于0的情况

{

x1 = x2 = (-b) / 2 * a;

}

void less(int a, int b)//小于0的情况

{

p = (-b) / 2 * a;

q = sqrt(-(disc)) / 2 * a;

}

void main()

{

int a, b, c;

printf("请输入a,b,c的值:");

scanf("%d %d %d", &a, &b, &c);

disc = b * b - 4 * a * c;

if (disc > 0)

{

greater(a, b);

printf("该方程在判别式>0时的两根为:%.2f||%.2f", x1, x2);

}

else if (disc = 0)

{

equal(a, b);

printf("该方程在判别式=0时的两根为:%.2f||%.2f", x1, x2);

}

else

{

less(a, b);

printf("该方程在判别式<0时的两根为:%.2f||%.2f", p+q, p-q);

}

}

C执行结果

3.写一个判素数的函数,在主函数输人一个整数,输出是否为素数的信息。

A解题思路

素数判断条件:除了1和本身外没有取余为0的数,1不是素数。

将此代入成代码即可。

B代码部分

#include<stdio.h>

int prime(int a)

{

int i;

if (a == 1)return 0;//1不是素数

for (i = 2; i < a; i++)

if ( a % i == 0)

{

return 0;

break;

}

return 1;

}

void main()

{

int a;

while (1)

{

printf("请输入一个整数:");

scanf("%d", &a);

if (prime(a) == 1)

printf("%d是素数。\n",a);

else

printf("%d不是素数。\n",a);

}

}

C执行结果

4.写一个函数,使给定的一个3X3的二维整型数组转置,即行列互换。

A解题思路

矩阵的转置:即为行变列,列变行。再定义一个数组存放转置后的矩阵就行了。

B代码部分

#include<stdio.h>

int i, j;

void transpose(int a[][3],int b[][3])

{



for (i = 0; i < 3; i++)

for (j = 0; j < 3; j++)

b[i][j] = a[j][i];

}

void main()

{

int a[3][3],b[3][3];

printf("请输入一个3*3的矩阵:\n");

for (i = 0; i < 3; i++)

for (j = 0; j < 3; j++)

scanf("%d", &a[i][j]);

transpose(a,b);

printf("转置后的矩阵为:\n");

for (i = 0; i < 3; i++)

{

for (j = 0; j < 3; j++)

printf("%d ", b[i][j]);

printf("\n");

}

}

C执行结果

5.写一个函数,使输人的一个字符串按反序存放,在主函数中输入和输 出字符串。

A解题思路

  1. 本题可使用两种方式求解。

  2. 第一种方式的思路是首先分别定义两个字符数组,将第一个字符串的元素从后往前赋值给第二个字符串,第二个字符串从前往后接收,循环结束后给第二个字符串加上\0然后输出即可。

  3. 第二种思路是首先定义字符数组下标的左值和右值,左值为0,右值为长度-1,然后将左边的元素换成右边的元素,将右边的元素换成左边的元素。最后将遍历一遍(当左值大于右值时说明已遍历一遍)的字符串输出即可。

B代码部分

#include<stdio.h>

#include<string.h>

void re1(char s1[], char s2[])//第一种方式

{

int i, j = 0;

//while (s1[++i]);

//i = i - 1;

i = strlen(s1)-1;//这一条语句与上面两行相等

for (; i >= 0; i--,j++)

s2[j] = s1[i];

s2[j] = '\0';

}

void re2(char s1[])//第二种方式

{

int left = 0, right = strlen(s1) - 1;

while (left < right)

{

char s = s1[left];

s1[left] = s1[right];

s1[right] = s;

left++;

right--;

}

}

void main()

{

char s1[128] = {0};

//char s2[128] = {0};

gets(s1);

//re1(s1, s2);//注释部分是另一种实现方式

//puts(s2);

re2(s1);

puts(s1);

}

C执行结果

6.写一个函数,将两个字符串连接。

A解题思路

1.先使i遍历到s1的末尾位置

2.然后开始字符串拷贝,将s2的第一个元素赋值给s2的末尾处,然后逐个往后。s2中的\0也会被拷贝到s1中。

3.将s1输出即可。

B代码部分

#include<stdio.h>

void mystrcat(char s1[], char s2[])

{

int i=0, j=0;

while (s1[++i]);//先使i遍历到s1的末尾位置

while (s1[i++] = s2[j++]);//开始字符串拷贝,这条语句执行完后,s2中的\0也会被拷贝到s1中。

}

void main()

{

char s1[128], s2[50];

printf("请输入两个需要连接的字符串:\n");

gets(s1);

gets(s2);

mystrcat(s1, s2);

puts(s1);

}

C执行结果

7.写一个函数,将一个字符串中的元音字母复制到另一字符串,然后输 出。

A解题思路

设置相应的条件在if语句中,将满足条件的元素存放到第二个字符串中。

B代码部分

#include<stdio.h>

void mystrcpy(char s[], char s2[])

{

int i = 0, j = 0;

while (s[i])

{

if (s[i] == 'a' || s[i] == 'A' || s[i] == 'e' || s[i] == 'E' ||

s[i] == 'i' || s[i] == 'I' || s[i] == 'o' || s[i] == 'O' ||

s[i] == 'u' || s[i] == 'U')

s2[j++] = s[i];

i++;

}

s2[j] = '\0';

}

void main()

{

char s[128], s2[128];

gets(s);

mystrcpy(s, s2);

puts(s2);

}

C执行结果

8.写一个函数,输人一个4位数字,要求输出这4个数字字符,但每两 个数字间空一个空格。如输人1990,应输出“1 9 9 0”。

A解题思路

在每个数字之间输出一个空格,最后一个字符不输出空格。

B代码部分

#include<stdio.h>

void myputs(char s1[])

{

int i = 0;

while (s1[i])

{

printf("%c", s1[i++]);

if(i<strlen(s1))

printf(" ");

}

}

void main()

{

char s1[5];

gets(s1);

myputs(s1);

}

C执行结果

9.编写一个函数,由实参传来一个字符串,统计此字符串中字母、数 字、空格和其他字符的个数,在主函数中输人字符串以及输出上述的 结果。

A解题思路

1,在循环中遍历整个数组,定义全局变量letter, num, speace, other;对应:字母、数 字、空格和其他字符,

2,全局变量初值为0且全局可用。

3,然后在循环中依次判断是否符合相应的条件,符合就相应的值+1,

4,直到将整个数组遍历完后将这些值在主函数输出。

B代码部分

#include<stdio.h>

int letter, num, speace, other;/*字母、数 字、空格和其他字符*/

void search(char str[])

{

for (int i = 0; str[i]; i++)

{

if ((str[i] >= 'A' && str[i] <= 'Z') || (str[i] >= 'a' && str[i] <= 'z'))

letter++;

else if (str[i] >= '0' && str[i] <= '9')

num++;

else if (str[i] == ' ')

speace++;

else

other++;

}

}

void main()

{

char str[128];

gets(str);

search(str);

printf("字母%d、数字%d、空格%d,其他字符%d", letter, num, speace, other);

}

C执行结果

10.写一个函数,输人一行字符,将此字符串中最长的单词输出。

A解题思路

相关思路都标注在代码块注释部分了。

B代码部分

#include<stdio.h>

void findmax(char str[], char max[])

{

int i, j;

i = j = 0;

int len = 0;

while (str[i])

{

j = i;//j等于当前单词的起始位置

while (str[j] != ' ' && str[j])//寻找当前单词的末尾处

j++;

len = j - i;//计算当前单词的长度

if (len > strlen(max))//判断当前单词是否为最大长度

strncpy(max, str + i, len);//是最大长度就拷贝到max中

j++;//计算下一个单词,当前j指向下一个单词的起始处

i = j;//将i也指向下一个单词的起始处

}

}

void main()

{

char str[256] = { 0 };

char max[256] = { 0 };//字符数组一定要先初始化再使用

printf("请输入一行数据,单词之间使用空格分隔:\n");

gets(str);

findmax(str, max);//函数运行完毕后,max数组中存放的是最长单词

printf("最长的单词为:%s", max);

}

C执行结果

11.写一个函数,用“起泡法”对输人的10个字符按由小到大顺序排列。

A解题思路

起泡法也就是冒泡排序,我们只需要知道冒泡排序的核心算法即可:

for(i=0;i<len;i++)

for(j=0;j<len-i;j++)

if (s[j] > s[j+1])

{

char x = s[j];

s[j] = s[j + 1];

s[j + 1] = x;

}

B代码部分

#include<stdio.h>

void sort(char s[])

{

int i, j;

int len = strlen(s)-1;

for(i=0;i<len;i++)

for(j=0;j<len-i;j++)

if (s[j] > s[j+1])

{

char x = s[j];

s[j] = s[j + 1];

s[j + 1] = x;

}

}

void main()

{

char s[11] = { '1','2','3','1','2','3', '1','2','3','9' };

sort(s);

puts(s);

}

C执行结果

13.用递归方法求n阶勒让德多项式的值,递归公式为

A解题思路

将公式换成c语言代码即可。

B代码部分

#include<stdio.h>

double fun(int n, int x)

{

if (n == 0)

return 1;

if (n == 1)

return x;

if (n >= 1)

return ((2 * n - 1) * x - fun(n - 1, x) - (n - 1) * fun(n - 2, x) / n);

}

void main()

{

int n,x;

printf("请输入n和x的值:");

scanf("%d %d", &n,&x);

printf("勒让德多项式的值为:%.2f", fun(n, x));

}

C执行结果

14.输人10个学生5门课的成绩, 分别用函数实现下列功能:

  1. ①计算每个学生的平均分;

  2. ②计算每门课的平均分;

  3. ③找出所有50个分数中最高的分数所对应的学生和课程;

  4. ④计算平均分方差

A解题思路

根据题目进行函数定义,最后一个函数是求方差,将方差公式转换成代码即可。

B代码部分

#include<stdio.h>

#define M 10//10个学生

#define N 5//5门课程

float stuavg[M];//用于存放每个学生的平均分

float courseavg[N];//用于存放每门课程的平均分

int i, j;

void savg(float score[][N])//①计算每个学生的平均分;

{

for (i = 0; i < M; i++)

{

float sum = 0.0;

for (j = 0; j < N; j++)

{

sum += score[i][j];

}

stuavg[i] = sum / N;

}

for (i = 0; i < M; i++)

printf("第%d个学生的平均成绩为:%.2f\n", i + 1, stuavg[i]);

}

void cavg(float score[][N])//②计算每门课的平均分;

{

for (i = 0; i < N; i++)

{

float sum = 0.0;

for (j = 0; j <M; j++)

{

sum += score[j][i];

}

courseavg[i] = sum / M;

}

for (i = 0; i < N; i++)

printf("第%d门课程的平均分为:%.2f\n", i + 1, courseavg[i]);

}

void findmax(float score[][N])//③找出所有50个分数中最高的分数所对应的学生和课程;

{

float max = score[0][0];

int x, y;

for (i = 0; i < M; i++)

{

for (j = 0; j < N; j++)

if (max < score[i][j])

{

max = score[i][j];

x = i;

y = j;

}

}

printf("所有50个分数中最高的分数为:%.2f所对应的学生是第%d个,课程是第%d个.\n", max, x + 1, y + 1);

}

void sum(float score[][N])//④计算平均分方差:

{

float sum1 = 0.0;//平均分平方和

float sum2 = 0.0;//平均分和

for (i = 0; i < M; i++)

{

sum1 += stuavg[M] * stuavg[M];

sum2 += stuavg[M];

}

printf("平均分方差为:%.2f", sum1 / M - (sum2 / M) * (sum2 / M));

}

void main()

{

float score[M][N] = { 0 };

for (i = 0; i < M; i++)

{

printf("请输入第%d名学生的%d门成绩:", i + 1, N);

for (j = 0; j < N; j++)

{

scanf("%f", &score[i][j]);

}

}

savg(score);

cavg(score);

findmax(score);

sum(score);

}

C执行结果

15.写几个函数: ①输人10个职工的姓名和职工号; ②按职工号由小到大顺序排序,姓名顺序也随之调整; ③要求输人一个职工号,用折半查找法找出该职工的姓名,从主函数输人要查找的职工号,输出该职工姓 名。

A解题思路

  1. 定义职工号和姓名两个数组,职工号为整形int id[N],职工姓名为char name[N][NAME_SIZE];

  2. 2.使用冒泡排序进行职工号的排序,姓名用strcpy排序。

  3. 3.折半查找的核心方法具体看代码部分。

B代码部分

#include<stdio.h>

#include<string.h>

#define N 10

#define NAME_SIZE 10

void Input(int id[], char name[][NAME_SIZE])

{

for (int i = 0; i < N; i++)

{

printf("输入职工号:");

scanf("%d", &id[i]);

getchar();//用于忽略所输入的回车符号。

printf("输入职工的姓名:");

gets(name[i]);

}

}

void Output(int id[], char name[][NAME_SIZE])

{

for (int i = 0; i < N; i++) {

printf("[%d],[%s]\n", id[i], name[i]);

}

}

//使用冒泡排序进行姓名与职工号同时排序

void Sort(int id[], char name[][NAME_SIZE])

{

char tmp_name[NAME_SIZE];//定义临时字符串,用于存储临时变量

for (int i = 0; i < N - 1; i++)

{

for (int j = 0; j < N - i - 1; j++)

{

if (id[j] > id[j + 1])

{

int tmp_id = id[j];

strcpy(tmp_name, name[j]);

id[j] = id[j + 1];

strcpy(name[j], name[j + 1]);

id[j + 1] = tmp_id;

strcpy(name[j + 1], tmp_name);

}

}

}

}

//二分查找(折半查找)算法设计查找的规律

void Search(int id[], char name[][NAME_SIZE], int key)

{

int low = 0;

int high = N - 1;

int mid;

while (low <= high)

{

mid = (low + high) / 2;

if (key == id[mid])

break;

if (key < id[mid])

high = mid - 1;

else

low = mid + 1;

}

if (low <= high)

printf("职工号为%d的职工姓名为:%s\n", key, name[mid]);

else

printf("要查找的职工号为%d的职工不存在。\n", key);

}

int main() {

int id[N];//职工号

char name[N][NAME_SIZE];//职工号对应的职工姓名

Input(id, name);

Output(id, name);

Sort(id, name);

printf("\n");

Output(id, name);

int no;

while (1)

{

printf("请输入要查找的职工号:");

scanf("%d", &no);

Search(id, name, no);

}

return 0;

}

C执行结果

16.写一个函数,输人一个十六进制数,输出相应的十进制数。

A解题思路

根据十六进制转10进制的规律进行转换:

  1. 每进一位需要乘以16

  2. 是大写字母时,需要将大写字母-字符A再+10

  3. 是小写字母时,需要将小写字母-字符a再+10

  4. 是0-9之间的数时,因为原来的数据是字符型,我们需要将其减去一个字符型的0才能变成整形参与运算。

B代码部分

#include<stdio.h>

int Transpose(char str[])

{

int i = 0;

int n=0;

while (str[i])

{

if (str[i] >= 'A' && str[i] <= 'Z')

n = n * 16 + str[i] - 'A' + 10;

if (str[i] >= 'a' && str[i] <= 'z')

n = n * 16 + str[i] - 'a' + 10;

if (str[i] >= '0' && str[i] <= '9')

n = n * 16 + str[i]-'0';//必须要加上-‘0’,这样保证两边是整形数据运算。

i++;

}

return n;

}

void main()

{

char str[128];

printf("请输入一个十六进制数:");

gets(str);

printf("Ox%s=%d", str, Transpose(str));

}

C执行结果

17.用递归法将一个整数n转换成字符串。例如,输人483,应输出字 符串”483”。n的位数不确定,可以是任意位数的整数。

A解题思路

使用递归关键是要有退出的条件,本题的递归思路是从后往前递归,输出字符时自然就会从前往后输出。

B代码部分

#include<stdio.h>

void prints(int s)

{

if (s / 10)

prints(s / 10);

putchar(s % 10 + '0');//从后往前递归,输出时从前往后

}

void main()

{

int s;

printf("请输入一个整数:");

scanf("%d", &s);

if (s < 0)//如果s输入的是负数的情况下,需要将先将负号输出然后将负数变为正数运算

{

putchar('-');

s *=-1;

}

prints(s);

}

C执行结果

18.给出年、月、日,计算该日是该年的第几天。

A解题思路

  1. 主函数输入年月日

  2. 将年月日传入seek函数

  3. 在seek函数中定义一个整形数组,用于存放每个月份的值

  4. 从1到当前月份每月的天数相加到sum

  5. Sum加上当前天数

  6. 判断如果月份大于2且当前年是闰年的话给总天数加1,因为闰年的2月份比平年多1天

  7. 输出sum即可

B代码部分

#include<stdio.h>

void seek(int year, int mouth,int day)

{

int m[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };

int sum = 0;

for (int i = 1; i < mouth; i++)//i不能等于当前月份,因为当前月份没过完不能将天数计入总值

sum += m[i];

sum += day;

 

if ((mouth > 2) && ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0))//判断如果月份大于2且当前年是闰年的话给总天数加1,因为闰年的2月份比平年多1天

sum += 1;

printf("该日是该年的第%d天。", sum);

}

void main()

{

int year, mouth, day;

printf("请输入年月日:");

scanf("%d %d %d", &year, &mouth, &day);

seek(year, mouth, day);

}

C执行结果

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

立志冲海大

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值