谭浩强C语言程序设计(3) 7章

1、递归实现N的阶乘

c复制
#include <cstdio>  // 包含标准输入输出库

// 计算n的阶乘
int total = 0;  // 定义全局变量total用于存储阶乘结果

// 递归函数计算阶乘
int fac(int a){
    // 如果输入的数小于0,输出错误信息
    if (a < 0){
        printf("%d < 0,error!",a);
    } 
    // 如果输入的数是0或1,阶乘结果为1
    else if (a == 0 || a==1){
        total = 1;
    }
    // 否则,递归调用fac函数计算阶乘
    else{
        total = fac(a - 1) * a;
    }
    // 返回阶乘结果
    return total;
}

int main() {
    // 定义变量a用于接收用户输入的数
    int a;
    // 提示用户输入一个数
    puts("input a number:\n");
    // 读取用户输入的数
    scanf("%d",&a);
    // 调用fac函数计算阶乘结果
    int result = fac(a);
    // 输出阶乘结果
    printf("result = %d",result);
}

 2、汉诺塔问题

不会。

3、输入10个数,输出最大值并且输出是第几个数

#include <cstdio>  // 包含标准输入输出库
#define n 10  // 定义数组的大小为10

// 定义函数用于获取两个数中的最大值
int getMax(int a, int b){
    // 使用三元运算符返回较大的数
    return a > b ? a : b;
}

int main() {
    // 定义一个大小为n的整数数组
    int a[n];
    // 循环提示用户输入10个数,并存储到数组中
    for (int i = 0; i < n; ++i) {
        printf("input %d :", i + 1);  // 提示用户输入第i+1个数
        scanf("%d", &a[i]);  // 读取用户输入的数并存储到数组的第i个位置
    }
    // 初始化最大值为数组的第一个元素
    int max = a[0];
    // 初始化最大值的索引为0
    int max_index = 0;
    // 循环遍历数组,找到最大值及其索引
    for (int i = 0; i < n; ++i) {
        // 使用getMax函数比较当前最大值和数组中的第i个元素
        if (getMax(max, a[i]) > max) {
            // 如果找到更大的值,更新最大值
            max = getMax(max, a[i]);
            // 更新最大值的索引
            max_index = i;
        }
    }
    // 输出最大值及其索引
    printf("max is :%d and index is %d", max, max_index);
}

4、选择法对十个数进行从小到大的排序

#include <cstdio>  // 包含标准输入输出库
#define n 10  // 定义数组的大小为10

// 选择法对数组进行排序
void sort(int a[], int length){
    int min, temp;  // min用于存储最小元素的下标,temp用于交换元素
    // 外层循环,遍历数组的每个元素
    for (int i = 0; i < n; ++i) {
        min = i;  // 假设当前元素是最小的
        // 内层循环,从当前元素的下一个元素开始,寻找最小元素
        for (int j = i + 1; j < n; ++j) {
            // 如果找到更小的元素,更新min的值
            if (a[j] < a[min]){
                min = j;
            }
        }
        // 如果找到的最小元素不是当前元素,进行交换
        if (min != i){
            temp = a[i];
            a[i] = a[min];
            a[min] = temp;
        }
    }
}

int main() {
    int a[n] = {0};  // 定义一个大小为n的整数数组,并初始化为0
    int i = 0;  // 定义循环变量
    // 循环提示用户输入10个数,并存储到数组中
    while(i < 10){
        printf("input the NO.%d:", i + 1);  // 提示用户输入第i+1个数
        scanf("%d", &a[i]);  // 读取用户输入的数并存储到数组的第i个位置
        i++;  // 循环变量自增
    }
    // 调用sort函数对数组进行排序
    sort(a, n);

    // 循环输出排序后的数组
    for (int j = 0; j < n; ++j) {
        printf("%d ", a[j]);
    }
}

5、输出1到5的阶乘的值

使用局部静态变量

6、使用函数调用的方式实现求两个数的最大公约数和最小公倍数

原理:

辗转相除法基于以下原理:两个整数的最大公约数等于其中较小的数和两数相除余数的最大公约数。换句话说,如果你有两个整数 a 和 b(假设 a>b),它们的最大公约数与 b 和 amodb(即 a 除以 b 的余数)的最大公约数相同。

算法步骤

  1. 输入两个整数 a 和 b,其中 a≥b。

  2. 计算余数 r=amodb。

  3. 更新数值:将 a 的值更新为 b,将 b 的值更新为 r。

  4. 重复步骤2和3,直到 b 变为0。

  5. 结果:当 b 变为0时,a 的值即为两数的最大公约数。

示例

假设我们要计算 48 和 18 的最大公约数:

  1. 48mod18=12,更新 a=18,b=12。

  2. 18mod12=6,更新 a=12,b=6。

  3. 12mod6=0,更新 a=6,b=0。

此时,b=0,所以最大公约数是 a=6。

最小公倍数就是48*18/6=144

为什么不需要大小判断?

  • 通用性:算法的每一步都是基于当前的 mn 进行的,无论它们的初始大小关系如何。算法通过不断地交换 mn 的角色(即 m 变成 nn 变成 m % n),确保了算法的通用性和正确性。

  • 假设m=18,n=48时,因为18%48=18,所以m=48,n=18,就换过来了。

#include "stdio.h"

// 计算最大公约数的函数
// 参数 m 和 n 是需要计算最大公约数的两个整数
// 返回值是 m 和 n 的最大公约数
int gcd(int m, int n){
    int temp;
    // 当 n 不为 0 时,继续执行循环
    while(n != 0){
        // 计算 m 除以 n 的余数
        temp = m % n;
        // 更新 m 为 n,n 为余数 temp
        m = n;
        n = temp;
    }
    // 当 n 为 0 时,m 就是最大公约数
    return m;
}

