一、结构体的定义与使用:
1.定义
在主函数内也可以在主函数外定义,下面是习惯用法:
struct student //定义一个叫做“student”的结构体;
{ //以下是其中各种元素;
char name[22];
char xuehao;
int age;
double mark;
}p[1001]; //给该结构体一个别名“p”,便于使用,且定义为一个结构体数组;
也可以这样:
#include <bits/stdc++.h>
using namespace std;
struct student
{
char name[22];
char xuehao;
int age;
double mark;
}; //此处不写;
int main()
{
struct student p[1001]; //在主函数内进行声明,效果相同;
return 0;
}
2.使用
*先补充一点sort函数的使用基础:
*再补充一点关于正则表达式“%[^\n]”:可用于需要输入带有空格的字符型数组(如英文名),这个表达式用于输入语句,如:
scanf("%[^\n]",&stu[i].name); //意为输入直到键入回车(也就是\n)时停止输入;
还有一点很重要,不能在结构体声明中初始化结构体成员,因为结构体声明只是创建一个新的数据类型,还不存在这种类型的变量。例如,以下声明是非法的:
//非法结构体声明
struct Date
{
int day = 23,
month = 8,
year = 1983;
};
因为结构体声明只声明一个结构体“看起来是什么样子的”,所以不会在内存中创建成员变量。只有通过定义该结构体类型的变量来实例化结构体,才有地方存储初始值。
我们通过一个题目来解释:NEFU OJ:谁考了第k名-排序
代码如下:
#include <bits/stdc++.h>
using namespace std;
struct stu //定义一个结构体;
{ char xuehao[10]; //学号,用字符型数组填数字时最好开大两格以上;
double chengji; //成绩
}p[105]; //别名为“p”,105个元素
bool cmp(stu a,stu b) //定义一个比较方式,名为“cmp”
{
return a.chengji>b.chengji; //排序方式:"<"是升序,">"是降序(可以记箭头方向)
}
int main()
{
int n,k;
cin>>n>>k;
for(int i=0;i<n;i++)
{getchar(); //这里注意使用getchar来防止回车被写入xuehao字符串;
scanf("%s %lf",&p[i].xuehao,&p[i].chengji);}
sort(p,p+n,cmp); //sort的使用:sort(起始地址,最后一个元素的下一个地址,自定义比较函数(可以不填));
//sort默认升序排序,可以用less换成降序排序;
printf("%s %g",p[k-1].xuehao,p[k-1].chengji);
return 0;
}
初学者在使用中要注意,在循环中使用结构体内变量时,格式为:“别名[循环变量]”.“变量名”,不要忘了循环变量。
二、结构体专题练习&题解
1.NEFU OJ:奇数单增序列
//这题比较简单,没什么好说的;
#include <bits/stdc++.h>
using namespace std;
int main()
{
int n;
cin>>n;
int str[n];
for(int i=0;i<n;i++)
cin>>str[i];
int str1[n],k=0;
for(int i=0;i<n;i++)
{
if(str[i]%2!=0)
{
str1[k]=str[i];
k++;
}
}
sort(str1,str1+k);
for(int i=0;i<k;i++)
{
if(i!=k-1)
cout<<str1[i]<<",";
else
cout<<str1[i];
}
return 0;
}
2.NEFU OJ:成绩排序
//也简单;
#include <bits/stdc++.h>
using namespace std;
struct stu
{
char name[22];
int grade;
}p[30];
bool cmp(stu a,stu b)
{
if(a.grade!=b.grade)
return a.grade>b.grade;
else
return a.name<b.name;
}
int main()
{
int n; cin>>n;
for(int i=0;i<n;i++)
{getchar();
scanf("%s %d",&p[i].name,&p[i].grade);}
sort(p,p+n,cmp);
for(int i=0;i<n;i++)
cout<<p[i].name<<" "<<p[i].grade<<endl;
return 0;
}
3.NEFU OJ:没必要的排序2
//这题要注意,排序会超时,得用桶排序
#include <bits/stdc++.h>
using namespace std;
int main()
{
int n,k,x,ans=0,y=0;
cin>>n>>k;
int t[100001]={0}; //定义一个“桶子”;
for(int i=0;i<n;i++)
{
scanf("%d",&x);
t[x]++; //输入该数,则在该桶位加1;
}
for(int i=100000;i>=1;i--)
{
if(t[i]>0)
{
ans=ans+t[i]*i; //加和;
y=y+t[i];
}
if(y>k)
{
ans=ans-(y-k)*i; //减去加多了的数;
break;
}
}
cout<<ans;
return 0;
}
4.NEFU OJ:老和尚的导员
//没啥好说的;
#include <bits/stdc++.h>
using namespace std;
struct hs
{
int num;
int cyy;
int xd;
int gs;
int yy;
int all;
}ren[101];
bool cmp(hs a,hs b)
{
if(a.all!=b.all)
return a.all>b.all;
else
{
if(a.cyy!=b.cyy)
return a.cyy>b.cyy;
else if(a.xd!=b.xd)
return a.xd>b.xd;
else if(a.gs!=b.gs)
return a.gs>b.gs;
else if(a.yy!=b.yy)
return a.yy>b.yy;
}
}
int main()
{
int n;
while(~scanf("%d",&n))
{for(int i=1;i<=n;i++)
{
ren[i].num=i;
scanf("%d %d %d %d",&ren[i].cyy,&ren[i].xd,&ren[i].gs,&ren[i].yy);
ren[i].all=ren[i].cyy+ren[i].xd+ren[i].gs+ren[i].yy;
}
sort(ren+1,ren+n+1,cmp);
for(int i=1;i<=n;i++)
cout<<ren[i].num<<" "<<ren[i].all<<endl;}
return 0;
}
5.NEFU OJ:健忘的老和尚
这题注意:无论是奖励还是惩罚**都按照总成绩从低到高输出**和尚的名字即可。
#include <bits/stdc++.h>
using namespace std;
struct hs
{
char name[110];
int all;
}ren[300];
bool cmp(hs a,hs b)
{
return a.all>b.all;
}
int main()
{
int n,m,s;
while(~scanf("%d %d %d",&n,&m,&s))
{
for(int i=0;i<n;i++)
{getchar();scanf("%s%d",&ren[i].name,&ren[i].all);}
sort(ren,ren+n,cmp);
for(int i=m-1;i>=0;i--)
cout<<ren[i].name<<endl;
for(int i=n-1;i>=n-s;i--)
cout<<ren[i].name<<endl;
}
return 0;
}
6.NEFU OJ:戏说三国
看清楚题目再写!!!智育、德育、武育三个分数,分别以**b%,a%,c%**的比率计入加权总分,不是abc!!!罚时一次20min!
#include <bits/stdc++.h>
using namespace std;
struct sg
{
char name[30];
double zy,dy,wy,all;
}x[1001];
bool cmp(sg a,sg b)
{
if(a.all!=b.all) return a.all>b.all;
else if(a.zy!=b.zy) return a.zy>b.zy;
else if(a.dy!=b.dy) return a.dy>b.dy;
else if(a.wy!=b.wy) return a.wy>b.wy;
}
int main()
{
int m,r=0; cin>>m;
while(m--)
{
int n; double a,b,c;
cin>>n>>a>>b>>c;
a=a/100; b=b/100; c=c/100;
for(int i=0;i<n;i++)
{getchar();scanf("%s %lf %lf %lf",&x[i].name,&x[i].zy,&x[i].dy,&x[i].wy);
x[i].all=x[i].zy*b+x[i].dy*a+x[i].wy*c;
x[i].zy=x[i].zy*b;
x[i].dy=x[i].dy*a;
x[i].wy=x[i].wy*c;}
sort(x,x+n,cmp);
r++;
cout<<"Case #"<<r<<":"<<endl;
for(int i=0;i<n;i++)
printf("%s %.4lf %.4lf %.4lf %.4lf\n",x[i].name,x[i].all,x[i].zy,x[i].dy,x[i].wy);
}
return 0;
}
7.NEFU OJ:相约摩洛哥
多组输入一定要注意累加变量的清零!!
#include <bits/stdc++.h>
using namespace std;
struct sg
{
char name[12];
int t1,t2,t3;
int c1,c2,c3;
int all,ac; //all和ac变量在每次运行后一定要记得清零!
}x[100001];
bool cmp(sg a,sg b)
{
if(a.ac!=b.ac) return a.ac>b.ac;
if(a.ac==b.ac) return a.all<b.all;
}
int main()
{
int n;
while(~scanf("%d",&n))
{
for(int i=0;i<n;i++)
{getchar();
scanf("%s %d %d %d",&x[i].name,&x[i].t1,&x[i].t2,&x[i].t3);}
for(int i=0;i<n;i++)
cin>>x[i].c1>>x[i].c2>>x[i].c3;
for(int i=0;i<n;i++)
{
if(x[i].t1!=-1) {x[i].all=x[i].all+x[i].t1+(x[i].c1-1)*20; x[i].ac++;}
if(x[i].t2!=-1) {x[i].all=x[i].all+x[i].t2+(x[i].c2-1)*20; x[i].ac++;}
if(x[i].t3!=-1) {x[i].all=x[i].all+x[i].t3+(x[i].c3-1)*20; x[i].ac++;}
}
sort(x,x+n,cmp);
for(int i=0;i<n;i++)
{printf("%s %d %d\n",x[i].name,x[i].ac,x[i].all);
x[i].all=0; x[i].ac=0;} //清零操作;
}
return 0;
}
8.NEFU OJ:结构体排序题一
这题要在主函数内进行多次排序,我尝试过把t1,t2赋值到结构体内用选择语句在bool函数内进行比较,但不知道由于什么原因致使输出结果与答案完全相反。
#include <bits/stdc++.h>
using namespace std;
struct px
{
int x,y;
}p[1001];
bool cmp1(px a,px b)
{
if(a.x==b.x) return a.y<b.y;
else return a.x<b.x;
}
bool cmp2(px a,px b)
{
if(a.x==b.x) return a.y>b.y;
else return a.x<b.x;
}
bool cmp3(px a,px b)
{
if(a.x==b.x) return a.y<b.y;
else return a.x>b.x;
}
bool cmp4(px a,px b)
{
if(a.x==b.x) return a.y>b.y;
else return a.x>b.x;
}
int main()
{
int n,i,t1,t2;
while(~scanf("%d%d%d",&t1,&t2,&n))
{
for(i=1;i<=n;i++)
scanf("%d %d",&p[i].x,&p[i].y);
//四种情况,分四种sort即可;
if(t1==1&&t2==1)sort(p+1,p+n+1,cmp1);
if(t1==1&&t2==0)sort(p+1,p+n+1,cmp2);
if(t1==0&&t2==1)sort(p+1,p+n+1,cmp3);
if(t1==0&&t2==0)sort(p+1,p+n+1,cmp4);
for(i=1;i<=n;i++)
printf("(%d,%d)\n",p[i].x,p[i].y);
}
return 0;
}
于2020年1月1日元旦,大一寒假培训第二天,编辑。
来源:CSDN
作者:清风拂山岗AC
链接:https://blog.csdn.net/qq_45830875/article/details/103793567