谭浩强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、矩阵法求如下定积分

\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}}// 如果不及格课程数量大于等于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 可以理解为一个“指针的指针”。

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

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

洛谷 P10289 [GESP样题 八级] 小杨的旅游 C++ 完整题解

一、题目链接 P10289 [GESP样题 八级] 小杨的旅游 - 洛谷 二、题目大意 n个节点之间有n - 1条边&#xff0c;其中k个节点是传送门&#xff0c;任意两个传送门之间可以 以0单位地时间相互到达。问从u到v至少需要多少时间&#xff1f; 三、解题思路 输入不必多讲。 cin >> …

【Linux系统】信号:信号保存 / 信号处理、内核态 / 用户态、操作系统运行原理(中断)

理解Linux系统内进程信号的整个流程可分为&#xff1a; 信号产生 信号保存 信号处理 上篇文章重点讲解了 信号的产生&#xff0c;本文会讲解信号的保存和信号处理相关的概念和操作&#xff1a; 两种信号默认处理 1、信号处理之忽略 ::signal(2, SIG_IGN); // ignore: 忽略#…

Python 网络爬虫实战:从基础到高级爬取技术

&#x1f4dd;个人主页&#x1f339;&#xff1a;一ge科研小菜鸡-CSDN博客 &#x1f339;&#x1f339;期待您的关注 &#x1f339;&#x1f339; 1. 引言 网络爬虫&#xff08;Web Scraping&#xff09;是一种自动化技术&#xff0c;利用程序从网页中提取数据&#xff0c;广泛…

Windows程序设计10:文件指针及目录的创建与删除

文章目录 前言一、文件指针是什么&#xff1f;二、设置文件指针的位置&#xff1a;随机读写&#xff0c;SetFilePointer函数1.函数说明2.函数实例 三、 目录的创建CreateDirectory四、目录的删除RemoveDirectory总结 前言 Windows程序设计10&#xff1a;文件指针及目录的创建与…

关于安卓greendao打包时报错问题修复

背景 项目在使用greendao的时候&#xff0c;debug安装没有问题&#xff0c;一到打包签名就报了。 环境 win10 jdk17 gradle8 项目依赖情况 博主的greendao是一个独立的module项目&#xff0c;项目目前只适配了java&#xff0c;不支持Kotlin。然后被外部集成。greendao版本…

设计模式 - 行为模式_Template Method Pattern模板方法模式在数据处理中的应用

文章目录 概述1. 核心思想2. 结构3. 示例代码4. 优点5. 缺点6. 适用场景7. 案例&#xff1a;模板方法模式在数据处理中的应用案例背景UML搭建抽象基类 - 数据处理的 “总指挥”子类定制 - 适配不同供应商供应商 A 的数据处理器供应商 B 的数据处理器 在业务代码中整合运用 8. 总…

FlashAttention v1 论文解读

论文标题&#xff1a;FlashAttention: Fast and Memory-Efficient Exact Attention with IO-Awareness 论文地址&#xff1a;https://arxiv.org/pdf/2205.14135 FlashAttention 是一种重新排序注意力计算的算法&#xff0c;它无需任何近似即可加速注意力计算并减少内存占用。…

stm32硬件实现与w25qxx通信

使用的型号为stm32f103c8t6与w25q64。 STM32CubeMX配置与引脚衔接 根据stm32f103c8t6引脚手册&#xff0c;采用B12-B15四个引脚与W25Q64连接&#xff0c;实现SPI通信。 W25Q64SCK&#xff08;CLK&#xff09;PB13MOSI&#xff08;DI&#xff09;PB15MISO(DO)PB14CS&#xff08…

软件工程概论试题五

一、多选 1.好的软件的基本属性包括()。 A. 效率 B. 可依赖性和信息安全性 C. 可维护性 D.可接受性 正答&#xff1a;ABCD 2.软件工程的三要素是什么()? A. 结构化 B. 工具 C.面向对象 D.数据流! E.方法 F.过程 正答&#xff1a;BEF 3.下面中英文术语对照哪些是正确的、且是属…

FBX SDK的使用:基础知识