// 计算最小公倍数的函数
// 参数 M 和 N 是原始的两个整数,gcd_value 是它们的最大公约数
// 返回值是 M 和 N 的最小公倍数
int lcm(int M, int N, int gcd_value){
    // 最小公倍数等于两数乘积除以它们的最大公约数
    return M * N / gcd_value;
}

int main(){
    int m, n;
    // 提示用户输入第一个整数 m
    printf("please input m: ");
    // 读取用户输入的整数 m
    scanf("%d", &m);
    // 提示用户输入第二个整数 n
    printf("please input n: ");
    // 读取用户输入的整数 n
    scanf("%d", &n);
    // 调用 gcd 函数计算 m 和 n 的最大公约数
    int max = gcd(m, n); 
    // 调用 lcm 函数计算 m 和 n 的最小公倍数
    int min = lcm(m, n, max); 
    // 输出最大公约数和最小公倍数
    printf("gcd=%d, lcm=%d\n", max, min);
    return 0;
}

7、写三个函数计算如下方程在判别式>0、=0、<0下的根

#include "stdio.h"  // 引入标准输入输出库,用于输入输出操作
#include "math.h"   // 引入数学库,用于计算平方根等数学函数

// 定义全局变量,用于存储一元二次方程的系数和解
float a, b, c, dt, x1, x2;

// 当判别式大于零时,调用此函数计算两个不同的实数根并输出结果
void more_than_zero(){
    x1 = (-b + sqrt(dt)) / (2 * a);  // 根据求根公式计算第一个根
    x2 = (-b - sqrt(dt)) / (2 * a);  // 根据求根公式计算第二个根
    printf("x1 = %f , x2 = %f\n", x1, x2);  // 输出两个实数根
}

// 当判别式等于零时,调用此函数计算两个相等的实数根并输出结果
void equal_zero(){
    x1 = x2 = (-b) / (2 * a);  // 根据求根公式计算两个相等的根
    printf("x1 = %f , x2 = %f\n", x1, x2);  // 输出两个相等的实数根
}

// 当判别式小于零时,调用此函数输出没有实数根的信息
void small_than_zero(){
    // 输出没有实数根,而是复数根的信息
    printf("No real roots: x1 = %f+%fi, x2 = %f-%fi\n", 
           (-b) / (2 * a), sqrt(-dt) / (2 * a), (-b) / (2 * a), sqrt(-dt) / (2 * a));
}

int main(){
    // 提示用户输入一元二次方程的系数 a, b, c
    printf("please input a: ");
    scanf("%f", &a);
    printf("please input b: ");
    scanf("%f", &b);
    printf("please input c: ");
    scanf("%f", &c);

    // 计算判别式 dt = b^2 - 4ac
    dt = pow(b, 2) - 4 * a * c;

    // 根据判别式的值,选择不同的函数来计算根
    if (dt > 0){
        more_than_zero();  // 判别式大于零,有两个不同的实数根
    } else if(dt == 0){
        equal_zero();  // 判别式等于零,有两个相等的实数根
    } else{
        small_than_zero();  // 判别式小于零,没有实数根
    }

    return 0;  // 程序结束
}

8、使用函数调用判断一个数是不是素数

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


// 函数用于判断一个数是否为素数
bool judge(int a) {
    // 处理小于2的数和2的情况
    if (a <= 1) {
        return false;  // 小于等于1的数不是素数
    }
    if (a == 2) {
        return true;  // 2是素数
    }
    if (a % 2 == 0) {
        return false;  // 排除所有大于2的偶数
    }
    // 只需检查到sqrt(a),且只需检查奇数
    for (int i = 3; i <= sqrt(a); i += 2) {
        if (a % i == 0) {
            return false;  // 如果a能被i整除,则a不是素数
        }
    }
    return true;  // 如果没有找到因子,则a是素数
}

int main() {
    int a;
    printf("Input a number: ");
    scanf("%d", &a);
    if (judge(a)) {
        printf("%d is a prime number.\n", a);
    } else {
        printf("%d is not a prime number.\n", a);
    }
    return 0;
}

9、写个函数实现3x3矩阵转置

#include <stdio.h>
#define N 3  // 定义矩阵的大小为 3x3

int a[N][N];  // 定义一个 3x3 的矩阵 a

// 函数用于转换矩阵,即计算矩阵的转置
void convert(){
    int temp;
    // 遍历矩阵的上三角部分
    for (int i = 0; i < N; ++i) {
        // 从 i+1 开始,避免重复交换和自身交换
        for (int j = i + 1; j < N; ++j) {
            // 交换元素
            temp = a[i][j];
            a[i][j] = a[j][i];
            a[j][i] = temp;
        }
    }
}

int main(){
    // 输入矩阵的元素
    for (int i = 0; i < N; ++i) {
        printf("Input the elements of line %d\n", i + 1);
        for (int j = 0; j < N; ++j) {
            printf("Input the No. %d element: ", j + 1);
            scanf("%d", &a[i][j]);  // 读取用户输入的元素
        }
        printf("\n");
    }

    // 输出原始矩阵
    printf("Original matrix:\n");
    for (int i = 0; i < N; ++i) {
        for (int j = 0; j < N; ++j) {
            printf("%3d", a[i][j]);  // 输出矩阵元素,占3个字符宽度
        }
        printf("\n");
    }

    // 调用函数计算矩阵的转置
    convert();

    // 输出转置后的矩阵
    printf("\nTransposed matrix:\n");
    for (int i = 0; i < N; ++i) {
        for (int j = 0; j < N; ++j) {
            printf("%3d", a[i][j]);  // 输出转置后的矩阵元素
        }
        printf("\n");
    }

    return 0;  // 程序结束
}

