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

# 第10章 指针和结构体

10.1 指针

一、什么是指针

指针(Pointer):变量的地址,通过它能找到以它为地址的内存单元。

例子1:理解指针概念

#include <bits/stdc++.h>
using namespace std;
int main(){int x=10;int* p=&x; // 定义整数指针p,指向x的地址cout<<p<<endl; // 输出x的地址(指针值)cout<<*p<<endl; // 输出p指向地址对应的值(即x的值)*p=*p+2; // 通过指针修改变量x的值(等价于x=x+2)cout<<x<<endl;return 0;
}

例子2:值拷贝与地址拷贝对比

#include <bits/stdc++.h>
using namespace std;
int main(){int x=10;// 值拷贝:y是新变量,修改y不影响xint y =x;y=y+2;cout<<x<<endl; // 输出10// 地址拷贝:p指向x的地址,修改*p即修改xint* p=&x;*p=*p+2;cout<<x<<endl; // 输出12return 0;
}

例子3:&和*的嵌套使用

#include <bits/stdc++.h>
using namespace std;
int main(){int x=10;int *p=&x;cout<<p<<endl; // 输出x的地址cout<<*p<<endl; // 输出x的值cout<<&(*p)<<endl; // 等价于&x,输出x的地址cout<<*&(*p)<<endl; // 等价于*p,输出x的值return 0;
}

例子4:p++和(p)++的区别

#include <bits/stdc++.h>
using namespace std;
int main(){int x=10;int* p=&x;cout<<p<<" "<<*p<<endl; // 输出x的地址和10// ++优先级高于*,*p++等价于p++(指针地址自增,不修改x的值)// *p++; (*p)++; // 先取p指向的值,再自增(x变为11)*p=*p+1; // x再自增1(变为12)cout<<p<<" "<<*p<<endl; // 输出原地址和12return 0;
}

二、指针作用

  1. 通过函数修改变量的值:普通参数传递是值拷贝,指针传递可直接操作原变量
#include <bits/stdc++.h>
using namespace std;
void change1(int x){ x++; } // 值传递,不影响原变量
void change2(int *p){ (*p)++; } // 指针传递,修改原变量
int main(){int x=1;change1(x);cout<<x<<endl; // 输出1int p=1;change2(&p);cout<<p<<endl; // 输出2return 0;
}
  1. 让函数返回多个值:通过指针输出额外结果
#include <bits/stdc++.h>
using namespace std;
// 返回平均值,通过指针输出最大值和最小值
double num(int a,int b,int* max,int* min){if(a>b){*max =a;*min =b;}else{*max =b;*min =a;}return(a+b)/2.0;
}
int main(){int a,b,max,min;cin>>a>>b;double r=num(a,b,&max,&min);cout<<max<<" "<<min<<" "<<r<<endl;return 0;
}
  1. 在scanf中使用指针:scanf需传入变量地址
#include <bits/stdc++.h>
using namespace std;
int main(){int a,b;// 变量读入:&取地址scanf("%d%d",&a,&b);// 变量输出printf("%d+%d=%d\n",a,b,a+b);printf("%d-%d=%d\n",a,b,a-b);int *p =&a;printf("%p %d\n",p,*p); // 输出a的地址和值return 0;
}

格式说明:%d(整数)、%f(float)、%lf(double)、%c(字符)、%s(字符串)、%p(指针)

三、数组指针

数组本质是指向首元素(a[0])的地址,指针可遍历数组

例子1:数组与指针的关联

#include <bits/stdc++.h>
using namespace std;
int main(){int a[5]={10,20,30,40,50};cout<<a<<" "<<&a<<" "<<&a[0]<<endl; // 三者均为a[0]的地址int *p =a; // 指针p指向数组首元素cout<<p<<" "<<a[0]<<endl; // 输出首地址和10*p=*p+2; // 修改a[0]为12cout<<p<<" "<<a[0]<<endl;p++; // 指针指向a[1]*p=*p+2; // 修改a[1]为22cout<<p<<" "<<a[1]<<endl;return 0;
}

例子2:函数中通过指针操作数组

#include <bits/stdc++.h>
using namespace std;
// 数组形式参数
void fun1(int a[],int n){for(int i=0;i<n;i++){cout<<a[i]<<" ";}cout<<endl;
}
// 指针形式参数
void fun2(int* a,int n){for(int i=0;i<n;i++){cout<<*a<<" ";a++;}cout<<endl;
}
// 字符数组遍历(指针方式)
void fun4(char* s){while(*s!='\0'){cout<<*s<<" ";s++;}cout<<endl;
}
int main(){int a[3]={10,20,30};fun1(a,3);fun2(a,3);char s[10]="hello";fun4(s);return 0;
}

10.2 结构体

一、什么是结构体

