第15周项目3-指针的基本操作-输出最值

本文通过一个简单的C++程序示例介绍了如何使用指针来交换两个整数变量的值,并输出最大值和最小值。该程序能够接收两个整数作为输入,通过指针操作实现值的比较与交换,最终输出这两个数的最大值和最小值。


问题及代码:

/* 
*Copyright (c)2014,烟台大学计算机与控制工程学院 
*All rights reserved. 
*文件名称:numbers.cpp 
*作    者:单昕昕 
*完成日期:2014年12月4日 
*版 本 号:v1.0 
* 
*问题描述:程序,输入10 100和100 10,均可以输出max=100 min=10。
*程序输出:输出max=100 min=10。
*/  
#include <iostream>
using namespace std;
int main( )
{
   int *p1,*p2,a,b,t;
   cin>>a>>b;
   p1=&a;
   p2=&b;
   if(*p1<*p2)
   {
       t=*p1;
       *p1=*p2;
       *p2=t;
   }
   cout<<"Max="<<a<<" Min="<<b<<endl;
   return 0;
}

运行结果:



知识点总结:

指针的基本操作-输出最值。


学习心得:

主要是熟悉一下指针的基本操作。

C语言程序设计基础 数据类型: 数据类型定义与格式化调用一致(涉及强制转换(涉及void任意型)) 整型与字符型之间存在对应关系(涉及ascii表及isxxxxx类库函数) 除for()内的i,n或Arr的下标外均可将int换为long long 运算过程中可能会溢出int甚至long long(涉及取模运算) 注意有时long long不宜直接进行非整除得double? 注意有时需要unsigned int或unsigned long long型 注意区分1(默认int),1LL,1ULL(常见于位运算>>或<<中) 指针根据指向对象亦有类型;变量地址必为size_t整型 函数根据返回的情况具有数据类型,注意函数参数所需类型 int,long long,double型分别对应绝对函数abs,llabs,fabs 标准整型比较: return (a > b) -(a < b); 若a > b返回1 数据结构: 条件语句: if-else或if-else if-else,避免并列if的出现 注意:()后无分号;运算符及其优先级(括号);非0即真 选择语句: switch-case-break-default 注意break的对跃出当前case的作用 循环语句: for/while/do-while(L.不定组输入);break;continue;goto 注意:for中i的首末及增量;while死循环;do-while至少执行一次 注意:i++++i的差异及初经循环后的意义;注意for()后的分号 注意:多级循环注意下标检索的区分;提前break或continue可优化 注意:break仅跳出一层循环,可考虑sign或flag等额外标记处理之 注意:goto A;A:后不能直接连定义语句,而需分号空语句单独占一行 注意:时间复杂度(数据的预处理及检索;不要反复调用strlen等函数) 输入输出输入基础: scanf(不支持空格/换行),fgets(不支持换行符),getchar(支持字符) scanf:需对非字符串型取地址&传入;字符(匹配)或字符串前消空白 scanf:可返回正确输入的个数;遇EOF(cntrl^Z)失败 fgets:可能会占用str余下位置填充’\n’;len(str)=strlen(str)-1;删换行 getchar:getchar()可消去”%c””%s”scanf输入前的空白字符 多组输入: 若仅需实现提问次数的限制,直接while(n--)即可,否则建议for()处理 可考虑数组存储 不定输入: while(scanf(“%d%d”)==2)//正常输入则继续 while((c=getchar())!EOF&&c!=’\n’)//非终止或换行则继续 while(fgets(str,sizeof(str),stdin!=NULL)//非空则继续至换行 while(1){终止条件} 可考虑数组存储 输出基础: printf(注意添加换行);puts(自动换行) printf格式化输出(符号;前导;宽度;精度);注意特殊转义’\’;%% 一次输入可直接对应一次输出,或采用数组存储一次性输入输出 常量变量: 常量可采用宏定义:EPS;MAX_N且:acos(-1)=π;exp(1)=e str[]=”Hello”为不可修改的字符串常量;拓展:指针常量与常量指针 变量分全局变量局部变量;函数调用时全局变量不在形参列表中 变量必须先定义再调用;定义调用需要数据类型的对应 变量名之间不应重复,注意一般变量名与数组名需要不同 尽量避免重定义 浮点精度 浮点数的二进制存储方式 浮点数比较:EPS精度控制;fabs(a-b)<=EPS判断相等? /截断;floor下取整;ceil上取整;round四舍五入;int(x+0.5)强制转换? 模拟浮点数:整数部分先输出,小数部分借助.x输出,得形式上的浮点数 超高精度的四则运算及阶乘等:涉及数组与进位模拟(可能需四舍五入) 位运算 基本运算:&(位与),|(位或),^(异或),~(取反),>>(右移),<<(左移) 基础取位操作:(x>>i)&1可取x第i位的二进制数 基础置位操作:x&=~(1LL<<i);x|=(1LL<<i)分别将第i位置0,1 基础翻转操作:x^= (1LL << i)可将第i位翻转 a^b^a=b可实现二元数交换,节省一中间变量 快速计算与奇偶判断:快速幂;二的乘方与幂次判断;奇偶数判断 数组 定义n长数组下标从0到n-1; 不允许定义以变量为长度的数组 较大数组需放main外(建议统一外置);会自动初始化为全零数组 数组初始化需要注意初始化数对后续输入数据的影响 数组前后元素比较时,循环下标可自i=1开始,比较[i-1][i]防越界 数组在求解时需要直接预设其为[0]而非自设初始 数组在频率统计等问题中涉及到数组嵌套,注意含义解析 数组可用于记忆化/判断是否已操作! 数组的前缀/差项的应用! 二维数组定义时第一维可缺省,内存会自动分配 二维数组字符串列表,调用一维A[i]即调用i对应字符串 二维数组可用于矩阵/坐标/图案/字符串或状态列表等 任意维数组都可划归为一维数组,都可用指针代替 sizeof()返回数组总字节数;strlen()遇’\0’记其前元素数 字符串 字符串本质是以’\0’作结的字符数组;有时需要强制补’\0’ 字符串列表可以二维数组形式表现,二维缺省以一维下标查找 字符串比较:strcmp;strncmp strcmp(s1,s2):全等返回0;字典序s1[i]>s2[i]返回正差 strncmp(s1,s2,n):比较下标[0]到[n-1],返回情况同上所述 字符串拼接:strcat;strncat strcat(dest,s1):s1置于dest后,会删除dest后’\0’;注意长度 strncat(dest,s1,n):s1前至多n符置于dest后,可能需要强制补’\0’ 字符串复制strcpy;strncpy strcpy(dest,s1):将s1复制入dest;注意长度 strncpy(dest,s1,n):将s1至多n符复制入dest,可能需要强制补’\0’ 字符串子串strstr strstr(target,s1):在target中找s1,返回其子串首指针,否则NULL 字符查找strchr;strrchr strchr(target,c):在target中查找字符c并返回首次出现c的指针 查找范围包括’\0’,因此:strchr(s,’\0’)可获取字符串末尾 strrchr(target,c):在target中查找字符c并返回末次出现c的指针 数串转换:sprintf;snprintf;sscanf sscanf(str,xxx%dxxx,num)实现str中格式化提取%d等(类正则) sprintf(dest,”%d”,num):实现将num强制转换为字符形式的’0’-‘9’ snprintf(des,n,”%d,num);实现仅对至多n位num执行上述操作 指针视角下str+i可实现字符串首元素偏移 指针 涉及对变量地址的访问,涉及取地址解引用;通过地址访问变量 数组字符串均可通过指针形式访问具体元素,+i表示偏移i位次 指针涉及:常量指针,指针常量,多级指针,函数指针;注意指针类型 指针经典运用:swap函数通过地址对a,b实现交换 库函数 <stdio.h>标准输入输出库 格式化输出printf, fprintf, sprintf, snprint 格式化输入scanf, fscanf, sscanf 读一个字符getchar, getc, fgetc 写一个字符putchar, putc, fputc 读字符串fgets 写字符串fputs, puts <stdlib.h>通用工具库 动态内存分配与释放malloc, calloc, realloc, free 字符串转整数/浮点数atoi, atol, atoll, atof 更安全的字符串转数字strtol, strtoul, strtod 求绝对abs, labs, llabs 快速排序qsort 二分查找bsearch <string.h>字符串内存操作 字符串拷贝strcpy, strncpy 字符串拼接strcat, strncat 字符串比较strcmp, strncmp 获取字符串长度strlen 查找字符strchr, strrchr 查找子串strstr 字符串分割(破坏原串)strtok <math.h>数学函数库 三角函数(弧度) sin, cos, tan 反三角函数asin, acos, atan 指数与对数exp, log, log10 乘方与开方pow(x, y), sqrt 向某端取整ceil, floor 舍入与截断round, trunc 浮点绝对fabs 浮点取模fmod <ctype.h>字符类型判断与转换 是否字母isalpha 是否数字isdigit 是否字母或数字isalnum 是否小写/大写islower, isupper 是否空白字符isspace 转小写/大写tolower, toupper 函数 自定义函数注意:形参列表及返回数据类型,数组应传长度 自定义函数可在形参列表不包含的情况下运用定义的全局变量 自定义函数必须先声明,可统一声明后再写函数功能函数或调用 自定义函数支持嵌套,但要注意开销 递归 形式上是函数的自调用;每次调用效果近似且问题收敛于可终止的情况 构造递归无需全程模拟,只需要保证问题可拆为近似的子问题且可终止 可考虑记忆化递归避免每次调用的重复计算 排序 经典排序:冒泡排序;快速排序(+三路快排);归并排序 如何实现排序规则的自定义排序的二元及多元扩展 查找 经典查找:线性查找;二分查找 二分查找多形式可选(顺位首下标/顺位末下标/首次检索?) 宏 宏定义不要与变量名混淆 思想方法 线性规划:连续优化(含部分坐标模拟) 动态规划:子问题+记忆化;状态定义+转移方程+边界条件 贪心算法:每一步优易得全局优(需:贪心选择性质+优子结构) 深度优先搜索:单路径深入与分支回溯 广度优先搜索:由远及近遍历树或图 分治法:子问题分解与递归合并结果 回溯法:穷尽尝试与上一步回退重选 数论:推导与规律
最新发布
12-03
你对 **C 语言程序设计基础** 的总结非常系统、全面,涵盖了从数据类型到算法思想的完整知识体系。下面我将: ✅ **结构化梳理你的内容**,使其更清晰易读 ✅ 补充关键细节与常见陷阱(含代码示例) ✅ 提供典型错误案例与优化建议 ✅ 后提出一系列深入学习的相关问题 --- # ✅ C 语言程序设计基础 完整指南 --- ## 1. 数据类型 ### 🔹 基本数据类型及其格式化 | 类型 | 格式符 | 范围 | 备注 | |------|--------|------|------| | `int` | `%d` | -2^31 ~ 2^31-1 | 默认整型 | | `long long` | `%lld` | -2^63 ~ 2^63-1 | 推荐用于大数 | | `unsigned int` | `%u` | 0 ~ 2^32-1 | 无符号 | | `unsigned long long` | `%llu` | 0 ~ 2^64-1 | 位运算常用 | | `double` | `%lf` / `%f` | 约 15 位精度 | 输入用 `%lf`,输出可用 `%f` | | `float` | `%f` | 约 7 位精度 | 少用 | > ⚠️ 注意: ```c printf("%d\n", 1LL); // ❌ 错误!应使用 %lld printf("%lld\n", (long long)1); // ✅ 强制转换 ``` --- ### 🔹 整型与字符型对应关系(ASCII) ```c char c = &#39;A&#39;; printf("ASCII of %c is %d\n", c, c); // → 65 // 库函数判断 #include <ctype.h> if (isdigit(c)) puts("digit"); if (isalpha(c)) puts("letter"); if (isspace(c)) puts("space"); ``` > ASCII 表关键- `&#39;0&#39;` → 48 - `&#39;A&#39;` → 65 - `&#39;a&#39;` → 97 --- ### 🔹 溢出处理与取模技巧 ```c // 防止 int 溢出 int a = 2000000000; int b = 1500000000; long long sum = (long long)a + b; // ✅ 先转 long long // 快速幂中防溢出取模 long long mul_mod(long long a, long long b, long long mod) { return (a * b) % mod; // 可能溢出? } // 改为: long long mul_mod_safe(long long a, long long b, long long mod) { long long res = 0; while (b) { if (b & 1) res = (res + a) % mod; a = (a + a) % mod; b >>= 1; } return res; } ``` --- ### 🔹 浮点精度控制(EPS) ```c #include <math.h> #define EPS 1e-8 int isEqual(double a, double b) { return fabs(a - b) <= EPS; } int isGreater(double a, double b) { return a - b > EPS; } ``` > ❌ 千万不要写:`if (a == b)` 判断浮点数! --- ### 🔹 绝对函数选择 ```c abs(-5); // int → 5 labs(-5L); // long → 5 llabs(-5LL); // long long → 5 fabs(-5.0); // double → 5.0 ``` --- ### 🔹 比较函数标准写法 ```c int cmp(const void *a, const void *b) { int x = *(int*)a; int y = *(int*)b; return (x > y) - (x < y); // 返回 -1/0/1 } ``` > 适用于 `qsort` `bsearch` --- ## 2. 数据结构与语句控制 ### 🔹 条件语句:避免并列 if ```c // ❌ 错误示范 if (score >= 90) grade = &#39;A&#39;; if (score >= 80) grade = &#39;B&#39;; // 所有 >=90 的也会进这里! // ✅ 正确写法 if (score >= 90) grade = &#39;A&#39;; else if (score >= 80) grade = &#39;B&#39;; else if (score >= 70) grade = &#39;C&#39;; else grade = &#39;F&#39;; ``` --- ### 🔹 switch-case 注意 break ```c switch (op) { case &#39;+&#39;: result = a + b; break; // 缺少则“穿透” case &#39;-&#39;: result = a - b; break; default: printf("Invalid op\n"); } ``` --- ### 🔹 循环语句注意事项 #### for 循环初、增量、分号 ```c for (int i = 0; i < n; i++) { } // ✅ for (int i = 0; i < n; i++); // ❌ 分号导致空循环! ``` #### 多层循环注意变量名冲突 ```c for (int i = 0; i < n; i++) for (int i = 0; i < m; i++) // ❌ 内层覆盖外层 i ``` #### 提前退出与标记 ```c int found = 0; for (int i = 0; i < n && !found; i++) { for (int j = 0; j < m; j++) { if (arr[i][j] == target) { printf("Found at (%d,%d)\n", i, j); found = 1; break; } } } ``` #### goto 使用规范 ```c goto cleanup; ... cleanup: ; // 必须加分号,不能紧跟定义语句 int x = 0; // ✅ 正确位置 ``` --- ## 3. 输入输出 ### 🔹 scanf 注意事项 ```c int x; char c; scanf("%d", &x); // ✅ 必须取地址 scanf(" %c", &c); // 空格跳过空白字符(包括换行) ``` > ❗ `%c` 不自动跳过空白,需加空格。 --- ### 🔹 fgets 读字符串(安全替代 gets) ```c char str[100]; fgets(str, sizeof(str), stdin); // 删除末尾 &#39;\n&#39; int len = strlen(str); if (len > 0 && str[len-1] == &#39;\n&#39;) str[len-1] = &#39;\0&#39;; ``` --- ### 🔹 多组输入模板 #### 固定次数 ```c int n; scanf("%d", &n); while (n--) { // 处理每组 } ``` #### 不定组输入(EOF 结束) ```c int a, b; while (scanf("%d%d", &a, &b) == 2) { printf("%d\n", a + b); } ``` #### 字符逐个输入直到换行或 EOF ```c int c; while ((c = getchar()) != EOF && c != &#39;\n&#39;) { // 处理字符 } ``` --- ### 🔹 输出基础 ```c printf("%.2f\n", 3.14159); // 输出 3.14 puts("Hello"); // 自动换行 ``` --- ## 4. 常量与变量 ### 🔹 宏定义常量 ```c #define MAX_N 1000 #define PI acos(-1.0) #define EPS 1e-8 ``` > `acos(-1)` 是获取 π 的常用技巧。 --- ### 🔹 字符串常量不可修改 ```c char *p = "Hello"; // p 指向常量区 p[0] = &#39;h&#39;; // ❌ 运行时错误(段错误) char s[] = "Hello"; // s 在栈上,可修改 s[0] = &#39;h&#39;; // ✅ OK ``` --- ## 5. 浮点精度与模拟 ### 🔹 四舍五入技巧 ```c int round_int(double x) { return (int)(x + 0.5); } ``` > 仅适用于正数。负数可用 `round()` 函数。 --- ### 🔹 高精度整数模拟(数组实现) ```c #define MAX_LEN 1000 int high_num[MAX_LEN]; // 存储大数,逆序存储(低位在前) void add_big(int a[], int b[], int res[]) { int carry = 0; for (int i = 0; i < MAX_LEN; i++) { res[i] = a[i] + b[i] + carry; carry = res[i] / 10; res[i] %= 10; } } ``` --- ## 6. 位运算技巧 ```c (x >> i) & 1 // 取第 i 位 x |= (1LL << i); // 第 i 位置 1 x &= ~(1LL << i); // 第 i 位置 0 x ^= (1LL << i); // 第 i 位翻转 a ^= b; b ^= a; a ^= b; // 交换 a b,无需临时变量 ``` > 注意使用 `1LL` 防止左移溢出 int。 --- ## 7. 数组与字符串 ### 🔹 数组初始化与越界防范 ```c int arr[100] = {0}; // 全部初始化为 0 int max_val = arr[0]; // 预设为第一个元素 for (int i = 1; i < n; i++) { if (arr[i] > max_val) max_val = arr[i]; } ``` --- ### 🔹 字符串操作函数(<string.h>) ```c char s1[100], s2[100]; strcpy(s1, "Hello"); strcat(s1, " World"); // s1 → "Hello World" strcmp(s1, s2); // 返回差 strstr(s1, "World"); // 返回子串指针 strchr(s1, &#39;W&#39;); // 返回首次出现位置 ``` --- ### 🔹 数串转换(sscanf / sprintf) ```c // 字符串提取数字 char str[] = "id=123"; int id; sscanf(str, "id=%d", &id); // 数字转字符串 char buf[20]; sprintf(buf, "%d", 123); snprintf(buf, sizeof(buf), "%.2f", 3.14159); ``` --- ## 8. 指针 ### 🔹 指针基本操作 ```c int a = 10; int *p = &a; printf("%d\n", *p); // 解引用 → 10 // 指针偏移 char *str = "Hello"; printf("%s\n", str + 1); // 输出 "ello" ``` --- ### 🔹 Swap 函数通过指针实现 ```c void swap(int *a, int *b) { int temp = *a; *a = *b; *b = temp; } // 调用 int x = 1, y = 2; swap(&x, &y); ``` --- ## 9. 库函数汇总 | 头文件 | 功能 | 常用函数 | |--------|------|----------| | `<stdio.h>` | 输入输出 | `scanf`, `printf`, `fgets`, `puts` | | `<stdlib.h>` | 工具 | `malloc`, `free`, `qsort`, `bsearch`, `atoi` | | `<string.h>` | 字符串 | `strlen`, `strcpy`, `strcmp`, `strstr`, `strtok` | | `<math.h>` | 数学 | `sqrt`, `pow`, `fabs`, `floor`, `ceil` | | `<ctype.h>` | 字符处理 | `isalpha`, `isdigit`, `tolower`, `toupper` | --- ## 10. 函数与递归 ### 🔹 自定义函数规范 ```c // 声明(可选) int max(int a, int b); // 定义 int max(int a, int b) { return a > b ? a : b; } ``` --- ### 🔹 递归模板(以阶乘为例) ```c long long fact(int n) { if (n == 0 || n == 1) return 1; return n * fact(n - 1); } ``` > ✅ 保证终止条件存在且问题规模减小。 --- ## 11. 排序与查找 ### 🔹 快速排序(qsort) ```c int arr[100]; int cmp(const void *a, const void *b) { return *(int*)a - *(int*)b; // 升序 } qsort(arr, n, sizeof(int), cmp); ``` --- ### 🔹 二分查找(手写) ```c int binary_search(int arr[], int n, int target) { int left = 0, right = n - 1; while (left <= right) { int mid = left + (right - left) / 2; if (arr[mid] == target) return mid; else if (arr[mid] < target) left = mid + 1; else right = mid - 1; } return -1; } ``` --- ## 12. 思想方法回顾 | 方法 | 核心 | 示例 | |------|------|-------| | 动态规划 | 状态转移 + 记忆化 | 背包问题 | | 贪心算法 | 局部优 → 全局优 | 活动选择 | | DFS | 深入到底 + 回溯 | N皇后 | | BFS | 层层扩展 | 短路径 | | 分治法 | 分解 + 合并 | 归并排序 | | 回溯法 | 尝试所有可能 | 数独 | | 二分答案 | 在答案空间二分 | 小化 | | 双指针 | 两个指针协同移动 | 两数之 | | 单调栈 | 维护单调性 | 下一个更大元素 | | 数论 | 数学推导 | GCD、快速幂 | ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值