10、调用函数实现字符串反转

#include "stdio.h"  // 引入标准输入输出库
#include "string.h" // 引入字符串处理库
#define N 100      // 定义字符串的最大长度为100

// 函数用于反转字符串
void reserve(char a[N]){
    int temp;  // 用于交换字符的临时变量
    int len = strlen(a);  // 获取字符串的长度
    // 遍历字符串的前半部分
    for (int i = 0; i < len / 2; ++i) {
        temp = a[i];  // 保存当前字符
        a[i] = a[len - i - 1];  // 将对称位置的字符赋值给当前位置
        a[len - i - 1] = temp;  // 将保存的字符赋值给对称位置
    }
}

int main(){
    char str[N];  // 定义一个字符数组,用于存储输入的字符串
    printf("Input a string:\n");  // 提示用户输入字符串
    gets(str);  // 使用gets函数读取一行文本,包括空格,直到遇到换行符
    reserve(str);  // 调用reserve函数反转字符串
    puts(str);  // 使用puts函数输出反转后的字符串
    return 0;  // 程序结束
}

11、调用函数实现两个字符串连接

#include <cstdio>  // 包含标准输入输出库
//#include "string"  // 这里注释掉了,因为代码中没有使用到<string>库的功能

#define N 30  // 定义一个宏N,表示字符串数组的最大长度

char s1[N], s2[N];  // 定义两个字符数组s1和s2,用于存储输入的字符串

// 函数定义:实现两个字符串的拼接
void concatStr(char s1[], char s2[]) {
    int i = 0, j = 0;  // 定义两个索引变量i和j,分别用于遍历s1和s2

    // 遍历s1,找到第一个空字符'\0'的位置,即s1的末尾
    while (s1[i] != '\0' && i < N) {
        i++;
    }

    // 遍历s2,将s2中的字符依次复制到s1的末尾
    while (s2[j] != '\0' && j < N) {
        s1[i++] = s2[j++];  // 将s2[j]赋值给s1[i],然后i和j分别加1
    }

    // 注意:这里没有显式地在s1的末尾添加'\0',但因为s1原本就有'\0',所以拼接后仍然保持字符串的格式
}

int main() {
    // 提示用户输入第一个字符串
    printf("input the first:\n");
    gets(s1);  // 使用gets函数读取用户输入的字符串,存储到s1中

    // 提示用户输入第二个字符串
    printf("input the second:\n");
    gets(s2);  // 使用gets函数读取用户输入的字符串,存储到s2中

    // 调用concatStr函数,将s2拼接到s1的末尾
    concatStr(s1, s2);

    // 输出拼接后的结果
    printf("the result is:\n");
    puts(s1);  // 使用puts函数输出s1的内容

    return 0;  // 程序正常结束
}

12、将一个字符串s1的元音字母复制到另一个字符串s2,然后输出s2

元音字母:a e i o u A E I O U

#include <cstdio>  // 包含标准输入输出库
#define N 20  // 定义一个宏N,表示字符串数组的最大长度

// 函数定义:将s1中的元音字母复制到s2中
void copy(char s1[], char s2[]) {
    int i = 0, j = 0;  // 定义两个索引变量i和j,分别用于遍历s1和s2

    // 遍历s1字符串
    while (s1[i] != '\0' && i < N) {  // 当s1[i]不是字符串结束符'\0'且i小于数组大小N时
        // 判断s1[i]是否为元音字母(包括大小写)
        if (s1[i] == 'a' || s1[i] == 'e' || s1[i] == 'i' || s1[i] == 'o' || s1[i] == 'u' ||
            s1[i] == 'A' || s1[i] == 'E' || s1[i] == 'I' || s1[i] == 'O' || s1[i] == 'U') {
            s2[j++] = s1[i];  // 如果是元音字母,则将其复制到s2中,并将j加1
        }
        i++;  // 继续遍历s1的下一个字符
    }
    s2[j] = '\0';  // 在s2的末尾添加字符串结束符'\0'
}

int main() {
    char s1[N], s2[N];  // 定义两个字符数组s1和s2,分别用于存储输入的字符串和结果字符串

    // 提示用户输入字符串
    puts("input the string:");
    gets(s1);  // 使用gets函数读取用户输入的字符串,存储到s1中

    // 调用copy函数,将s1中的元音字母复制到s2中
    copy(s1, s2);

    // 输出结果字符串s2
    printf("s2:");
    puts(s2);  // 使用puts函数输出s2的内容

    return 0;  // 程序正常结束
}

在C语言中,字符串操作函数(如putsprintf等)依赖字符串的结束符'\0'来确定字符串的结束位置。如果不显式地添加'\0'puts函数会继续读取s2数组之后的内存内容,直到遇到一个'\0'为止。这可能会导致输出乱码或程序崩溃。

 13、输入1990输出1 9 9 0

#include <cstdio>  // 包含标准输入输出库
#include <cstring> // 包含字符串处理函数的头文件
#define N 20       // 定义一个宏N,表示字符串数组的最大长度

// 函数定义:将字符串s中的字符按照“字符-空格”的模式重新排列
void convert(char s[]) {
    int len = 2 * strlen(s) - 1;  // 计算新字符串的长度,每个字符之间插入一个空格
    char s1[N];                   // 定义一个临时数组s1,用于存储原始字符串
    int j = 0;                    // 定义一个索引变量j,用于遍历s1

    // 使用strcpy函数将s的内容复制到s1中
    strcpy(s1, s);

    // 遍历新字符串的每个位置
    for (int i = 0; i < len; ++i) {
        // 如果索引i是偶数,则将s1中的字符复制到s[i]中
        // 否则,在s[i]中插入一个空格
        s[i] = i % 2 == 0 ? s1[j++] : ' ';
    }
}

