谭浩强C语言程序设计(4) 8章(下)

news2025/2/4 0:45:59

1、输入三个字符串按照字母顺序从小到大输出

#include <cstdio>  // 包含cstdio头文件,用于输入输出函数
#include <cstring> // 包含cstring头文件,用于字符串处理函数

#define N 20       // 定义字符串的最大长度为20

// 函数:交换两个字符串的内容
void sort(char* strA, char* strB) {
    char temp[N];  // 定义一个临时数组,用于存储其中一个字符串的内容
    strcpy(temp, strA);  // 将strA的内容复制到临时数组temp中
    strcpy(strA, strB);  // 将strB的内容复制到strA中
    strcpy(strB, temp);  // 将临时数组temp的内容(原来的strA)复制到strB中
}

int main() {
    char str1[N], str2[N], str3[N]; // 定义三个字符串,用于存储用户输入
    puts("input the str1,str2,str3:"); // 提示用户输入三个字符串
    scanf("%s %s %s", str1, str2, str3); // 读取用户输入的三个字符串

    // 如果第一个字符串比第二个大,交换它们
    if (stricmp(str1, str2) > 0) { // 使用stricmp进行不区分大小写的比较
        sort(str1, str2);          // 调用sort函数交换str1和str2的内容
    }

    // 如果第二个字符串比第三个大,交换它们
    if (stricmp(str2, str3) > 0) {
        sort(str2, str3);          // 调用sort函数交换str2和str3的内容
    }

    // 如果第一个字符串比第三个大,交换它们
    if (stricmp(str1, str3) > 0) {
        sort(str1, str3);          // 调用sort函数交换str1和str3的内容
    }

    // 输出排序后的字符串
    printf("%s %s %s", str1, str2, str3);

    return 0; // 程序结束
}

        在C中,数组名在大多数情况下会被视为指向数组第一个元素的指针。当将数组作为参数传递给函数时,实际上传递的是数组的首地址,也就是指针的值传递。这时候函数内部的指针是原指针的一个副本,但它们指向的是同一块内存地址。

        当使用strcpy函数时,比如strcpy(strA, strB),这里的strA和strB是传入的指针,指向main函数中的数组。strcpy的作用是将strB指向的字符串内容复制到strA指向的内存空间中。因此,操作的是指针所指向的内存区域,而不是指针本身的值。这样,原数组的内容就被修改了。

        虽然指针本身是副本,但它们指向的是同一块内存地址。通过副本指针去修改内存中的数据,自然会影响原数据,因为原指针也指向同一块内存。

图解:

1、初始状态

2、strcpy(temp,strA); 

3、strcpy(strA,strB); 

4、strcpy(strB,temp);

 2、输入10个数,最小的数和第一个数交换,最大的数和最后一个数交换

#include <cstdio>

#define N 5  // 定义数组长度

// 输入函数:为数组元素赋值
void input(int* num) {
    for (int i = 0; i < N; ++i) {
        printf("input the No.%d num:", i + 1);
        scanf("%d", num + i);  // 等价于 &num[i],指针偏移方式访问数组元素
    }
}

// 获取最小值索引函数
int getMinIndex(int* num) {
    int minIndex = 0;          // 初始化为首元素索引
    int min = *num;            // 初始化为首元素值
    for (int i = 0; i < N; ++i) {
        if (min > *(num + i)) {  // 发现更小值时更新
            min = *(num + i);
            minIndex = i;
        }
    }
    return minIndex;
}

// 获取最大值索引函数
int getMaxIndex(int* num) {
    int maxIndex = 0;          // 初始化为首元素索引
    int max = *num;            // 初始化为首元素值
    for (int i = 0; i < N; ++i) {
        if (max < *(num + i)) {  // 发现更大值时更新
            max = *(num + i);
            maxIndex = i;
        }
    }
    return maxIndex;
}

/**
 * 极值交换函数(已修复原逻辑问题)
 * 执行顺序:
 * 1. 交换最小值到数组首部
 * 2. 在更新后的数组中重新获取最大值位置
 * 3. 交换最大值到数组末尾
 */
void minAndMax(int* num) {
    // 第一阶段:处理最小值交换 --------------------------
    int minIndex = getMinIndex(num);  // 获取原始最小值位置
    int temp;
    
    // 执行最小值交换操作
    temp = *num;                // 暂存原首元素值
    *num = *(num + minIndex);   // 将最小值写入首元素位置
    *(num + minIndex) = temp;   // 将原首元素值写入原最小值位置
    
    // 第二阶段:处理最大值交换 --------------------------
    /* 关键改进点:在交换最小值后重新获取最大值位置
     * 解决原版本最大值可能被意外移动的问题
     */
    int maxIndex = getMaxIndex(num);  // 获取当前数组最大值位置
    
    // 执行最大值交换操作
    temp = *(num + maxIndex);         // 暂存当前最大值
    *(num + maxIndex) = *(num + N-1); // 将末元素值写入原最大值位置
    *(num + N-1) = temp;              // 将最大值写入末元素位置
}