结构体是用户自定义的数据结构,可存储不同类型数据项(数组仅存储相同类型)。

例子1:结构体定义与使用

#include <bits/stdc++.h>
using namespace std;
// 定义结构体Student(驼峰命名)
struct Student{int num; // 学号string name; // 姓名double height; // 身高
}s1,s2; // 定义结构体时直接创建变量s1、s2// 输出结构体成员(struct可省略)
void print(Student s){cout<<s.num<<" "<<s.name<<" "<<s.height<<endl;
}int main(){Student s; // 创建结构体变量// 赋值s.num =1;s.name="zhang";s.height=178.5;print(s);// 直接给s1赋值s1.num=2;s1.name="wang";s1.height=182.6;print(s1);return 0;
}

注意:引用结构体成员用“结构体变量.成员名”

例子2:结构体数组

#include <bits/stdc++.h>
using namespace std;
struct Student{int num;string name;double height;
};
// 输出结构体数组
void print(Student a[],int n){for(int i=0;i<n;i++){cout<<a[i].num<<" "<<a[i].name<<" "<<a[i].height<<endl;}
}
int main(){int n;Student a[100]; // 结构体数组cin>>n;for(int i=0;i<n;i++){cin>>a[i].num>>a[i].name>>a[i].height;}print(a,n);return 0;
}

例子3:结构体指针

#include <bits/stdc++.h>
using namespace std;
struct Student{int num;string name;double height;
};
int main(){Student s;s.num=1;s.name="wang";s.height=185.5;// 直接访问成员cout<<s.num<<" "<<s.name<<" "<<s.height<<endl;// 结构体指针Student *p =&s;// 指针访问成员:-> 或 (*p).成员名cout<<p->num<<" "<<p->name<<" "<<p->height<<endl;cout<<(*p).num<<" "<<(*p).name<<" "<<(*p).height<<endl;return 0;
}

二、结构体的应用

应用1:期末考试成绩排名(冒泡排序+sort排序)

// 解法一:冒泡排序
#include <bits/stdc++.h>
using namespace std;
struct Student{int num;string name;int score;
};
int main(){Student a[110];int n,i,j;cin>>n;for(i=0;i<n;i++){cin>>a[i].num>>a[i].name>>a[i].score;}// 冒泡排序:成绩降序,成绩相同学号升序for(i=1;i<=n-1;i++){for(j=0;j<=n-i-1;j++){if(a[j].score <a[j+1].score || (a[j].score==a[j+1].score && a[j].num>a[j+1].num)){swap(a[j],a[j+1]);}}}for(i=0;i<n;i++){cout<<a[i].num<<" "<<a[i].name<<" "<<a[i].score<<endl;}return 0;
}// 解法二:sort排序
#include <bits/stdc++.h>
using namespace std;
struct Student{int num;string name;int score;
};
// 比较函数
bool cmp(Student s1,Student s2){if(s1.score>s2.score || (s1.score==s2.score && s1.num<s2.num)){return true;}else{return false;}
}
int main(){Student a[110];int n,i;cin>>n;for(i=0;i<n;i++){cin>>a[i].num>>a[i].name>>a[i].score;}sort(a,a+n,cmp);for(i=0;i<n;i++){cout<<a[i].num<<" "<<a[i].name<<" "<<a[i].score<<endl;}return 0;
}

应用2:遥控飞机争夺赛(求平均成绩并排序)