int main() {
    char s[N];  // 定义一个字符数组s,用于存储用户输入的字符串

    // 提示用户输入字符串
    puts("input the string:");
    gets(s);  // 使用gets函数读取用户输入的字符串

    // 调用convert函数,将字符串s中的字符按照“字符-空格”的模式重新排列
    convert(s);

    // 输出结果
    puts("s:");
    puts(s);  // 使用puts函数输出处理后的字符串s

    return 0;  // 程序正常结束
}

 14、调用函数实现计算字符串中字母、数字、空格和其他字符的个数

#include <cstdio>
#define N 50

static int zimu,shuzi,space,others;
void compute(char s[]){
    int i = 0;
    while(i < N && s[i] != '\0'){
        // 判断字符是否为字母(包括大小写)
        if ((s[i] >= 'a' && s[i] <= 'z') || (s[i] >= 'A' && s[i] <= 'Z')) {
            zimu++;  // 字母计数加1
        }
            // 判断字符是否为数字
        else if (s[i] >= '0' && s[i] <= '9') {
            shuzi++;  // 数字计数加1
        }
            // 判断字符是否为空格
        else if (s[i] == ' ') {
            space++;  // 空格计数加1
        }
            // 其他字符
        else {
            others++;  // 其他字符计数加1
        }
        i++;
    }
}

int main(){
    char s[N];
    puts("input the string:");
    gets(s);
    compute(s);
    printf("zimu:%d,shuzi:%d,space:%d,others:%d",zimu,shuzi,space,others);
}

15、输出字符串中最长的单词

#include <stdio.h>
#include <string.h>
#define N 50

// 找到最长单词的起始位置
int longest(char s[]) {
    int i = 0;  // 用于遍历字符串的索引
    int len = 0;  // 当前单词的长度
    int maxLen = 0;  // 记录最长单词的长度
    int start = 0;  // 当前单词的起始位置
    int maxStart = 0;  // 最长单词的起始位置

    // 遍历字符串,直到遇到字符串结束符'\0'
    while (s[i] != '\0') {
        if (s[i] == ' ') {  // 如果当前字符是空格
            if (len > maxLen) {  // 检查当前单词的长度是否大于已记录的最大长度
                maxLen = len;  // 更新最大长度
                maxStart = start;  // 更新最长单词的起始位置
            }
            len = 0;  // 重置当前单词长度为0
            start = i + 1;  // 更新下一个单词的起始位置
        } else {  // 如果当前字符不是空格
            len++;  // 当前单词长度加1
        }
        i++;  // 移动到下一个字符
    }

    // 检查最后一个单词
    // 原因:在循环中,只有遇到空格时才会更新maxLen和maxStart
    // 但如果字符串的最后一个单词后面没有空格(即它是字符串的最后一个单词),则它的长度和起始位置不会在循环中被更新
    if (len > maxLen) {
        maxLen = len;  // 更新最大长度
        maxStart = start;  // 更新最长单词的起始位置
    }

    return maxStart;  // 返回最长单词的起始位置
}

int main() {
    char s[N];  // 定义一个字符数组s,用于存储用户输入的字符串

    // 提示用户输入字符串
    puts("input the string:");
    gets(s);  // 读取用户输入的字符串

    // 调用longest函数,找到最长单词的起始位置
    int maxStart = longest(s);

    // 从最长单词的起始位置开始,输出最长单词
    int i = maxStart;
    while (s[i] != '\0' && s[i] != ' ') {  // 遍历最长单词,直到遇到字符串结束符'\0'或空格
        printf("%c", s[i]);  // 输出当前字符
        i++;  // 移动到下一个字符
    }
    printf("\n");  // 输出换行符,结束输出

    return 0;  // 程序正常结束
}

16、冒泡法对输入的10个字符从小到大排序

#include <cstdio>
#include <cstring>
#define N 20

// 冒泡排序函数,对字符串中的字符进行升序排序
void bubble(char s[]) {
    int len = strlen(s);  // 获取字符串的长度
    int flag;  // 用于标记是否发生了交换
    int i, j;  // 外层循环变量i和内层循环变量j
    char temp;  // 用于交换字符的临时变量

    // 外层循环控制排序的轮数,总共需要len-1轮
    for (i = 0; i < len - 1; ++i) {
        flag = 0;  // 每轮开始时,假设字符串已经排序好
        // 内层循环控制每轮的比较和交换操作
        for (j = 0; j < len - i - 1; ++j) {
            // 如果当前字符大于下一个字符,则交换它们
            if (s[j] > s[j + 1]) {
                temp = s[j];  // 保存当前字符
                s[j] = s[j + 1];  // 将下一个字符移到当前位置
                s[j + 1] = temp;  // 将保存的字符移到下一个位置
                flag = 1;  // 发生了交换,标记为1
            }
        }
        // 如果在一轮中没有发生任何交换,说明字符串已经排序完成,可以提前退出
        if (flag == 0) {
            break;
        }
    }
}

int main() {
    char s[N];  // 定义一个字符数组s,用于存储用户输入的字符串

    // 提示用户输入字符串
    puts("input the string:");
    gets(s);  // 读取用户输入的字符串

    // 调用bubble函数,对字符串中的字符进行升序排序
    bubble(s);

    // 输出排序后的结果
    puts("result:");
    puts(s);

    return 0;  // 程序正常结束
}

17、牛顿迭代法求方程x=1附近的根,精度为10(-3)