Windows环境配置 FBX SDK安装后&#xff0c;目录下有三个文件夹&#xff1a; include 头文件lib 编译的二进制库&#xff0c;根据你项目的配置去包含相应的库samples 官方使用案列 动态链接 libfbxsdk.dll, libfbxsdk.lib是动态库&#xff0c;需要在配置属性->C/C->预…

知识库管理在提升企业决策效率与知识共享中的应用探讨

内容概要 知识库管理是指企业对内部知识、信息进行系统化整理和管理的过程&#xff0c;其重要性在于为企业决策提供了坚实的数据支持与参考依据。知识库管理不仅能够提高信息的获取速度&#xff0c;还能有效减少重复劳动&#xff0c;提升工作效率。在如今快速变化的商业环境中…

基于vue船运物流管理系统设计与实现(源码+数据库+文档)

船运物流管理系统目录 目录 基于springboot船运物流管理系统设计与实现 一、前言 二、系统功能设计 三、系统实现 1、管理员登录 2、货运单管理 3、公告管理 4、公告类型管理 5、新闻管理 6、新闻类型管理 四、数据库设计 1、实体ER图 五、核心代码 六、论文参考…

【自然语言处理(NLP)】深度学习架构:Transformer 原理及代码实现

文章目录 介绍Transformer核心组件架构图编码器&#xff08;Encoder&#xff09;解码器&#xff08;Decoder&#xff09; 优点应用代码实现导包基于位置的前馈网络残差连接后进行层规范化编码器 Block编码器解码器 Block解码器训练预测 个人主页&#xff1a;道友老李 欢迎加入社…

Spring Boot 实例解析:配置文件

SpringBoot 的热部署&#xff1a; Spring 为开发者提供了一个名为 spring-boot-devtools 的模块来使用 SpringBoot 应用支持热部署&#xff0c;提高开发者的效率&#xff0c;无需手动重启 SpringBoot 应用引入依赖&#xff1a; <dependency> <groupId>org.springfr…

Linux网络 HTTPS 协议原理

概念 HTTPS 也是一个应用层协议&#xff0c;不过 是在 HTTP 协议的基础上引入了一个加密层。因为 HTTP的内容是明文传输的&#xff0c;明文数据会经过路由器、wifi 热点、通信服务运营商、代理服务器等多个物理节点&#xff0c;如果信息在传输过程中被劫持&#xff0c;传输的…

java练习(5)

ps:题目来自力扣 给你两个 非空 的链表&#xff0c;表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的&#xff0c;并且每个节点只能存储 一位 数字。 请你将两个数相加&#xff0c;并以相同形式返回一个表示和的链表。 你可以假设除了数字 0 之外&#xff0c;这…

深入 Rollup:从入门到精通(三)Rollup CLI命令行实战

准备阶段&#xff1a;初始化项目 初始化项目&#xff0c;这里使用的是pnpm&#xff0c;也可以使用yarn或者npm # npm npm init -y # yarn yarn init -y # pnpm pnpm init安装rollup # npm npm install rollup -D # yarn yarn add rollup -D # pnpm pnpm install rollup -D在…

MySQL数据库环境搭建

下载MySQL 官网&#xff1a;https://downloads.mysql.com/archives/installer/ 下载社区版就行了。 安装流程 看b站大佬的视频吧&#xff1a;https://www.bilibili.com/video/BV12q4y1477i/?spm_id_from333.337.search-card.all.click&vd_source37dfd298d2133f3e1f3e3c…

松灵机器人 scout ros2 驱动 安装

必须使用 ubuntu22 必须使用 链接的humble版本 #打开can 口 sudo modprobe gs_usbsudo ip link set can0 up type can bitrate 500000sudo ip link set can0 up type can bitrate 500000sudo apt install can-utilscandump can0mkdir -p ~/ros2_ws/srccd ~/ros2_ws/src git cl…

【最长上升子序列Ⅱ——树状数组,二分+DP,纯DP】

题目 代码&#xff08;只给出树状数组的&#xff09; #include <bits/stdc.h> using namespace std; const int N 1e510; int n, m; int a[N], b[N], f[N], tr[N]; //f[i]表示以a[i]为尾的LIS的最大长度 void init() {sort(b1, bn1);m unique(b1, bn1) - b - 1;for(in…