当前位置: 首页 > article >正文

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

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.kler.cn/a/530374.html

相关文章:

  • 51单片机 01 LED
  • GWO优化LSBooST回归预测matlab
  • 【自然语言处理(NLP)】基于Transformer架构的预训练语言模型:BERT 训练之数据集处理、训练代码实现
  • 【Numpy核心编程攻略:Python数据处理、分析详解与科学计算】1.27 线性代数王国:矩阵分解实战指南
  • JavaScript 入门教程
  • d3.js: Relation Graph
  • Maven全解析:从基础到精通的实战指南
  • 利用DeepSeek提炼腾讯AI研究院的图景关键词——延伸畅想
  • Resnet 改进:尝试在不同位置加入Transform模块
  • LeetCode435周赛T2贪心
  • Elixir语言的安全开发
  • GWO优化LSBooST回归预测matlab
  • Java多线程与高并发专题——生产/消费者模式
  • XML DOM 节点树
  • ROS应用之AMCL 多机器人支持
  • Python-基于PyQt5,wordcloud,pillow,numpy,os,sys等的智能词云生成器(最终版)
  • C++编程语言:抽象机制:泛型编程(Bjarne Stroustrup)
  • 汇编语言运行环境搭建及简单使用
  • 沙皮狗为什么禁养?
  • 第39天:WEB攻防-通用漏洞_CSRF_SSRF_协议玩法_内网探针_漏洞利用
  • ubuntu 下使用deepseek
  • C# 装箱和拆箱(以及 as ,is)
  • gitea - fatal: Authentication failed
  • 水质数据监控大屏,保护水资源,共筑绿水青山
  • MySQL不适合创建索引的11种情况
  • Linux mpstat 命令使用详解