a = 1,b=2,c=3,d=4

#include <cstdio>
#include <cmath>

float a, b, c, d;  // 定义一元三次方程的系数

// 计算一元三次方程 f(x) = ax^3 + bx^2 + cx + d
float fx(float x) {
    return a * pow(x, 3) + b * pow(x, 2) + c * x + d;
}

// 计算一元三次方程的导数 f'(x) = 3ax^2 + 2bx + c
float fxd(float x) {
    return 3 * a * pow(x, 2) + 2 * b * x + c;
}

// 使用牛顿法求解一元三次方程的根
float solut() {
    float x0 = 1;  // 初始猜测值
    float x1 = x0 - fx(x0) / fxd(x0);  // 牛顿法迭代公式

    // 迭代直到 x1 和 x0 的差值小于 1e-3
    while (abs(x1 - x0) > 1e-3) {
        x0 = x1;  // 更新 x0
        x1 = x0 - fx(x0) / fxd(x0);  // 再次使用牛顿法迭代公式
    }

    return x1;  // 返回求得的根
}

int main() {
    puts("input a,b,c,d:");  // 提示用户输入系数
    scanf("%f,%f,%f,%f", &a, &b, &c, &d);  // 读取用户输入的系数

    // 调用 solut 函数求解方程的根
    printf("x=%10.7f", solut());  // 输出求得的根,保留 7 位小数

    return 0;  // 程序正常结束
}

18、递归实现N阶勒让德多项式的值

#include <cstdio>

// 计算勒让德多项式 P_n(x)
float px(int n, float x) {
    if (n == 0) {
        return 1;  // P_0(x) = 1
    } else if (n == 1) {
        return x;  // P_1(x) = x
    } else {
        // 使用递归公式计算 P_n(x)
        // 递归公式:P_n(x) = ((2n-1)xP_{n-1}(x) - (n-1)P_{n-2}(x)) / n
        return ((2 * n - 1) * x * px(n - 1, x) - (n - 1) * px(n - 2, x)) / n;
    }
}

int main() {
    int n;
    float x;
    puts("input the 'n' and 'x':");
    // 读取用户输入的 n 和 x
    // 注意:输入格式应该是两个整数,用逗号分隔
    scanf("%d,%f", &n, &x);

    // 调用 px 函数计算 P_n(x)
    printf("p%d(%.2f) = %.6f\n", n, x, px(n, x));

    return 0;
}

19、输入10个学生的5门成绩,实现下面功能

(1)计算每个学生的平均分

(2)计算每门课的平均分

(3)计算最高分对应的学生和课程

(4)计算平均值方差

#include <cstdio>
#include <cmath>
#define M 10  // 定义学生数量
#define N 5   // 定义课程数量

float averageStudent[M];  // 每个学生的平均分
float averageCourses[N];  // 每门课程的平均分
int student = 0, course = 0;  // 最高分数对应的学生和课程
float fc = 0;  // 平均分方差

// 计算每个学生的平均分
void getAverageStudent(float scores[M][N]) {
    float sum = 0;  // 用于累加分数
    for (int i = 0; i < M; ++i) {  // 遍历每个学生
        for (int j = 0; j < N; ++j) {  // 遍历每门课程
            sum += scores[i][j];  // 累加该学生的分数
        }
        averageStudent[i] = sum / N;  // 计算该学生的平均分
        sum = 0;  // 重置sum为0,用于下一个学生的分数累加
    }
}

// 计算每门课程的平均分
void getAverageCourses(float scores[M][N]) {
    float sum = 0;  // 用于累加分数
    for (int i = 0; i < N; ++i) {  // 遍历每门课程
        for (int j = 0; j < M; ++j) {  // 遍历每个学生
            sum += scores[j][i];  // 累加该课程的分数
        }
        averageCourses[i] = sum / M;  // 计算该课程的平均分
        sum = 0;  // 重置sum为0,用于下一门课程的分数累加
    }
}

// 找出最高分数的学生和课程
void getTop(float scores[M][N]) {
    float maxScore = 0;  // 用于存储最高分数
    for (int i = 0; i < M; ++i) {  // 遍历每个学生
        for (int j = 0; j < N; ++j) {  // 遍历每门课程
            if (scores[i][j] > maxScore) {  // 如果当前分数大于最高分数
                maxScore = scores[i][j];  // 更新最高分数
                student = i;  // 更新最高分数对应的学生编号
                course = j;  // 更新最高分数对应的课程编号
            }
        }
    }
}

// 计算平均分方差
float getFc(float scores[M][N]) {
    float sumXi = 0, sumXi2 = 0, result;
    float mu = 0;  // 所有学生平均分的平均值

    // 计算所有学生平均分的平均值
    for (int i = 0; i < M; ++i) {
        sumXi += averageStudent[i];
    }
    mu = sumXi / M;

    // 计算方差
    for (int i = 0; i < M; ++i) {
        sumXi2 += pow(averageStudent[i] - mu, 2);
    }
    result = sumXi2 / M;

    return result;
}