// 输出数组内容
void output(int* num) {
    for (int i = 0; i < N; ++i) {
        printf("%d ", num[i]);  // 使用数组下标方式访问元素
    }
}

int main() {
    int num[N];          // 声明整型数组
    input(num);          // 调用输入函数
    minAndMax(num);      // 执行极值交换
    output(num);         // 输出结果
    
    return 0;            // 程序正常退出
}

3、输入n个整数实现向后或者向前移动m个单位

#include <cstdio>
#define N 10  // 定义数组最大容量(最多存储10个元素)

/**
 * 实现数组循环右移操作
 * @param a     要操作的数组指针(会被修改)
 * @param len   数组实际使用的有效长度(必须小于等于N)
 * @param place 实际移动的位置数(经过规范化处理后的值)
 * 
 * 实现原理:
 * 1. 创建临时数组存储移动后的结果
 * 2. 通过取模运算实现循环右移
 * 3. 将结果复制回原数组
 */
void move(int* a, int len, int place) {
    int temp[len];  // 创建临时数组用于存储移动后的元素

    // 核心循环:将每个元素移动到新位置
    for (int i = 0; i < len; ++i) {
        // 计算新下标公式:(原下标+移动位数)%数组长度
        // 当计算结果超过数组长度时,自动从数组开头继续计算
        temp[(i + place) % len] = a[i]; // 例:len=5,place=7时等同于place=2
    }

    // 将排序结果写回原数组
    for (int i = 0; i < len; ++i) {
        a[i] = temp[i];  // 逐个元素复制回原数组
    }
}

/**
 * 输出数组元素
 * @param a   要输出的数组指针
 * @param len 数组实际有效长度
 * 
 * 输出格式:元素间用空格分隔,最后换行
 */
void output(int* a, int len) {
    for (int i = 0; i < len; ++i) {
        printf("%d ", a[i]);  // 遍历输出每个元素
    }
    printf("\n");  // 输出完成后换行
}

int main() {
    int a[N];       // 存储数据的数组(物理容量为10)
    int len = 0;    // 用户实际使用的元素个数
    int place = 0;  // 原始输入的移动位数

    // 第一阶段:获取用户输入
    puts("how many number?");
    scanf("%d", &len);  // 注意:此处未校验len>10的情况

    printf("input the %d numbers:", len);
    for (int i = 0; i < len; ++i) {
        scanf("%d", &a[i]);  // 连续读取指定数量的整数
    }

    // 第二阶段:获取并处理移动位数
    printf("how many place do you want move?");
    scanf("%d", &place);

    // 关键处理:位移规范化(支持负数和超长位移)
    // 1. place % len 处理过大位移(如place=15,len=10→5)
    // 2. +len 保证结果非负(处理负数位移)
    // 3. 再次%len 确保最终值在[0,len-1]范围内
    place = (place % len + len) % len;  // 示例:place=-3,len=5→2

    // 第三阶段:执行移动并输出结果
    move(a, len, place);
    output(a, len);

    return 0;  // 正常退出程序
}

 4、N个人围成一圈按照顺序排号。从第一个开始报数(1到3)凡是报号为3的出圈,最后剩下的那个是刚开始的几号?(约瑟夫环问题)😒

#include <cstdio> // 包含标准输入输出库
#define N 10      // 定义数组的最大容量为10

int main() {
    int arr[N];                       // 定义一个大小为N的数组,用于标记每个人的状态(1表示在场,0表示出局)
    int totalPeople = 0;              // 总人数
    int current = 0;                  // 当前的位置指针(从0开始)
    int count = 0;                    // 报数计数器(记录当前数到第几个人)

    printf("How many people? ");      // 提示用户输入总人数
    scanf("%d", &totalPeople);        // 读取用户输入的总人数

    int remaining = totalPeople;      // 剩余人数,初始值等于总人数
    for (int i = 0; i < totalPeople; ++i) {
        arr[i] = 1;                   // 初始化数组,所有人的状态设置为1(在场)
    }

    // 模拟报数过程,直到只剩1人
    while (remaining > 1) {
        if (arr[current] == 1) {      // 如果当前位置的人在场
            count++;                  // 报数加1
            if (count == 3) {         // 如果报数到3
                arr[current] = 0;     // 将当前位置的人标记为出局
                remaining--;          // 剩余人数减1
                count = 0;            // 重置报数计数器
                printf("%d out ", current); // 输出出局的人的编号
            }
        }
        current = (current + 1) % totalPeople; // 移动到下一个位置(环形移动)
    }

    printf("\n");                     // 换行
    for (int i = 0; i < totalPeople; ++i) {
        if (arr[i] == 1) {            // 查找最后剩下的那个人
            printf("The last survivor is %d\n", i + 1); // 输出最后剩下的人的编号(加1是为了将索引转换为实际编号)
        }
    }

    return 0;                         // 程序结束
}

 5、求字符串长度

#include <cstdio>
#define N 20

int getLength(char* p){
    int i = 0,length = 0;
    while(p[i] != '\0' && i < N){
        length++;
        i++;
    }
    return length;
}

