首页 > 技术文章 > C程序设计(第五版)-第7章 用函数实现模块化程序设计课后习题答案

luckyang 2022-01-18 14:57 原文

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

题目解析:

  • 该题直接使用“辗转相除法”来求解最大公约数和最小公倍数
  • 最大公约数函数(利用欧几里得算法)
  • 最小公倍数 = x * y / 最大公约数
#include <stdio.h>
#include <windows.h>

int HCF(int x, int y); // 定义最大公约数函数
int LCM(int x, int y); // 定义最小公倍数函数

int main()
{
    int a, b, hcf, lcm;
    printf("请输入两个数:\n");
    scanf("%d %d", &a, &b);
    hcf = HCF(a, b);
    lcm = LCM(a, b);

    printf("最大公约数:%d,最小公倍数:%d", hcf, lcm);
    return 0;
}

int HCF(int x, int y)
{
    int hcf = 0;
    if (y > x)
    {
        int temp = y;
        y = x;
        x = temp;
    }

    //1997 / 615 = 3 (余 152)
    // 615 / 152 = 4(余7)
    // 152 / 7 = 21(余5)
    // 7 / 5 = 1 (余2)
    // 5 / 2 = 2 (余1)
    // 2 / 1 = 2 (余0)
    // 至此,最大公约数为1
    for (int z = x % y; z != 0;)
    {
        x = y;
        y = z;
        z = x % y;
    }

    return y;
}

int LCM(int x, int y)
{
    return (x * y) / HCF(x, y);
}

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

#include <stdio.h>
#include <windows.h>
#include <math.h>

void greater_than_zero(float a, float b, float disc);
void equal_to_zero(float a, float b);
void smaller_than_zero(float a, float b, float disc);

// 请输入a,b,c:
// 3 4 1
// b^2-4ac=4.000000
// x1 = -0.333333, x2 = -1.000000
int main()
{

    float a, b, c, disc;
    printf("请输入a,b,c:\n");
    scanf("%f %f %f", &a, &b, &c);

    disc = pow(b, 2) - (4 * a * c);
    printf("b^2-4ac=%f\n", disc);

    if (disc > 0)
    {
        greater_than_zero(a, b, disc);
    }
    else if (disc == 0)
    {
        equal_to_zero(a, b);
    }
    else if (disc < 0)
    {
        smaller_than_zero(a, b, disc);
    }

    return 0;
}

void greater_than_zero(float a, float b, float disc)
{
    float x1, x2;
    x1 = (-b + sqrt(disc)) / (2 * a);
    x2 = (-b - sqrt(disc)) / (2 * a);
    printf("x1 = %f, x2 = %f\n", x1, x2);
}
void equal_to_zero(float a, float b)
{
    float x;
    x = (-b) / (2 * a);
    printf("x1 = x2 = %f\n", x);
}
void smaller_than_zero(float a, float b, float disc)
{
    float x1, x2;
    x1 = (-b + sqrt(disc)) / (2 * a);
    x2 = (-b - sqrt(disc)) / (2 * a);
    printf("x1 = %f, x2 = %f\n", x1, x2);
}

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

  • 素数是一个大于1的自然数,除了1和它自身外,不能被其他自然数整除的数叫做素数
  • 该题可以使用概念直接判断法求解,不过不需要判断所有的数据,只需要判断数据的一半即可,因为偶数不可能为素数(除了2),所以只需判断该数的一半即可的到答案
#include <stdio.h>
#include <windows.h>

void isAPrimeNumber(int x);
int main()
{
    int x;

    do
    {
        printf("请输入一个整数\n");
        scanf("%d", &x);
    } while (x <= 1);
    isAPrimeNumber(x);
    return 0;
}

void isAPrimeNumber(int x)
{
    int flag = 1; // 1代表是 0代表false

    for (int i = 2; i <= x / 2; i++)
    {
        if (x % i == 0)
        {
            flag = 0;
            break;
        }
    }

    if (flag)
    {
        printf("%d是素数\n", x);
    }
    else
    {
        printf("%d不是素数\n", x);
    }
}

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

#include <stdio.h>
#include <windows.h>

void PrintArray(int ar[3][3]);
void ReverseArray(int ar[3][3]);

int main()
{
    printf("------------------\n");
    int a[3][3] = {
        {0, 1, 2}, 
        {3, 4, 5}, 
        {6, 7, 8}
        };
    printf("---------前---------\n");
    PrintArray(a);
    printf("---------后---------\n");
    ReverseArray(a);

    return 0;
}