int main() {
    float scores[M][N] = {  // 定义学生成绩数组
        {60, 90.0, 78.5, 92.0, 88.0},
        {60, 98.5, 90.0, 63.0, 80.5},
        {60, 66.5, 92.0, 85.0, 78.5},
        {60, 92.5, 85.0, 76.0, 90.0},
        {60, 85.0, 90.0, 92.5, 88.0},
        {60, 88.0, 78.5, 36.0, 85.5},
        {60, 56.0, 92.5, 88.0, 90.0},
        {60, 56.0, 85.0, 100, 92.0},
        {60, 82.0, 45.5, 90.0, 99.0},
        {60, 88.0, 77.0, 70.5, 90.0}
    };

    getAverageStudent(scores);  // 计算每个学生的平均分
    printf("averageStudent:");
    for (int i = 0; i < M; ++i) {
        printf("%4.2f\t", averageStudent[i]);
    }
    printf("\n");

    getAverageCourses(scores);  // 计算每门课程的平均分
    printf("averageCourses:");
    for (int i = 0; i < N; ++i) {
        printf("%4.2f\t", averageCourses[i]);
    }
    printf("\n");

    getTop(scores);  // 找出最高分数的学生和课程
    printf("the max student is:%d and the course is:%d\n", student, course);

    printf("the result is:%4.2f", getFc(scores));  // 输出平均分方差
}

20、写几个函数

(1)输入10个职工的姓名和员工号。

(2)职工号由小到大排序,姓名也随之改变。

(3)输出职工号,用折半查找找出姓名。

#include <cstdio>
#define N 5

typedef struct {
    int No;                // 用户编号
    char username[5];      // 用户名
} User;

// 折半插入排序
void sort(User user[N]) {
    int mid, j;            // 中间索引和循环变量
    User temp;             // 临时变量,用于存储当前待插入的元素
    for (int i = 1; i < N; ++i) {  // 从第二个元素开始,逐个插入到前面已排序的序列中
        temp = user[i];    // 将当前元素存储到临时变量中
        int low = 0;       // 设置折半查找的下界
        int high = i - 1;  // 设置折半查找的上界
        while (low <= high) {  // 当下界小于等于上界时,继续折半查找
            mid = (low + high) / 2;  // 计算中间索引
            if (user[mid].No > temp.No) {  // 如果中间元素大于待插入元素
                high = mid - 1;  // 调整上界
            } else {
                low = mid + 1;  // 调整下界
            }
        }
        for (j = i - 1; j >= low; --j) {  // 将从插入位置到当前元素之间的所有元素向后移动一位
            user[j + 1] = user[j];
        }
        user[low] = temp;  // 将待插入元素插入到正确的位置
    }
}

// 折半查找
User getUser(User user[N], int id) {
    int low = 0;           // 设置折半查找的下界
    int high = N - 1;      // 设置折半查找的上界
    int mid;               // 中间索引
    while (low <= high) {  // 当下界小于等于上界时,继续折半查找
        mid = (low + high) / 2;  // 计算中间索引
        if (id == user[mid].No) {  // 如果中间元素的编号等于目标编号
            return user[mid];  // 返回该用户
        } else if (id > user[mid].No) {  // 如果目标编号大于中间元素的编号
            low = mid + 1;  // 调整下界
        } else {
            high = mid - 1;  // 调整上界
        }
    }
    // 如果未找到目标用户,返回一个特殊的用户对象
    User notFound = {-1, "N/A"};
    return notFound;
}

int main() {
    User user[N];          // 定义一个用户数组
    int id;                // 定义一个变量,用于存储用户输入的编号
    // 输入用户信息
    for (int i = 0; i < N; ++i) {
        printf("please input the No.%d's id and username: ", i + 1);
        scanf("%d", &user[i].No);  // 输入用户编号
        scanf("%s", user[i].username);  // 输入用户名
        printf("\n");
    }

    // 输出用户信息
    for (int i = 0; i < N; ++i) {
        printf("id:%d and name:%s\n", user[i].No, user[i].username);
    }

    // 对用户数组进行排序
    sort(user);

    // 输入要查找的用户编号
    printf("input the user's id:");
    scanf("%d", &id);

    // 调用折半查找函数,查找用户
    User result = getUser(user, id);
    if (result.No == -1) {
        printf("User not found.\n");
    } else {
        printf("the id is: %d and the username is: %s\n", result.No, result.username);
    }
}

21、输入十六进制输出十进制

十六进制转十进制:

十六进制数是基于16的数制,使用数字0-9和字母A-F(或a-f)表示,其中A=10, B=11, C=12, D=13, E=14, F=15。

要将十六进制数转换为十进制数,可以使用以下公式:

十进制数=∑i=0n​(di​×16i)

其中,di​是十六进制数的第i位数字(从右向左数,最右边的位是0),n是十六进制数的位数减1。

示例: 将十六进制数1A3转换为十进制数。

1A316​=1×162+A×161+3×160 =1×256+10×16+3×1 =256+160+3 =41910​

#include <cstdio>
#include <cstring>
#include <cmath>
#define N 10  // 定义数组的最大长度

// 函数:将十六进制字符串转换为十进制数
double convert(char num[]) {
    int len = strlen(num);  // 获取字符串的长度
    double sum = 0;         // 用于存储最终的十进制结果
    // 从左到右遍历字符串
    for (int i = 0; i < len; ++i) {
        // 如果是数字字符('0'到'9')
        if (num[i] >= '0' && num[i] <= '9') {
            // 将字符转换为对应的数值,并乘以16的相应幂次
            sum += (num[i] - '0') * pow(16, len - 1 - i);
        } 
        // 如果是小写字母('a'到'f')
        else if (num[i] >= 'a' && num[i] <= 'f') {
            // 将字符转换为对应的数值,并乘以16的相应幂次
            sum += (num[i] - 'a' + 10) * pow(16, len - 1 - i);
        } 
        // 如果是大写字母('A'到'F')
        else if (num[i] >= 'A' && num[i] <= 'F') {
            // 将字符转换为对应的数值,并乘以16的相应幂次
            sum += (num[i] - 'A' + 10) * pow(16, len - 1 - i);
        }
    }
    return sum;  // 返回最终的十进制结果
}