int main(){
    char str[N];
    printf("input the string:");
    scanf("%s",str);
    printf("the length of string is:%d", getLength(str));
}

6、将包含N个字符的字符串从第M个位置开始复制到另一个字符数组,并输出

#include <cstdio> // 包含标准输入输出库
#define N 20      // 定义数组的最大容量为20

// 复制字符串的部分功能
void copy(char* p1, char* p2, int start) {
    int i = start - 1; // 从用户指定的起始位置开始(注意:数组索引从0开始,所以需要减1)
    int j = 0;         // 目标字符串的索引

    // 从起始位置开始复制,直到遇到字符串结束符'\0'或超出数组范围
    while (p1[i] != '\0' && i < N) {
        p2[j++] = p1[i++]; // 将源字符串p1的字符复制到目标字符串p2中
    }
    p2[j] = '\0'; // 在目标字符串末尾添加字符串结束符'\0'
}

int main() {
    char str1[N]; // 定义第一个字符串数组,用于存储用户输入的源字符串
    char str2[N]; // 定义第二个字符串数组,用于存储复制后的结果字符串
    int start = 0; // 用户指定的起始位置

    // 提示用户输入源字符串
    printf("input the str1: ");
    scanf("%s", str1); // 读取用户输入的源字符串

    // 提示用户输入起始位置
    printf("input the start: ");
    scanf("%d", &start); // 读取用户输入的起始位置

    // 调用复制函数,从起始位置开始复制字符串
    copy(str1, str2, start);

    // 输出目标字符串(复制后的结果)
    printf("%s", str2);

    return 0; // 程序结束
}

 7、输入5x5矩阵,最大的元素放在中心,四个角上是最小的元素,大小顺序是从左到右,从上到下放😒

#include <cstdio>
#define N 5  // 定义矩阵的大小为5x5

// 函数作用:处理矩阵,把最大值放到中心,四个角放最小值
void change(int (*point)[N]) {
    int a[4];  // 用于存储四个最小值
    int b[4];  // 用于存储四个角的原始值

    // 1. 找到最大的元素并放到中心位置
    int max = point[0][0];  // 假设第一个元素是最大值
    for (int i = 0; i < N; ++i) {
        for (int j = 0; j < N; ++j) {
            if (point[i][j] > max) {  // 如果当前矩阵的值比假设的最大值更大
                max = point[i][j];    // 更新最大值
            }
        }
    }
    point[2][2] = max;  // 将最大值放置到矩阵中心(即坐标 [2][2])

    // 2. 保存四个角的原始值
    b[0] = point[0][0];  // 左上角
    b[1] = point[0][4];  // 右上角
    b[2] = point[4][0];  // 左下角
    b[3] = point[4][4];  // 右下角

    // 3. 找到四个最小值,并将它们替换到四个角的位置
    for (int k = 0; k < 4; ++k) {  // 多次循环找到四个最小值
        int min_val = 1000000;  // 假设矩阵值不会超过这个数值
        int row = -1, col = -1; // 记录最小值的位置

        // 遍历矩阵,找到当前最小值
        for (int i = 0; i < N; ++i) {
            for (int j = 0; j < N; ++j) {
                if (point[i][j] < min_val) {  // 如果当前值比假设的最小值更小
                    min_val = point[i][j];    // 更新最小值
                    row = i;                 // 记录最小值的行号
                    col = j;                 // 记录最小值的列号
                }
            }
        }
        a[k] = min_val;  // 保存当前最小值
        point[row][col] = b[k];  // 将最小值的位置替换为原始角的值
    }

    // 4. 将四个最小值放置到四个角
    point[0][0] = a[0];  // 左上角
    point[0][4] = a[1];  // 右上角
    point[4][0] = a[2];  // 左下角
    point[4][4] = a[3];  // 右下角
}