void PrintArray(int ar[3][3])
{
    for (int i = 0; i < 3; i++)
    {
        for (int j = 0; j < 3; j++)
        {
            printf("%d ", ar[i][j]);
        }
        printf("\n");
    }
}
void ReverseArray(int ar[3][3])
{
    int result[3][3];

    for (int i = 0; i < 3; i++){
        for (int j = 0; j < 3; j++){
            result[i][j] = ar[j][i];
        }
    }

    PrintArray(result);

}

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

题目解析及答案:

  • 要把一个字符串反序存放,其实就是对字符串做一个逆序操作,操作过程为收尾字符交换,直到把所有字符全部交换完毕。
#include <stdio.h>
#include <windows.h>

void reverseChar(char a[]);

int main()
{
    printf("-------请输入10个字符串-----------\n");
    char a[10];
    scanf("%s", a);
    printf("-------前-----------\n");
    printf("%s\n", a);
    reverseChar(a);
    printf("-------后-----------\n");
    puts(a);

    return 0;
}

void reverseChar(char a[])
{
    int start = 0;
    int end = strlen(a) - 1; // 数组下表从0开始

    while (end > start)
    {
        char temp = a[end];
        a[end] = a[start];
        a[start] = temp;

        start++;
        end--;
    }
}

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

题目解析及答案:

  • 利用一个临时数组,空间要保证能够容纳两个字符串,先把第一个字符串进行拷贝到临时数组,第二个字符串在临时数组的尾部接着链接,最后记得加上字符串的结束标记\0即可
#include <stdio.h>
#include <windows.h>

void cat(char a[], char b[], char c[]);

int main()
{
    printf("------------------\n");
    char a[10], b[10], c[20];
    printf("输入a字符串:\n");
    gets(a);
    printf("输入b字符串:\n");
    scanf("%s", &b);
    cat(a, b, c);
    return 0;
}

void cat(char a[], char b[], char c[])
{
    int j = 0;

    for (int i = 0; i < strlen(a) & a[i] != '\0'; i++, j++)
    {
        c[j] = a[i];
    }

    for (int i = 0; i < strlen(b) & b[i] != '\0'; i++, j++)
    {
        c[j] = b[i];
    }

    c[j + 1] = '\0';

    puts(c);
}

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

#include <stdio.h>
#include <windows.h>
void cpy(char s[], char c[])
{
    int i, j;
    for (i = 0, j = 0; s[i] != '\0'; 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')
        {
            c[j] = s[i];
            j++;
        }
    }
    c[j] = '\0';
}

int main()
{
    char str[80], c[80];
    printf("input string:");
    gets(str);
    cpy(str, c); //将str中的元音字母拷贝到c中
    printf("The vowel letters are:%s\n", c);
    return 0;
}

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

#include <stdio.h>
#include <windows.h>
void OutString(char str[]);

int main()
{
    printf("------------------\n");

    char str[5] = {0};
    printf("input four digits:");
    scanf("%s", str);
    OutString(str);
    return 0;
}

void OutString(char str[])
{
    for (int i = 0; i < strlen(str); i++)
    {
        printf("%c", str[i]);
        // 最后一个不输出-
        if (i == strlen(str) - 1)
        {
            break;
        }
        else
        {
            printf("-");
        }
    }
}

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

#include <stdio.h>
#include <windows.h>

void statisticsStrCount(char a[]);
int main()
{
    char a[100];
    printf("请输入一cuan字符串\n");
    gets(a);
    statisticsStrCount(a);
    return 0;
}

void statisticsStrCount(char a[])
{
    int alphabet_count = 0, number_count = 0, blank_count = 0, other_count = 0;
    for (int i = 0; i < 100 & a[i] != '\0'; i++)
    {
        if ((a[i] >= 'a' && a[i] <= 'z') || (a[i] >= 'A' && a[i] <= 'Z'))
        {
            alphabet_count++;
        }
        else if ((a[i] >= '0' && a[i] <= '9'))
        {
            number_count++;
        }
        else if (a[i] = ' ')
        {
            blank_count++;
        }
        else
        {
            other_count++;
        }
    }

    printf("字母:%d个,数字:%d个,空格:%d个,其它:%d个", alphabet_count, number_count, blank_count, other_count);
}

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

题目解析及答案:

单词以空格进行分隔,因此寻找空格出现的位置即为关键,每次从单词的起始到空格出现的位置即为一个单词,此时计算单词的长度,如果比当前最大的还长,就进行跟新最长单词信息,当整个字符串遍历完成,word即保存最长字符串。

#include <stdio.h>
#include <windows.h>
void statisticsMaxStr(char a[]);
int main()
{
    char a[100];
    printf("请输入一段英文\n");
    gets(a);
    statisticsMaxStr(a);
    return 0;
}

void statisticsMaxStr(char a[])
{
    char maxStr[50];
    int maxStrCount = 0, currentCount = 0;
    int minIndex = 0, maxIndex = 0, i;

    for (i = 0; i < 100 & a[i] != '\0'; i++)
    {
        currentCount++;

        // 碰到空格,将计数器赋值为0
        if (a[i] == ' ')
        {
            if (currentCount >= maxStrCount)
            {
                maxStrCount = currentCount;
                maxIndex = i;
                minIndex = i + 1 - currentCount;
            }
            currentCount = 0;
        }
    }

    if (currentCount >= maxStrCount) //此乃用于最长的单词在结尾的情况
    {
        maxStrCount = currentCount;
        maxIndex = i;
        minIndex = i + 1 - currentCount;
    }

    for (int i = minIndex; i < maxIndex; i++)
    {
        printf("%c", a[i]);
    }
}

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

#include <stdio.h>
#include <windows.h>

void sortChar(char a[]);
int main()
{
    char a[10];
    printf("请输入10个字符:");
    gets(a);
    sortChar(a);
    return 0;
}

void sortChar(char a[])
{
    for (int i = 0; i < strlen(a)-1; i++)
    {
        for (int j = 0; j < strlen(a) - i - 1; j++)
        {
            if (a[j + 1] < a[j])
            {
                char temp = a[j];
                a[j] = a[j + 1];
                a[j + 1] = temp;
            }
        }
    }

    puts(a);
}

12、用牛顿迭代法求根。方程为ax3+bx2 +cx+d=0, 系数a,b,c,d的值依次为1,2,3,4,由主函数输人。求x在1附近的一个实根。求出根后由主函数输出。

题目解析及答案:

此题的难点并不是编程,主要是要理解数学公式的求解方法,理解之后代码的实现并不困难。

#include<stdio.h>
#include<math.h>

float solut(int a, int b, int c, int d)
{
	float x = 1, x0, f, f1;
	do
	{
		x0 = x;
		f = ((a*x0 + b)*x0 + c)*x0 + d;
		f1 = (3 * a*x0 + 2 * b)*x0 + c;
		x = x0 - f / f1;
	} while (fabs(x - x0) >= 1e-3);
	return(x);
}

int main()
{
	int a, b, c, d;
	printf("input a,b,c,d:");
	scanf("%d %d %d %d", &a, &b, &c, &d);
	printf("x=%10.7f\n", solut(a, b, c, d));
	return 0;
}

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

image-20220112112759382

  • 递归函数的设计,有一个点非常重要,那就是必须要有返回条件,,此题中的返回条件即为n0和n1时,因为当n为这两值时,程序直接返回相应的值,只有n>=1时,才进行递归运算。
#include<stdio.h>

double polya(int n,int x)
{
	double result; 
	if(n == 0)  
		result = 1;  
	if(n == 1)
		result = x; 
	if(n>1)
		result = ((2*n-1)*x*polya(n-1,x)-(n-1)*polya(n-2,x))/n;    
	return result;
}

int main()
{ 
	int x,n; 
	scanf("%d %d", &n, &x); 
	printf("%.2f\n", polya(n,x)); 
	return 0;
}

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

①计算每个学生的平均分;
②计算每门课的平均分;
③找出所有50个分数中最高的分数所对应的学生和课程;
④计算平均分方差:

其中,x;为某一学生的平均分。

题目解析及答案:
此题的关键是如何存储某个学生对应某门课程的分数,这里利用了一个二维数组score,其中score[i] [j]就代表了第i个学生的第j门课程的分数,只要能够理解这个存储方式,其余的计算就是比较容易理解和实现的。

#include <stdio.h>
#include <windows.h>

#define M 10
#define N 5

void studentAverageScore(float a[M][N]);         // 计算每个学生的平均分
void scourseAverageScore(float a[M][N]);         // 计算每门课的平均分
void studentMaxScoreAndScore(float a[M][N]);     // 找出所有50个分数中最高的分数所对应的学生和课程
float studentAverageScoreVariance(float a[M][N]); // 计算平均分方差