int main(){
    char num[N];  // 定义一个字符数组用于存储输入的十六进制数
    puts("input the 16:");  // 提示用户输入十六进制数
    gets(num);  // 读取用户输入的字符串
    // 调用convert函数将十六进制数转换为十进制数,并输出结果
    printf("%s convert 10 is %3.1f(10)", num, convert(num));
}

22、递归实现将int类型的数据转为字符串😒

#include <cstdio>

// 函数:将十进制整数转换为字符串形式并逐位输出
void convert(int num){
    // 如果是负数,先输出负号,并将负数转换为正数
    if (num < 0) {
        putchar('-');  // 输出负号
        num = -num;    // 将负数转换为正数
    }
    // 如果当前数的高位不为0,递归调用 convert 函数处理更高位
    if (num / 10 != 0) {
        convert(num / 10);  // 递归调用,处理更高位
    }
    // 输出当前位
    putchar(num % 10 + '0');  // num % 10 得到当前位的数字,加上 '0' 的ASCII值将其转换为字符
}

int main(){
    int num;
    // 提示用户输入一个整数
    puts("input the num:");
    // 读取用户输入的整数
    scanf("%d", &num);
    // 调用 convert 函数进行转换并输出
    convert(num);
    // 输出换行符,确保输出格式正确
    putchar('\n');
    return 0;
}

23、输入年月日输出是该年的第几天

#include <cstdio>
#define N 7

// 判断今年是不是闰年
bool judge(int year) {
    // 如果年份能被4整除但不能被100整除,或者能被400整除,则是闰年
    return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
}

// 计算从年初到指定日期的总天数
int compute(int year, int month, int day) {
    int sum = 0; // 用于累加天数
    // 遍历从1月到指定月份的所有月份
    for (int i = 1; i <= month; ++i) {
        int j = i - 1; // 当前月份之前的完整月份
        // 如果是2月
        if (j == 2) {
            // 如果是闰年,2月有29天,否则28天
            if (judge(year)) {
                sum += 29;
            } else {
                sum += 28;
            }
        } 
        // 如果是1月、3月、5月、7月、8月、10月、12月
        else if (j == 1 || j == 3 || j == 5 || j == 7 || j == 8 || j == 10 || j == 12) {
            sum += 31; // 这些月份都有31天
        } 
        // 如果是4月、6月、9月、11月
        else if (j == 4 || j == 6 || j == 9 || j == 11) {
            sum += 30; // 这些月份都有30天
        }
    }
    // 加上指定日期的天数
    return sum + day;
}

