谭浩强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 // 定义数组的最大容量为10int 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++; // 报数加1if (count == 3) { // 如果报数到3arr[current] = 0; // 将当前位置的人标记为出局remaining--; // 剩余人数减1count = 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 20int 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、矩阵法求如下定积分
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}}// 如果不及格课程数量大于等于2if (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-1temp[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; // 初始化比较结果为 0for (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码的差值,并赋值给 resultbreak; // 找到第一个不相等的字符后,跳出循环}}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可以理解为一个“指针的指针”。通常用于指针数组的间接访问,或者动态二维数组的操作。
相关文章:
谭浩强C语言程序设计(4) 8章(下)
1、输入三个字符串按照字母顺序从小到大输出 #include <cstdio> // 包含cstdio头文件,用于输入输出函数 #include <cstring> // 包含cstring头文件,用于字符串处理函数#define N 20 // 定义字符串的最大长度为20// 函数:…...
使用朴素贝叶斯对散点数据进行分类
本文将通过一个具体的例子,展示如何使用 Python 和 scikit-learn 库中的 GaussianNB 模型,对二维散点数据进行分类,并可视化分类结果。 1. 数据准备 假设我们有两个类别的二维散点数据,每个类别包含若干个点。我们将这些点分别存…...
【Pytorch和Keras】使用transformer库进行图像分类
目录 一、环境准备二、基于Pytorch的预训练模型1、准备数据集2、加载预训练模型3、 使用pytorch进行模型构建 三、基于keras的预训练模型四、模型测试五、参考 现在大多数的模型都会上传到huggface平台进行统一的管理,transformer库能关联到huggface中对应的模型&am…...
Python 深拷贝与浅拷贝:数据复制的奥秘及回溯算法中的应用
引言 在 Python 编程领域,数据复制是极为常见的操作。而深拷贝和浅拷贝这两个概念,如同紧密关联却又各具特色的双子星,在数据处理过程中扮演着重要角色。深入理解它们,不仅有助于编写出高效、准确的代码,还能避免许多…...
Node.js 和 npm 安装教程
Node.js 和 npm 安装教程 Node.js 和 npm 安装教程什么是 Node.js 和 npm?Node.jsnpm 安装前的注意事项在 Windows 上安装 Node.js 和 npm步骤 1:访问 Node.js 官网步骤 2:选择适合的版本步骤 3:下载安装包步骤 4:运行…...
简单易懂的倒排索引详解
文章目录 简单易懂的倒排索引详解一、引言 简单易懂的倒排索引详解二、倒排索引的基本结构三、倒排索引的构建过程四、使用示例1、Mapper函数2、Reducer函数 五、总结 简单易懂的倒排索引详解 一、引言 倒排索引是一种广泛应用于搜索引擎和大数据处理中的数据结构,…...
初级数据结构:栈和队列
目录 一、栈 (一)、栈的定义 (二)、栈的功能 (三)、栈的实现 1.栈的初始化 2.动态扩容 3.压栈操作 4.出栈操作 5.获取栈顶元素 6.获取栈顶元素的有效个数 7.检查栈是否为空 8.栈的销毁 9.完整代码 二、队列 (一)、队列的定义 (二)、队列的功能 (三)…...
在K8S中,pending状态一般由什么原因导致的?
在Kubernetes中,资源或Pod处于Pending状态可能有多种原因引起。以下是一些常见的原因和详细解释: 资源不足 概述:当集群中的资源不足以满足Pod或服务的需求时,它们可能会被至于Pending状态。这通常涉及到CPU、内存、存储或其他资…...
阿里云 - RocketMQ入门
前言 云消息队列 RocketMQ 版产品具备异步通信的优势,主要应用于【异步解耦】、【流量削峰填谷】等场景对于同步链路,需要实时返回调用结果的场景,建议使用RPC调用方案阿里云官网地址RocketMQ官网地址 模型概述 生产者生产消息并发送至服务…...
Agentic Automation:基于Agent的企业认知架构重构与数字化转型跃迁---我的AI经典战例
文章目录 Agent代理Agent组成 我在企业实战AI Agent企业痛点我构建的AI Agent App 项目开源 & 安装包下载 大家好,我是工程师令狐,今天想给大家讲解一下AI智能体,以及企业与AI智能体的结合,文章中我会列举自己在企业中Agent实…...
分享10个实用的Python工具的源码,支持定制
1.音频处理工具 【免费】一个功能丰富的音频处理工具箱,支持音频格式转换、剪辑和音量调节等功能资源-CSDN文库 2.视频转换工具 【免费】一个简单易用的视频格式转换工具,支持多种常见视频格式之间的转换资源-CSDN文库 3.PDF工具箱 【免费】一个功能…...
Denavit-Hartenberg DH MDH坐标系
Denavit-Hartenberg坐标系及其规则详解 6轴协作机器人的MDH模型详细图_6轴mdh-CSDN博客 N轴机械臂的MDH正向建模,及python算法_mdh建模-CSDN博客 运动学3-----正向运动学 | 鱼香ROS 机器人学:MDH建模 - 哆啦美 - 博客园 机械臂学习——标准DH法和改进MDH…...
WebPages 表单:设计与实现指南
WebPages 表单:设计与实现指南 引言 在当今的互联网时代,表单是WebPages与用户交互的重要手段。它不仅收集用户信息,还提供了一种便捷的交互方式。本文将详细介绍WebPages表单的设计与实现,旨在帮助开发者更好地理解并运用表单&…...
列表标签(无序列表、有序列表)
无序列表 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Document</title> </head><…...
每天学点小知识之设计模式的艺术-策略模式
行为型模式的名称、定义、学习难度和使用频率如下表所示: 1.如何理解模板方法模式 模板方法模式是结构最简单的行为型设计模式,在其结构中只存在父类与子类之间的继承关系。通过使用模板方法模式,可以将一些复杂流程的实现步骤封装在一系列基…...
AI开发学习之——PyTorch框架
PyTorch 简介 PyTorch (Python torch)是由 Facebook AI 研究团队开发的开源机器学习库,广泛应用于深度学习研究和生产。它以动态计算图和易用性著称,支持 GPU 加速计算,并提供丰富的工具和模块。 PyTorch的主要特点 …...
SAP HCM insufficient authorization, no.skipped personnel 总结归纳
导读 权限:HCM模块中有普通权限和结构化权限。普通权限就是PFCG的权限,结构化权限就是按照部门ID授权,颗粒度更细,对分工明细化的单位尤其重要,今天遇到的问题就是结构化权限的问题。 作者:vivi,来源&…...
机器学习算法在网络安全中的实践
机器学习算法在网络安全中的实践 本文将深入探讨机器学习算法在网络安全领域的应用实践,包括基本概念、常见算法及其应用案例,从而帮助程序员更好地理解和应用这一领域的技术。"> 序言 网络安全一直是信息技术领域的重要议题,随着互联…...
DeepSeek V3 vs R1:大模型技术路径的“瑞士军刀“与“手术刀“进化
DeepSeek V3 vs R1:——大模型技术路径的"瑞士军刀"与"手术刀"进化 大模型分水岭:从通用智能到垂直突破 2023年,GPT-4 Turbo的发布标志着通用大模型进入性能瓶颈期。当模型参数量突破万亿级门槛后,研究者们开…...
STM32CUBEIDE编译的hex使用flymcu下载后不能运行
测试后确认,不论是1.10版本还是1.16版本,编译生成的hex下载后不能运行,需要更改boot 设置才能开始运行,flymcu下载后已经告知一切正常,跳转到8000 0000处开始运行,实际没有反应,而使用mdk编译生…...
图像噪声处理技术:让图像更清晰的艺术
在这个数字化时代,图像作为信息传递的重要载体,其质量直接影响着我们的视觉体验和信息解读。然而,在图像采集、传输或处理过程中,难免会遇到各种噪声干扰,如高斯噪声、椒盐噪声等,这些噪声会降低图像的清晰…...
java-抽象类注意点
ChinesePerson 类 public class ChinesePerson extends Person{public ChinesePerson(){}public ChinesePerson(String name, int age){super(name, age);}Overridepublic void greet() {System.out.println("你好,我的名字叫" this.getName());} }Engl…...
【c++】类与对象详解
目录 面向过程思想和面向对象思想类的定义引入类的关键字类定义的两种方式类的访问限定符类的作用域类大小的计算封装 this指针类的6个默认成员函数构造函数初步理解构造函数深入理解构造函数初始化列表单参数构造函数引发的隐式类型转换 析构函数拷贝构造函数赋值运算符重载运…...
MySQL的GROUP BY与COUNT()函数的使用问题
在MySQL中,GROUP BY和 COUNT()函数是数据聚合查询中非常重要的工具。正确使用它们可以有效地统计和分析数据。然而,不当的使用可能会导致查询结果不准确或性能低下。本文将详细讨论 GROUP BY和 COUNT()函数的使用方法及常见问题,并提供相应的…...
问deepseek,如何看待ai降低学习成本而导致软件开发岗位需求降低,和工资下降。 软件从业人员何去何从?
它给我的回答是这样的: 思考逻辑 嗯,用户问的是AI如何降低学习成本,进而导致软件开发岗位需求减少和工资下降,以及软件从业人员该怎么办。这个问题挺复杂的,我得先理清楚各个部分。首先,AI确实在改变很多行…...
Jason配置环境变量
jason官网 https://jason-lang.github.io/ https://github.com/jason-lang/jason/releases 步骤 安装 Java 21 或更高版本 安装 Visual Studio Code 根据操作系统,请按照以下具体步骤操作 视窗 下载 Jason 的最新版本,选择“jason-bin-3.3.0.zip”…...
word2vec 实战应用介绍
Word2Vec 是一种由 Google 在 2013 年推出的重要词嵌入模型,通过将单词映射为低维向量,实现了对自然语言处理任务的高效支持。其核心思想是利用深度学习技术,通过训练大量文本数据,将单词表示为稠密的向量形式,从而捕捉单词之间的语义和语法关系。以下是关于 Word2Vec 实战…...
AI技术在SEO关键词优化中的应用策略与前景展望
内容概要 在数字营销的快速发展中,AI技术逐渐成为SEO领域的核心驱动力。其通过强大的数据分析和处理能力,不仅改变了我们优化关键词的方式,也提升了搜索引擎优化的效率和效果。在传统SEO中,关键词的选择与组合常依赖人工经验和直…...
c/c++高级编程
1.避免变量冗余初始化 结构体初始化为0,等价于对该内存进行一次memset,对于较大的结构体或者热点函数,重复的赋值带来冗余的性能开销。现代编译器对此类冗余初始化代码具有一定的优化能力,因此,打开相关的编译选项的优…...
玩转Docker | 使用Docker部署MySQL数据库
玩转Docker | 使用Docker部署MySQL数据库 玩转Docker | 使用Docker部署MySQL数据库一、Docker简介(一)Docker是什么(二)Docker的优势二、准备工作(一)安装Docker(二)了解MySQL数据库三、使用Docker部署MySQL数据库(一)拉取MySQL镜像(二)运行MySQL容器(三)验证MyS…...