float a[M][N];
float a_stu[M], a_cour[N];

int main()
{
    printf("输入分数\n");
    for (int i = 0; i < M; i++)
    {
        for (int j = 0; j < N; j++)
        {
            scanf("%f", &a[i][j]);
        }
    }

    studentAverageScore(a);
    scourseAverageScore(a);
    studentMaxScoreAndScore(a);
    studentAverageScoreVariance(a);

    return 0;
}

void studentAverageScore(float a[M][N])
{
    for (int i = 0; i < M; i++)
    {
        float totalScore = 0;

        for (int j = 0; j < N; j++)
        {
            totalScore += a[i][j];
        }
        a_stu[i] = totalScore / 5.0;
        printf("第%d个学生平均成绩:%f", i, totalScore / N);
    }
}
void scourseAverageScore(float a[M][N])

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

        for (int j = 0; j < M; j++)
        {
            totalScore += a[j][i];
        }

        a_cour[i] = totalScore / (float)M;
        printf("第%d门课程平均成绩:%f", i, totalScore / M);
    }
}
void studentMaxScoreAndScore(float a[M][N])
{

    int x, y;
    int maxScore = 0;

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

        for (int j = 0; j < N; j++)
        {
            if (a[i][j] >= maxScore)
            {
                maxScore = a[i][j];
                x = i;
                y = j;
            }
        }

        printf("第%d个学生的%d课程成绩最好", x, y);
    }
}
float studentAverageScoreVariance(float a[M][N])
{
    int i;
    float sumx, sumxn;
    sumx = 0.0;
    sumxn = 0.0;
    for (i = 0; i < N; i++)
    {
        sumx += a_stu[i] * a_stu[i];
        sumxn += a_stu[i];
    }
    return (sumx / N - (sumxn / N) * (sumxn / N));
}

15、写几个函数:

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

题目解析及答案:
利用二分查找的关键在于数据一定要先有序,所以在查找前我们需要对数据进行排序。

#include <stdio.h>
#include <windows.h>

#define N 4
struct Employee // 职工结构体
{
    int id;        // 职工编号
    char name[20]; // 职工姓名
};

void inputEmployee(struct Employee e[N]);
void sortEmployee(struct Employee e[N]);
void searchEmployee(struct Employee e[N], int id);

main()
{
    printf("------------------\n");
    int id;
    struct Employee employeeAry[N]; //创建N个结构体数组
    inputEmployee(employeeAry);
    sortEmployee(employeeAry);

    printf("请输入要查找的员工编号:");
    scanf("%d", &id);
    searchEmployee(employeeAry, id);
    return 0;
}

void inputEmployee(struct Employee e[N])
{
    for (int i = 0; i < N; i++)
    {
        printf("请输入第%d个员工编号:", i);
        scanf("%d", &e[i].id);
        printf("请输入第%d个员工姓名:", i);
        scanf("%s", &e[i].name);
        printf("\n");
    }
}
void sortEmployee(struct Employee e[N])
{
    // 冒泡排序法
    for (int i = 0; i < N - 1; i++)
    {
        for (int j = 0; j < N - 1 - i; j++)
        {
            if (e[j + 1].id < e[j].id)
            {
                struct Employee temp;
                temp.id = e[j + 1].id;
                strcpy(temp.name, e[j + 1].name);

                e[j + 1].id = e[j].id;
                strcpy(e[j + 1].name, e[j].name);

                e[j].id = temp.id;
                strcpy(e[j].name, temp.name);
            }
        }
    }
}
void searchEmployee(struct Employee e[N], int id)
{
    int mid, min, max, flag;
    min = 0;
    max = N - 1;
    flag = 0; // 没有该编号员工

    // 二分查找
    while (min <= max)
    {
        mid = (min + max) / 2;
        if (e[mid].id > id)
        {
            max = mid - 1;
        }
        else if (e[mid].id < id)
        {
            min = mid + 1;
        }
        else if (e[mid].id = id)
        {
            printf("编号%d的员工姓名是:%s", id, e[mid].name);
            flag = 1;
            return;
        }
    }

    if (flag == 0)
    {
        printf("编号%d的员工不存在", id);
    }
}

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

题目解析及答案:

  • 转换的过程需要乘的基数为16,其次注意十六进制中的a~f的字母转换,并且无论大小写都要能够转换。