int main() {
    int year, month, day; // 用于存储输入的年、月、日
    // 提示用户输入年份
    puts("input the year:");
    // 读取用户输入的年份
    scanf("%d", &year);
    // 提示用户输入月份
    puts("input the month:");
    // 读取用户输入的月份
    scanf("%d", &month);
    // 提示用户输入日期
    puts("input the day:");
    // 读取用户输入的日期
    scanf("%d", &day);
    // 调用compute函数计算从年初到指定日期的总天数,并输出结果
    printf("the sum is:%d", compute(year, month, day));
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/961981.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

WPF基础 | WPF 常用控件实战:Button、TextBox 等的基础应用

WPF基础 | WPF 常用控件实战&#xff1a;Button、TextBox 等的基础应用 一、前言二、Button 控件基础2.1 Button 的基本定义与显示2.2 按钮样式设置2.3 按钮大小与布局 三、Button 的交互功能3.1 点击事件处理3.2 鼠标悬停与离开效果3.3 按钮禁用与启用 四、TextBox 控件基础4.…

MATLAB的数据类型和各类数据类型转化示例

一、MATLAB的数据类型 在MATLAB中 &#xff0c;数据类型是非常重要的概念&#xff0c;因为它们决定了如何存储和操作数据。MATLAB支持数值型、字符型、字符串型、逻辑型、结构体、单元数组、数组和矩阵等多种数据类型。MATLAB 是一种动态类型语言&#xff0c;这意味着变量的数…

模型I/O

文章目录 什么是模型I/O模型I/O功能之输出解析器输出解析器的功能输出解析器的使用Pydantic JSON输出解析器结构化输出解析器 什么是模型I/O 模型I/O在所有LLM应用中&#xff0c;核心元素无疑都是模型本身。与模型进行有效的交互是实现高效、灵活和可扩展应用的关键。LangChain…

docker安装Redis:docker离线安装Redis、docker在线安装Redis、Redis镜像下载、Redis配置、Redis命令

一、镜像下载 1、在线下载 在一台能连外网的linux上执行docker镜像拉取命令 docker pull redis:7.4.0 2、离线包下载 两种方式&#xff1a; 方式一&#xff1a; -&#xff09;在一台能连外网的linux上安装docker执行第一步的命令下载镜像 -&#xff09;导出 # 导出镜像…

QT串口通信,实现单个温湿度传感器数据的采集

1、硬件设备 RS485中继器(一进二出),usb转485模块、电源等等 => 累计115元左右。 2、核心代码 #include "MainWindow.h" #include "ui_MainWindow.h"MainWindow::

android主题设置为..DarkActionBar.Bridge时自定义DatePicker选中日期颜色

安卓自定义DatePicker选中日期颜色 背景&#xff1a;解决方案&#xff1a;方案一&#xff1a;方案二&#xff1a;实践效果&#xff1a; 背景&#xff1a; 最近在尝试用原生安卓实现仿element-ui表单校验功能&#xff0c;其中的的选择日期涉及到安卓DatePicker组件的使用&#…

6.工厂模式(Factory Method)

定义 通过“对象创建” 模式绕开new&#xff0c;来避免对象创建&#xff08;new&#xff09;过程中所导致的紧耦合&#xff08;依赖具体类&#xff09;&#xff0c;从而支持对象创建的稳定。它是接口抽象之后的第一步工作。 动机 在软件系统中&#xff0c;经常面临着创建对象…

Java CAS操作

通过前面的学习认识到了CPU缓存&#xff0c;Java内存模型&#xff0c;以及线程安全的原子、可见、顺序三大特性。本文则重点认识CAS操作&#xff0c;这是Java并发编程常见的一个操作&#xff0c;AbstractQueuedSynchronizer基于此操作提供了丰富的同步器和各种锁。 CAS&#x…

【Numpy核心编程攻略:Python数据处理、分析详解与科学计算】1.25 视觉风暴:NumPy驱动数据可视化

1.25 视觉风暴&#xff1a;NumPy驱动数据可视化 目录 #mermaid-svg-i3nKPm64ZuQ9UcNI {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-i3nKPm64ZuQ9UcNI .error-icon{fill:#552222;}#mermaid-svg-i3nKPm64ZuQ9UcNI …

鸟瞰欧洲(意境欧洲) 第一季

目录 《鸟瞰欧洲 第一季》纪录片笔记一、基本信息二、详细内容&#xff08;一&#xff09;剧集设置&#xff08;二&#xff09;各国亮点1. **荷兰**2. **意大利**3. **德国**4. **英国**5. **西班牙**6. **波兰** &#xff08;三&#xff09;拍摄特色 三、特色与评价四、总结五…

【MQ】探索 Kafka

高性能 消息的顺序性、顺序写磁盘 零拷贝 RocketMQ内部主要是使用基于mmap实现的零拷贝&#xff0c;用来读写文件 减少cpu的拷贝次数和上下文切换次数&#xff0c;实现文件的高效读写操作 Kafka 零拷贝 Kafka 使用到了 mmap 和 sendfile 的方式来实现零拷贝。分别对应 Jav…

供应链系统设计-供应链中台系统设计(十一)- 清结算中心概念片篇

概述 上篇供应链系统设计-供应链中台系统设计&#xff08;十&#xff09;- 清结算中心概念片篇文中提到了什么是金融客户、资金账号、资金账户、以及资金账号和资金账户的关系&#xff0c;如下图所示&#xff1a; 这些对于清算和结算来说都是前置的概念&#xff0c;本篇文章我…

allegro修改封闭图形线宽

说在前面 我们先把最优解说在前面,然后后面再说如果当时不熟悉软件的时候为了挖孔是用了shapes该怎么修改回来。 挖空最方便的方式是在cutout层画一个圆弧,下面开始图解,先add一个圆弧 z 最好是在画的时候就选择好层,如果忘记了后续再换回去也行,但好像软件有bug,此处并…

使用scikit-learn中的KNN包实现对鸢尾花数据集的预测

引言 K最近邻&#xff08;KNN&#xff09;算法是一种简单且直观的分类算法。它通过计算数据点之间的距离来对新样本进行分类。鸢尾花数据集是一个经典的机器学习数据集&#xff0c;包含了三种不同类型的鸢尾花&#xff0c;每种类型由四个特征&#xff08;花萼长度、花萼宽度、…

Hive:静态分区(分区语法,多级分区,分区的查看修改增加删除)

hive在建表时引入了partition概念。即在建表时&#xff0c;将整个表存储在不同的子目录中&#xff0c;每一个子目录对应一个分区。在查询时&#xff0c;我们就可以指定分区查询&#xff0c;避免了hive做全表扫描&#xff0c;从而提高查询率。 oracle和Hive分区的区别 orcale在…

基于FPGA的BT656解码

概述 BT656全称为“ITU-R BT.656-4”或简称“BT656”,是一种用于数字视频传输的接口标准。它规定了数字视频信号的编码方式、传输格式以及接口电气特性。在物理层面上,BT656接口通常包含10根线(在某些应用中可能略有不同,但标准配置为10根)。这些线分别用于传输视频数据、…

随机矩阵投影长度保持引理及其证明

原论文中的引理 2 \textbf{2} 2 引理 2 \textbf{2} 2的内容​​ &#x1f449;前提 1 1 1&#xff1a;设一个随机矩阵 S ( s i j ) ∈ R t d S\text{}(s_{ij})\text{∈}\mathbb{R}^{t\text{}d} S(sij​)∈Rtd&#xff0c;每个元素 s i j s_{ij} sij​独立同分布于 N ( 0 , …

详细解释java当中的所有知识点(前言及数据类型及变量)(第一部分)

会将java当中的所有的知识点以及相关的题目进行分享&#xff0c;这是其中的第一部分&#xff0c;用红色字体标注出重点&#xff0c;以及加粗的方式进行提醒 目录 一、Java语言概述 1.Java语言简介 2.语言优势 二、main方法 1.Java程序结构组成 2.运行Java程序 3.注释 4.…

STM32 PWMI模式测频率占空比

接线图&#xff1a; PWMI基本结构 代码配置&#xff1a; 与上一章输入捕获代码一样&#xff0c;根据结构体&#xff0c;需要在输入捕获单元再配置一个通道。我们调用一个函数 这个函数可以给结构体赋值&#xff0c;当我们定义了一遍结构体参数&#xff0c;再调用这个函数&…

Fort Firewall:全方位守护网络安全

Fort Firewall是一款专为 Windows 操作系统设计的开源防火墙工具&#xff0c;旨在为用户提供全面的网络安全保护。它基于 Windows 过滤平台&#xff08;WFP&#xff09;&#xff0c;能够与系统无缝集成&#xff0c;确保高效的网络流量管理和安全防护。该软件支持实时监控网络流…