int main() {
    int arr[N][N];  // 定义一个5x5的整数矩阵

    // 输入矩阵
    printf("Enter the 5x5 matrix:\n");
    for (int i = 0; i < N; ++i) {
        printf("Enter row %d (numbers separated by spaces):\n", i + 1);
        for (int j = 0; j < N; ++j) {
            scanf("%d", &arr[i][j]);  // 读取每一行的数值
        }
    }

    // 打印原始矩阵
    printf("\nThe original matrix is:\n");
    for (int i = 0; i < N; ++i) {
        for (int j = 0; j < N; ++j) {
            printf("%d ", arr[i][j]);  // 打印每一行的数值
        }
        printf("\n");
    }

    // 调用函数处理矩阵
    change(arr);  // 调用change函数,处理矩阵

    // 打印修改后的矩阵
    printf("\nThe modified matrix is:\n");
    for (int i = 0; i < N; ++i) {
        for (int j = 0; j < N; ++j) {
            printf("%d ", arr[i][j]);  // 打印处理后的矩阵
        }
        printf("\n");
    }

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

书上写的有点难懂哦,呜呜呜。

8、输入十个等长的字符串,对字符串排序并输出排序好的字符串

#include <cstdio>
#include <cstring>
#define N 3
#define M 6

// 折半插入排序
void sort(char (*p)[M]) {
    int high, low, mid;
    char temp[M];  // 使用临时数组保存当前待插入的字符串
    for (int i = 1; i < N; ++i) {
        high = i - 1;
        low = 0;
        strcpy(temp, p[i]);  // 将当前字符串复制到临时数组
        while (low <= high) {
            mid = (low + high) / 2;
            if (stricmp(p[mid], temp) > 0) {
                high = mid - 1;
            } else {
                low = mid + 1;
            }
        }
        // 将 [low, i-1] 区间的字符串后移一位
        for (int j = i - 1; j >= low; j--) {
            strcpy(p[j + 1], p[j]);  // 复制字符串内容
        }
        strcpy(p[low], temp);  // 将临时字符串插入到正确位置
    }
}

int main() {
    char str[N][M], (*point)[M];
    for (int i = 0; i < N; ++i) {
        printf("Enter string %d (max length %d): ", i + 1, M - 1);
        scanf("%s", str[i]);  // 输入字符串
    }

    printf("\nUnsorted array of strings:\n");
    for (int i = 0; i < N; ++i) {
        printf("%s\n", str[i]);  // 输出未排序的数组
    }

    point = str;
    sort(point);  // 调用排序函数

    printf("\nSorted array of strings:\n");
    for (int i = 0; i < N; ++i) {
        printf("%s\n", str[i]);  // 输出排序后的数组
    }

    return 0;
}

在代码中,strcpy(p[j + 1], p[j]); 的作用是将字符串 p[j] 复制到 p[j + 1]。这是因为数组中的元素是字符数组(即字符串),而直接赋值 p[j + 1] = p[j] 是不允许的,因为数组名是常量指针,不能直接被赋值。

9、矩阵法求如下定积分

\int_{0}^{1}sinxdx         

\int_{-1}^{1}cosxdx

\int_{0}^{2}e^{x}dx

10、一个班4个学生5门课程,实现下面的函数

(1)求第一门课程的平均分

(2)算出两门课不及格的学生的总分和平均分

(3)输出全部成绩在85以上的学生或者是平均分在90以上的学生

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

// 定义学生数量(N)、课程数量(M)和课程名称的最大长度(L)
#define N 4  // 学生数量
#define M 5  // 课程数量
#define L 20 // 课程名称最大长度

// 计算第一门课程的平均分
float getNo1ScoreAverage(float (*point)[M]) {
    float sum = 0; // 用于存储第一门课程的总成绩
    // 遍历所有学生,累加第一门课程的成绩
    for (int i = 0; i < N; ++i) {
        sum += *(*(point + i)); // point是一个指向二维数组的指针,*(*(point+i))相当于访问第i个学生的第1门课程的成绩
    }
    return sum / N; // 返回第一门课程的平均分
}

// 找出至少有两门课程不及格的学生
void getTwoFail(float (*point)[M]) {
    int count = 0; // 不及格课程的数量
    float score = 0; // 单门课程成绩
    float arr[M];  // 用于存储学生的成绩
    float sum = 0; // 总成绩
    float average = 0;  // 平均分
    bool flag = true;  // 标记是否找到不合格学生

    // 遍历所有学生
    for (int i = 0; i < N; ++i) {
        count = 0; // 重置不及格课程计数
        // 遍历每个学生的课程成绩
        for (int j = 0; j < M; ++j) {
            score = *(*(point + i) + j); // 获取当前课程成绩
            arr[j] = score; // 将成绩存入数组
            if (score < 60) { // 如果成绩低于60分,表示不及格
                count++; // 不及格课程计数加1
            }
        }
        // 如果不及格课程数量大于等于2
        if (count >= 2) {
            flag = !flag; // 设置标记为找到不合格学生
            // 输出该学生的编号和所有成绩信息
            printf("The fail student is No.%d\n", i + 1);
            sum = 0; // 重置总成绩
            // 计算总成绩和平均分
            for (int k = 0; k < M; ++k) {
                sum += arr[k];
            }
            average = sum / M;
            printf("His score is :%3.2f and average is:%3.2f\n", sum, average);
        }
    }
    // 如果没有找到不合格学生
    if (flag) {
        printf("No fail student!!!\n");
    }
}

// 找出平均分在90分以上或者每门成绩都在85分以上的学生
void getGood(float (*point)[M]) {
    float score = 0; // 单门课程成绩
    int count = 0; // 单门成绩在85以上的课程数
    float sum = 0; // 总成绩
    float average = 0;  // 平均分

    // 遍历所有学生
    for (int i = 0; i < N; ++i) {
        count = 0; // 重置课程计数
        sum = 0; // 重置总成绩
        // 遍历每个学生的课程成绩
        for (int j = 0; j < M; ++j) {
            score = *(*(point + i) + j); // 获取当前课程成绩
            if (score > 85) { // 如果成绩超过85分
                count++; // 计数加1
            }
            sum += score; // 累加总成绩
        }
        // 如果每门成绩都超过85分
        if (count == M) {
            printf("No.%d student's score all above 85\n!", i + 1);
        }
        average = sum / M; // 计算平均分
        // 如果平均分超过90分
        if (average > 90) {
            printf("No.%d student's average above 90!\n", i + 1);
        }
    }
}

int main() {
    float scores[N][M], (*p)[M]; // 定义学生成绩的二维数组和指向它的指针
    // 输入学生成绩
    for (int i = 0; i < N; ++i) {
        printf("input the No.%d's student's scores:\n", i + 1); // 提示输入第i个学生的成绩
        for (int j = 0; j < M; ++j) {
            printf("input the score %d:", j + 1); // 提示输入第j门课程的成绩
            scanf("%f", &scores[i][j]); // 输入成绩并存入数组
        }
    }

    p = scores; // 指针p指向学生成绩数组

    printf("\n");
    // 输出第一门课程的平均分
    printf("The score 1's average is:%3.2f\n", getNo1ScoreAverage(p));
    // 查找并输出至少有两门课程不及格的学生信息
    getTwoFail(p);
    // 查找并输出平均分在90分以上或者每门成绩都在85分以上的学生信息
    getGood(p);

    return 0; // 程序结束
}

11、输入一堆字符串,有数字和非数字,将连续的数字视为一个整数并存放到数组,输出数组的元素

例如A123x456 1760? 302TAB5876

输出123 456 1760 302 5876这几个整数

#include <cstdio>
#include <cstring>
#include <cstdlib> // 包含 atoi 函数

#define N 30 // 定义字符串和数组的最大长度

/**
 * @brief 将字符数组转换为整数
 * @param temp 存储数字字符的数组(必须以'\0'结尾)
 * @return 转换后的整数值
 * @note 使用 atoi 实现转换,但需注意:
 *       - 若 temp 包含非数字字符,atoi 会截断前面的数字部分(如 "123a" 转成 123)
 *       - 若数值超出 int 范围,行为未定义
 */
int convert(char temp[N]) {
    return atoi(temp); // 标准库函数,ASCII to integer
}

/**
 * @brief 从字符串中提取连续数字并存入整数数组
 * @param str 输入的原始字符串
 * @param arr 用于存储提取结果的整数数组
 * @param strLen 输入字符串的长度
 * @param validCount 引用参数,用于返回实际提取的数字个数
 * @note 逻辑说明:
 *       1. 遍历字符串每个字符
 *       2. 当发现数字字符时,开始收集连续数字
 *       3. 将连续数字字符存入临时数组 temp
 *       4. 调用 convert 转换为整数并存入结果数组
 */
void getData(char str[], int arr[], int strLen, int &validCount) {
    char temp[N];  // 临时存储数字字符的缓冲区
    int tempIndex = 0; // temp 数组的当前索引
    int arrIndex = 0;  // arr 数组的当前索引

    for (int i = 0; i < strLen; ++i) {
        // 发现数字字符时开始收集
        if (str[i] >= '0' && str[i] <= '9') {
            tempIndex = 0; // 重置临时数组索引

            // 收集连续数字字符(注意:未处理负数符号)
            while (i < strLen && (str[i] >= '0' && str[i] <= '9')) {
                // 潜在问题:若连续数字超过 N-1 个会导致缓冲区溢出
                // 建议添加:&& tempIndex < N-1
                temp[tempIndex++] = str[i++];
            }
            temp[tempIndex] = '\0'; // 添加字符串结束符

            // 转换并存储结果
            arr[arrIndex++] = convert(temp);
            validCount++; // 更新有效数字计数

            i--; // 回退一个字符,因为外层循环会执行 i++
        }
    }
}

int main() {
    char str[N];     // 输入字符串缓冲区
    int arr[N];      // 存储提取结果的数组
    int validCount = 0; // 实际提取的有效数字个数

    // 输入处理
    puts("input the string:");
    gets(str); // 警告:存在缓冲区溢出风险!建议改用 fgets(str, N, stdin)

    // 计算有效长度(去除可能的换行符)
    int len = strlen(str);
    printf("Length: %d\n", len);

    // 执行核心提取逻辑
    getData(str, arr, len, validCount);

    // 输出结果(仅打印有效数据)
    printf("Extracted numbers: ");
    for (int i = 0; i < validCount; ++i) {
        printf("%d ", arr[i]);
    }

    return 0;
}

`atoi`是C标准库中的一个函数,用于将字符串转换为整数。用户可能在代码中看到它被用来处理从字符串中提取的数字部分,比如将"123"转换为123。但是字符数组的结尾必须是‘\0’

12、编写函数实现两个字符串的比较

#include <cstdio>  // 包含标准输入输出库的头文件

#define N 10       // 定义宏 N,表示字符串的最大长度为 10

// 定义一个函数 compare,用于比较两个字符串
int compare(char str1[], char str2[]) {
    int result = 0;                     // 初始化比较结果为 0
    for (int i = 0; i < N && (str1[i] != '\0' && str2[i] != '\0'); ++i) {
        // 遍历字符串,直到遇到字符 '\0' 或超过 N 的长度
        if (str1[i] != str2[i]) {       // 如果当前字符不相等
            result = str1[i] - str2[i]; // 计算ASCII码的差值,并赋值给 result
            break;                      // 找到第一个不相等的字符后,跳出循环
        }
    }
    return result;  // 返回比较结果
}

int main() {
    char str1[N], str2[N];  // 定义两个字符数组 str1 和 str2,用于存储用户输入的字符串
    puts("input the str1:");  // 提示用户输入第一个字符串
    gets(str1);               // 读取用户输入的字符串,存储到 str1 中
    puts("input the str2:");  // 提示用户输入第二个字符串
    gets(str2);               // 读取用户输入的字符串,存储到 str2 中

    int result = compare(str1, str2);  // 调用 compare 函数,比较两个字符串
    printf("result:%d", result);       // 输出比较结果

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

13、指针数组实现输入月号,输出英文月号

#include <cstdio>

int main() {
    // 定义一个字符串数组,存储12个月的英文名称
    const char* months[] = {
            "January",  // 1月
            "February", // 2月
            "March",    // 3月
            "April",    // 4月
            "May",      // 5月
            "June",     // 6月
            "July",     // 7月
            "August",   // 8月
            "September",// 9月
            "October",  // 10月
            "November", // 11月
            "December"  // 12月
    };

    puts("input the month:");
    int month;
    scanf("%d", &month);

    // 检查输入是否在有效范围内
    if (month >= 1 && month <= 12) {
        printf("%s\n", months[month - 1]);  // 使用 month - 1 调整索引
    } else {
        printf("Invalid month number. Please enter a number between 1 and 12.\n");
    }

    return 0;
}

15、使用双重指针实现对5个字符串排序输出

#include <cstdio>   // 输入输出函数
#include <cstdlib>  // 动态内存管理函数
#include <cstring>  // 字符串操作函数

#define N 5         // 要处理的字符串数量
#define max 10      // 每个字符串的最大长度(包含空终止符)

// 折半插入排序函数,对字符串指针数组进行不区分大小写排序
void sort(char** str) {
    int low, mid, high; // 二分查找的区间指针
    char* temp;         // 临时保存当前待插入字符串指针
    
    // 从第二个元素开始逐个插入到前面已排序序列
    for (int i = 0; i < N; ++i) {
        low = 0;        // 初始化查找区间起始位置
        high = i - 1;   // 初始化查找区间结束位置
        temp = str[i];  // 保存当前待插入的字符串指针

        // 二分查找插入位置(升序排列)
        while (low <= high) {
            mid = (low + high) / 2;
            // 使用不区分大小写的比较(注意:stricmp是Windows特有,Linux可用strcasecmp)
            if (stricmp(str[mid], temp) > 0) {
                high = mid - 1; // 中间值更大,调整上限
            } else {
                low = mid + 1;  // 中间值更小,调整下限
            }
        }

        // 将插入位置后的元素后移(移动指针而不是复制字符串内容)
        for (int j = i - 1; j >= low; j--) {
            str[j + 1] = str[j]; // 直接移动指针位置
        }

        // 将当前元素插入到正确位置
        str[low] = temp;
    }
}

int main() {
    char* str[N]; // 字符串指针数组

    // 输入处理:为每个字符串动态分配内存
    for (int i = 0; i < N; ++i) {
        printf("input the string %d:", i + 1);
        str[i] = (char*)malloc(max * sizeof(char)); // 分配max字节内存
        scanf("%s", str[i]); // 注意:实际最多读取max-1个字符,需用户保证输入合规
    }

    // 调用排序函数对指针数组进行排序
    sort(str);

    // 输出排序结果
    puts("\nthe result:");
    for (int i = 0; i < N; ++i) {
        printf("%s ", str[i]);
    }

    // 改进建议:应在此处添加内存释放
    // for (int i = 0; i < N; ++i) {
    //     free(str[i]);
    // }
    
    return 0;
}

16、双重指针对输入的数字排序

#include <cstdio> // 包含标准输入输出库
#define N 5 // 定义数组的大小,这里为5

// 折半插入排序函数,参数为指向指针的指针
void sort(int** pInt) {
    int low, mid, high; // 定义二分查找所需的变量
    int* temp; // 用于临时存储当前元素

    // 从第二个元素开始进行排序
    for (int i = 1; i < N; ++i) {
        low = 0; // 初始化二分查找的下边界
        high = i - 1; // 初始化二分查找的上边界
        temp = *(pInt + i); // 当前要插入的元素

        // 使用二分查找确定当前元素的插入位置
        while (low <= high) {
            mid = (low + high) / 2; // 计算中间位置
            if (*pInt[mid] > *temp) { // 如果中间位置的元素大于当前元素
                high = mid - 1; // 调整上边界
            } else {
                low = mid + 1; // 调整下边界
            }
        }

        // 将插入位置之后的元素后移一位,为当前元素腾出空间
        for (int j = i - 1; j >= low; --j) {
            pInt[j + 1] = pInt[j];
        }

        // 将当前元素插入到正确的位置
        pInt[low] = temp;
    }
}

int main() {
    int arr[N]; // 定义一个存储输入数字的数组
    int* point[N]; // 指向数组元素的指针数组
    int** pInt; // 指向指针数组的指针

    // 读取用户输入的数字
    for (int i = 0; i < N; ++i) {
        printf("input the num%d:", i + 1); // 提示用户输入第i个数字
        scanf("%d", &arr[i]); // 读取用户输入的数字
        point[i] = &arr[i]; // 将指针数组的第i个元素指向数组的第i个元素
    }

    pInt = point; // 使 pInt 指向指针数组

    // 调用排序函数对指针数组进行排序
    sort(pInt);

    // 输出排序后的结果
    printf("Sorted array: ");
    for (int i = 0; i < N; ++i) {
        printf("%d ", *pInt[i]); // 通过指针数组访问并输出排序后的数字
    }

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

1. int arr[N];

  • 作用:声明了一个名为 arr 的整数数组。

  • 细节

    • N 是一个宏定义的常量,表示数组的大小(例如 #define N 5)。

    • 数组 arr 用于存储 N 个整数,可以通过下标访问和修改数组中的元素,例如 arr[0] 表示数组的第一个元素。

    • 数组的大小在编译时确定,因此 N 必须是一个常量。

2. int* point[N];

  • 作用:声明了一个指针数组 point

  • 细节

    • 指针数组是一个数组,其每个元素都是一个指向整数的指针(int*)。

    • 例如,point[0] 是一个指针,可以指向一个整数变量。

    • N 表示指针数组的大小,即指针数组中有 N 个指针。

    • 通常用于通过指针间接操作数组的元素,或者动态地管理内存

3. int** pInt;

  • 作用:声明了一个指向指针的指针 pInt

  • 细节

    • pInt 是一个指针,但它指向的不是一个普通的整数,而是指向一个指向整数的指针(即 int*)。

    • 简单来说,pInt 可以理解为一个“指针的指针”。

    • 通常用于指针数组的间接访问,或者动态二维数组的操作。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

使用朴素贝叶斯对散点数据进行分类

本文将通过一个具体的例子&#xff0c;展示如何使用 Python 和 scikit-learn 库中的 GaussianNB 模型&#xff0c;对二维散点数据进行分类&#xff0c;并可视化分类结果。 1. 数据准备 假设我们有两个类别的二维散点数据&#xff0c;每个类别包含若干个点。我们将这些点分别存…

【Pytorch和Keras】使用transformer库进行图像分类

目录 一、环境准备二、基于Pytorch的预训练模型1、准备数据集2、加载预训练模型3、 使用pytorch进行模型构建 三、基于keras的预训练模型四、模型测试五、参考 现在大多数的模型都会上传到huggface平台进行统一的管理&#xff0c;transformer库能关联到huggface中对应的模型&am…

Python 深拷贝与浅拷贝:数据复制的奥秘及回溯算法中的应用

引言 在 Python 编程领域&#xff0c;数据复制是极为常见的操作。而深拷贝和浅拷贝这两个概念&#xff0c;如同紧密关联却又各具特色的双子星&#xff0c;在数据处理过程中扮演着重要角色。深入理解它们&#xff0c;不仅有助于编写出高效、准确的代码&#xff0c;还能避免许多…

简单易懂的倒排索引详解

文章目录 简单易懂的倒排索引详解一、引言 简单易懂的倒排索引详解二、倒排索引的基本结构三、倒排索引的构建过程四、使用示例1、Mapper函数2、Reducer函数 五、总结 简单易懂的倒排索引详解 一、引言 倒排索引是一种广泛应用于搜索引擎和大数据处理中的数据结构&#xff0c;…

初级数据结构:栈和队列

目录 一、栈 (一)、栈的定义 (二)、栈的功能 (三)、栈的实现 1.栈的初始化 2.动态扩容 3.压栈操作 4.出栈操作 5.获取栈顶元素 6.获取栈顶元素的有效个数 7.检查栈是否为空 8.栈的销毁 9.完整代码 二、队列 (一)、队列的定义 (二)、队列的功能 (三&#xff09…

阿里云 - RocketMQ入门

前言 云消息队列 RocketMQ 版产品具备异步通信的优势&#xff0c;主要应用于【异步解耦】、【流量削峰填谷】等场景对于同步链路&#xff0c;需要实时返回调用结果的场景&#xff0c;建议使用RPC调用方案阿里云官网地址RocketMQ官网地址 模型概述 生产者生产消息并发送至服务…

Agentic Automation:基于Agent的企业认知架构重构与数字化转型跃迁---我的AI经典战例

文章目录 Agent代理Agent组成 我在企业实战AI Agent企业痛点我构建的AI Agent App 项目开源 & 安装包下载 大家好&#xff0c;我是工程师令狐&#xff0c;今天想给大家讲解一下AI智能体&#xff0c;以及企业与AI智能体的结合&#xff0c;文章中我会列举自己在企业中Agent实…

列表标签(无序列表、有序列表)

无序列表 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Document</title> </head><…

每天学点小知识之设计模式的艺术-策略模式

行为型模式的名称、定义、学习难度和使用频率如下表所示&#xff1a; 1.如何理解模板方法模式 模板方法模式是结构最简单的行为型设计模式&#xff0c;在其结构中只存在父类与子类之间的继承关系。通过使用模板方法模式&#xff0c;可以将一些复杂流程的实现步骤封装在一系列基…

AI开发学习之——PyTorch框架

PyTorch 简介 PyTorch &#xff08;Python torch&#xff09;是由 Facebook AI 研究团队开发的开源机器学习库&#xff0c;广泛应用于深度学习研究和生产。它以动态计算图和易用性著称&#xff0c;支持 GPU 加速计算&#xff0c;并提供丰富的工具和模块。 PyTorch的主要特点 …

SAP HCM insufficient authorization, no.skipped personnel 总结归纳

导读 权限:HCM模块中有普通权限和结构化权限。普通权限就是PFCG的权限&#xff0c;结构化权限就是按照部门ID授权&#xff0c;颗粒度更细&#xff0c;对分工明细化的单位尤其重要&#xff0c;今天遇到的问题就是结构化权限的问题。 作者&#xff1a;vivi&#xff0c;来源&…

机器学习算法在网络安全中的实践

机器学习算法在网络安全中的实践 本文将深入探讨机器学习算法在网络安全领域的应用实践&#xff0c;包括基本概念、常见算法及其应用案例&#xff0c;从而帮助程序员更好地理解和应用这一领域的技术。"> 序言 网络安全一直是信息技术领域的重要议题&#xff0c;随着互联…

java-抽象类注意点

ChinesePerson 类 public class ChinesePerson extends Person{public ChinesePerson(){}public ChinesePerson(String name, int age){super(name, age);}Overridepublic void greet() {System.out.println("你好&#xff0c;我的名字叫" this.getName());} }Engl…

问deepseek,如何看待ai降低学习成本而导致软件开发岗位需求降低,和工资下降。 软件从业人员何去何从?

它给我的回答是这样的&#xff1a; 思考逻辑 嗯&#xff0c;用户问的是AI如何降低学习成本&#xff0c;进而导致软件开发岗位需求减少和工资下降&#xff0c;以及软件从业人员该怎么办。这个问题挺复杂的&#xff0c;我得先理清楚各个部分。首先&#xff0c;AI确实在改变很多行…

Jason配置环境变量

jason官网 https://jason-lang.github.io/ https://github.com/jason-lang/jason/releases 步骤 安装 Java 21 或更高版本 安装 Visual Studio Code 根据操作系统&#xff0c;请按照以下具体步骤操作 视窗 下载 Jason 的最新版本&#xff0c;选择“jason-bin-3.3.0.zip”…

word2vec 实战应用介绍

Word2Vec 是一种由 Google 在 2013 年推出的重要词嵌入模型,通过将单词映射为低维向量,实现了对自然语言处理任务的高效支持。其核心思想是利用深度学习技术,通过训练大量文本数据,将单词表示为稠密的向量形式,从而捕捉单词之间的语义和语法关系。以下是关于 Word2Vec 实战…

AI技术在SEO关键词优化中的应用策略与前景展望

内容概要 在数字营销的快速发展中&#xff0c;AI技术逐渐成为SEO领域的核心驱动力。其通过强大的数据分析和处理能力&#xff0c;不仅改变了我们优化关键词的方式&#xff0c;也提升了搜索引擎优化的效率和效果。在传统SEO中&#xff0c;关键词的选择与组合常依赖人工经验和直…

c/c++高级编程

1.避免变量冗余初始化 结构体初始化为0&#xff0c;等价于对该内存进行一次memset&#xff0c;对于较大的结构体或者热点函数&#xff0c;重复的赋值带来冗余的性能开销。现代编译器对此类冗余初始化代码具有一定的优化能力&#xff0c;因此&#xff0c;打开相关的编译选项的优…

【网络】传输层协议TCP(重点)

文章目录 1. TCP协议段格式2. 详解TCP2.1 4位首部长度2.2 32位序号与32位确认序号&#xff08;确认应答机制&#xff09;2.3 超时重传机制2.4 连接管理机制(3次握手、4次挥手 3个标志位)2.5 16位窗口大小&#xff08;流量控制&#xff09;2.6 滑动窗口2.7 3个标志位 16位紧急…

HarmonyOS:ArkWeb进程

ArkWeb是多进程模型,分为应用进程、Web渲染进程、Web GPU进程、Web孵化进程和Foundation进程。 说明 Web内核没有明确的内存大小申请约束,理论上可以无限大,直到被资源管理释放。 ArkWeb进程模型图 应用进程中Web相关线程(应用唯一) 应用进程为主进程。包含网络线程、Vi…