#include <stdio.h>
#include <windows.h>
#include <math.h>

void HextoDec(char a[]);
int main()
{
    char a[20];
    // 十六进制整常数的前缀为0X或0x
    printf("输入一个十六进制数:");
    gets(a);
    HextoDec(a);
    return 0;
}

// 例:2AF5换算成10进制:
// 用竖式计算:
// 第0位: 5 * 16^0 = 5
// 第1位: F * 16^1 = 240
// 第2位: A * 16^2= 2560
// 第3位: 2 * 16^3 = 8192
// -------------------------------------
// 10997
// 直接计算就是:
// 5 * 16^0 + F * 16^1 + A * 16^2 + 2 * 16^3 = 10997
void HextoDec(char a[])
{
    int result = 0;
    for (int i = 0, j = strlen(a) - 1; i < strlen(a); i++, j--)
    {
        if (a[i] == 'A' || a[i] == 'a')
        {
            result += (10 * pow(16, j));
        }
        else if (a[i] == 'B' || a[i] == 'b')
        {
            result += (11 * pow(16, j));
        }
        else if (a[i] == 'C' || a[i] == 'c')
        {
            result += (12 * pow(16, j));
        }
        else if (a[i] == 'D' || a[i] == 'd')
        {
            result += (13 * pow(16, j));
        }
        else if (a[i] == 'E' || a[i] == 'e')
        {
            result += (14 * pow(16, j));
        }
        else if (a[i] == 'F' || a[i] == 'f')
        {
            result += (15 * pow(16, j));
        }
        else
        {
            // ASCII码为0时,ASCII码对应48,所以(对应数字 = ASCII码- 48)
            result += ((a[i] - 48) * pow(16, j));
        }
    }

    printf("十六进制%s的二进制是:%d", a, result);
}

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

题目解析及答案:

  • 递归法求解主要要有结束条件,此题为n/10 == 0时就直接输出,其次本题还要考虑如果整数位负数的情形,此时需要输出一个字符串的负号。
#include <stdio.h>
#include <windows.h>

void convert(int number);
int main()
{
    int number;
    printf("请输入一个整数\n");
    scanf("%d", &number);
    if (number < 0)
    {
        putchar('-');
        number = -number;
    }
    convert(number);
    return 0;
}

void convert(int number)
{
    int i;
    if ((i = number / 10) != 0)
    {
        convert(i);
    }
    putchar(number % 10 + '0');
}

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

题目解析:

  • 此题采用枚举法进行每月天数的累加,其中关键点注意需要判断年份是否为闰年,如果是还需要多累加1天。
#include <stdio.h>
#include <windows.h>

int sumDay(int month, int day); // 计算日子
int leap(int year);             // 是否是闰年,闰年返回1,不是返回0

// 请输入年,月,日:
// 2020 6 24
// 2020-6-24是今年的第176天
int main()
{
    int year, month, day;
    printf("请输入年,月,日:\n");
    scanf("%d %d %d", &year, &month, &day);
    int sumDayCount = sumDay(month, day);
    int leapCount = leap(year);
    int total = sumDayCount + leapCount;
    printf("%d-%d-%d是今年的第%d天", year, month, day, total);
    return 0;
}

int sumDay(int month, int day)
{
    int sumDayCount = 0;
    int monthlyDay[13] = {0,
                          31,
                          28,
                          31,
                          30,
                          31,
                          30,
                          31,
                          31,
                          30,
                          31,
                          30,
                          31};

    for (int i = 1; i < month; i++)
    {
        sumDayCount += monthlyDay[i];
    }
    sumDayCount += day;
    return sumDayCount;
}
int leap(int year)
{
    int leapCount;
    leapCount = year % 4 == 0 && year % 100 != 0 || year % 400 == 0;
    return leapCount;
}

C程序设计(第五版)-第1章 程序设计和C语言课后习题答案
C程序设计(第五版)-第2章 算法--程序的灵魂课后习题答案
C程序设计(第五版)-第3章 最简单的C程序设计—顺序程序设计课后习题答案
C程序设计(第五版)-第4章 选择结构程序设计课后习题答案
C程序设计(第五版)-第5章 循环结构程序设计课后习题答案
C程序设计(第五版)-第6章 利用数组处理批量数据课后习题答案
C程序设计(第五版)-第7章 用函数实现模块化程序设计课后习题答案

推荐阅读