#include <bits/stdc++.h>
using namespace std;
struct Player{int num; // 选手编号double score; // 平均成绩
};
bool cmp(Player p1,Player p2){if(p1.score>p2.score){return true;}else{return false;}
}
int main(){int n,i,j,x,s,ma,mi;Player a[110];cin>>n;for(i=0;i<n;i++){cin>>a[i].num;s=0;ma=INT_MIN;mi=INT_MAX;for(j=0;j<5;j++){cin>>x;s+=x;ma=max(ma,x);mi=min(mi,x);}a[i].score=(s-ma-mi)/3.0; // 去掉最高分和最低分求平均}sort(a,a+n,cmp);// 输出前三名,保留3位小数for(i=0;i<3;i++){cout<<a[i].num<<" "<<fixed<<setprecision(3)<<a[i].score<<endl;}return 0;
}

应用3:活动选择(贪心算法)

#include <bits/stdc++.h>
using namespace std;
struct Node{int begin; // 活动开始时间int end; // 活动结束时间
}a[110];
// 按结束时间升序排序
bool cmp(Node n1,Node n2){if(n1.end<n2.end){return true;}else{return false;}
}
int main(){int n,i,c=0,e;cin>>n;for(i=0;i<n;i++){cin>>a[i].begin>>a[i].end;}sort(a,a+n,cmp);c=1;e=a[0].end; // 第一个活动必选// 遍历后续活动,选择不冲突的for(i=1;i<n;i++){if(a[i].begin>=e){c++;e=a[i].end;}}cout<<c<<endl;return 0;
}

应用4:宇宙总统2(统计得票并排序)

#include <bits/stdc++.h>
using namespace std;
struct Node{string name; // 名字int count; // 得票数
}a[1100];
// 得票数降序,得票相同按名字字典码降序
bool cmp(Node n1,Node n2){if(n1.count>n2.count || (n1.count==n2.count && n1.name>n2.name)){return true;}else{return false;}
}
int main(){int n,k=0,i,j;bool f;string s;cin>>n;for(i=1;i<=n;i++){cin>>s;f=false;// 查找是否已有该名字for(j=1;j<=k;j++){if(a[j].name==s){a[j].count++;f=true;break;}}// 不存在则新增if(!f){k++;a[k].name=s;a[k].count=1;}}sort(a+1,a+k+1,cmp);for(i=1;i<=k;i++){cout<<a[i].name<<" "<<a[i].count<<endl;}return 0;
}

三、结构体作业

  1. 1730:【入门】购买贺年卡
  2. 1740:【基础】统计每个数出现的次数(提示:结构体存储数及出现次数)
  3. 1346:【入门】等比例缩放照片(提示:结构体存储宽、高及宽高比差值)
  4. 1347:【基础】游览动物园(提示:结构体存储坐标、与小红距离、与出口距离)
  5. 1561:【提高】买木头(提示:结构体存储木头长度和数量)
  6. 1330:【入门】求最大梯形的面积(提示:结构体存储上底、下底、高和面积)
  7. 1482:【提高】花生采摘(提示:结构体存储坐标和花生数量)
http://www.jsqmd.com/news/41214/

相关文章:

  • 2025年步进式加热直饮水机订制厂家权威推荐榜单:奶茶店全自动烧水器/大型工业净水器/饭店专用开水器源头厂家精选
  • 2025 最新钢结构厂家推荐排行榜,涵盖全产业链服务与优质产能企业权威甄选钢结构建筑/钢结构房屋/钢结构屋面/钢结构网架/钢结构桁架/钢结构连廊公司推荐
  • 2025 年 11 月漆渣脱水系统,漆渣脱水机,漆渣脱水装置品牌最新推荐,产能、专利、环保三维数据透视!
  • Convex
  • 2025年全自动无屑切割倒角一体机实力厂家权威推荐榜单:自动化切割倒角一体机/切割倒角一体机/自动切割倒角一体机源头厂家精选
  • 2025 年 11 月喷漆废水处理工艺,喷漆废水处理技术改造,喷漆废水处理运维服务公司最新推荐,聚焦资质、案例、售后的五家机构深度解读
  • 2025 国内网架厂家最新推荐排行榜:聚焦钢结构 / 球形 / 螺栓球多场景,甄选技术服务双优的权威品牌指南
  • 【题解】P4707 重返现世
  • Flink Data Sink 理论 、架构、语义保证、两阶段提交与可插拔拓扑 - 指南
  • 滞留卡常题
  • 2025年推拉窗源头厂家权威推荐榜单:性价比门窗/系统窗/自建房门窗源头厂家精选
  • Cursor ai network issue workaround in Ubuntu 22.04
  • 2025 年漆渣脱水设备厂家最新推荐榜单:优质品牌厂家工艺系统装置全解析,助力企业高效环保处置漆渣脱水系统/漆渣脱水机/漆渣脱水装置厂家推荐
  • 2025 最新喷漆废水处理公司推荐!喷漆废水处理设备 / 药剂 / 工艺 / 循环回用系统优质品牌榜单,含技术改造与运维服务厂家优选
  • [KaibaMath]1024 丑陋的真子集符号⫋的由来
  • 安装Ubuntu
  • 完整教程:VScode 入门(设置篇)
  • 微服务架构中的 Token 工作机制详解
  • [KaibaMath]1023 柯西不等式的简洁证明
  • 2025 最新网架厂家权威排行榜:焊接球 / 螺栓球 / 大跨度等多类型网架实力企业最新推荐
  • WEB集群-HTTP概述与Nginx部署
  • 实战内容
  • 2025 最新无缝钢管厂家推荐榜:国际测评认证 + 技术创新 + 全场景适配权威指南
  • 【Qt开发】多元素类控件(二)-> QTableWidget - 实践
  • BBS伪随机数生成器
  • [KaibaMath]1022 一道平面几何题的两种解法
  • 实用指南:从0开始了解kafka《第二篇 kafka的安装、管理和配置》
  • 动态规划法
  • 函数表达式:JavaScript中那些你不知道的优雅写法 - 教程
  • 11.15模拟赛