C++结构体入门刷题记录~(持续更新)
1结构体
题目描述
要求定义一个结构体数组,包含年月日,表示每一个人的出生日期。然后对出生日期由小到大排序,并输入排序后的结果。
输入
第一行输入t表示有t个出生日期
每行输入三个整数,分别表示年、月、日
依次输入t个实例
输出
按照从小到大的顺序依次输出出生日期。
#include<iostream>
#include<algorithm>
using namespace std;
struct date{
int year;
int month;
int day;
};
bool cmp(date a,date b)//we want to set the rules for sort,so using bool
{
if(a.year!=b.year)
{
return a.year<b.year;
}//ascending order
else if(a.month!=b.month)
{
return a.month<b.month;
}
else
{
return a.day<b.day;
}
}//ATTENTION:struct and fuction'd set ouside the main fuction
int main()
{
int t;
cin>>t;
date arr[1000];//so we input the array,because it's convenient
for(int i=0;i<t;i++)//so smart to let the for to input
{
cin>>arr[i].year>>arr[i].month>>arr[i].day;
}
sort(arr,arr+t,cmp);
for(int j=0;j<t;j++)
{
cout<<arr[j].year<<" "<<arr[j].month<<" "<<arr[j].day<<endl;
}
return 0;
}
2还是结构体
输入队伍ID ,根据做出的题目进行排序。

#include<iostream>
#include<algorithm>
using namespace std;
struct acm
{
long long id;
int score;
};
bool cmp(acm a,acm b)
{
return a.score>b.score;//descending order
}
int main()
{
int t;
cin>>t;
acm arr[1000];
for(int i=0;i<t;i++)
{
cin>>arr[i].id>>arr[i].score;
}
stable_sort(arr,arr+t,cmp);//保证相等元素维持原本的相对顺序,正好符合“题数相等,保持输入顺序”的要求
for(int j=0;j<t;j++)
{
cout<<"队伍id:"<<arr[j].id <<" "
<<"做出题目数为:"<<arr[j].score<<endl;
}
return 0;
}
问题一(硬伤):输出格式不符合题目要求
题目要求的输出格式是:
ID M
cout << "队伍id:" << arr[j].id << " " << "做出题目数为:" << arr[j].score << endl;
这会输出中文提示文字,OJ 判题是严格按字符比对的,多一个字、少一个字都会判错。
必须改成:
cout << arr[j].id << " " << arr[j].score << endl;
问题二(隐患):数组大小可能不够
题目描述里 N 的范围是 1 < N ≤ 10000,而你定义的数组是:
acm arr[1000]; // 最多只能装 1000 个
如果测试数据有 10000 个队伍,你的程序会越界崩溃。
建议改成:
acm arr[10001]; // 多留一个空间,安全
修改后:
#include<iostream>
#include<algorithm>
using namespace std;
struct acm
{
long long id;
int score;
};
bool cmp(acm a,acm b)
{
return a.score>b.score;//descending order
}
int main()
{
int t;
cin>>t;
acm arr[10001];
for(int i=0;i<t;i++)
{
cin>>arr[i].id>>arr[i].score;
}
stable_sort(arr,arr+t,cmp);//保证相等元素维持原本的相对顺序,正好符合“题数相等,保持输入顺序”的要求
for(int j=0;j<t;j++)
{
cout<<arr[j].id<<" "<<arr[j].score<<endl;
}
return 0;
}
3结构体指针
题目描述
已知一群学生的考试试卷,要求对试卷内容进行对比,查找是否有抄袭。
每张试卷包含:学号(整数类型)、题目1答案(字符串类型)、题目2答案(字符串类型)、题目3答案(字符串类型)
要求:使用结构体来存储试卷的信息。定义一个函数,返回值为一个整数,参数是两个结构体指针,函数操作是比较两张试卷的每道题目的答案,如果相同题号的答案相似度超过90%,那么就认为有抄袭,函数返回抄袭题号,否则返回0。相似度是指在同一题目中,两个答案的逐个位置上的字符两两比较,相同的数量大于等于任一个答案的长度的90%,就认为抄袭。
输入
第一行输入t表示有t张试卷
第二行输入第1张试卷的学生学号
第三行输入第1张试卷的题目1答案
第四行输入第1张试卷的题目2答案
第五行输入第1张试卷的题目3答案
每张试卷对应4行输入
依次输入t张试卷的数据
输出
在一行中,把发现抄袭的两个学号和题目号,数据之间用单个空格隔开
如果发现是题目1抄袭,题目号为1,以此类推
输出顺序按照输入的学号顺序进行输出
一、问题:
代码里写了好几个 return,最后还有个 return 0,会不会每个 return 都执行一遍?
答案:
绝对不会。return 的作用是立即结束当前函数,并把后面的值交还给调用者。
一旦执行到任何一个 return,函数就当场退出,后面的所有代码都不会再执行。
问题:
代码里写了好几个 return,最后还有个 return 0,会不会每个 return 都执行一遍?
答案:
绝对不会。return 的作用是立即结束当前函数,并把后面的值交还给调用者。
一旦执行到任何一个 return,函数就当场退出,后面的所有代码都不会再执行。
二、struct* 和 *struct 的区别
前者是定义指针,后者是解引用
#include<iostream>
#include<string>
using namespace std;
struct paper
{
int id;
string ans1;
string ans2;
string ans3;
};
bool similar(string s1,string s2)//辅助函数帮助判断是否90%
{
//比较二者的长度,达到较短的长度时就停止比较
//先设出二者长度,为后面的循环提供上限
//还有一个作用是90%需要比较相同数和长度len
int len1=s1.length();
int len2=s2.length();
int minlen=0;
if(len1<len2)
{
minlen=len1;
}
else
{
minlen=len2;
}
//一个一个字符比较,涉及循环;统计出相同字符数,涉及统计就要设出来
int same=0;
for(int i=0;i<minlen;i++)
{
if(s1[i]==s2[i])//判断条件记得==
{
same++;//有一个相同就加一,计算机就是递加的过程
}
}
//统计完了,就看有没有超标了
//一般是 same>0.9*len,但是浮点不方便,同乘以10
if(same*10>=9*len1||same*10>=9*len2)
{
return true;
}
else
{
return false;
}
//题目要求的函数,把上面bool函数当作条件,成立则返回相应题号
}
int checkcopy(paper* p1,paper* p2)
{
if(similar(p1->ans1,p2->ans1))
{
return 1;
}
if(similar(p1->ans2,p2->ans2))
{
return 2;
}
if(similar(p1->ans3,p2->ans3))
{
return 3;
}
return 0;
}
int main()
{
int t;
cin>>t;
paper arr[1000];
for(int i=0;i<t;i++)
{
cin>>arr[i].id;
cin>>arr[i].ans1;
cin>>arr[i].ans2;
cin>>arr[i].ans3;
}
for(int i=0;i<t;i++)//双重循环才能对所有进行两两比较!!!
{
for(int j=i+1;j<t;j++)
{
int problem = checkcopy(&arr[i],&arr[j]);
if(problem!=0)
{
cout<<arr[i].id<<" "<<arr[j].id<<" "<<problem<<endl;
}
}
}
return 0;
}
4结构体
题目描述
用具有x,y两个整型变量成员的结构类型SPoint来表示坐标点。用SRect结构类型来描述矩形,其中包含p1和p2两个SPoint成员分别表示矩形对角线上的两个点。
编写判断两个矩形是否重叠的函数bool isoverlap(const SRect &rect1, const SRect &rect2)。
主函数输入两个矩形,调用isoverlap函数判断是否重叠。
输入
判断次数
矩形1的对角线顶点坐标x1、y1、x2、y2
矩形2的对角线顶点坐标x1、y1、x2、y2
......
输出
是否重叠


#include<iostream>
using namespace std;
//1,设出结构体,点集和矩形集
struct SPoint
{
int x; //struct needs ;;;;;!
int y;
};
struct SRect
{
SPoint p1;
SPoint p2;
};
//2,编写判断矩形是否重叠的函数
bool isoverlap(const SRect &rect1, const SRect &rect2)
{
//对矩形一找到它的边界,所以都是rect1 ,对比p1p2
int left1,right1,top1,bottom1;
//左边界找x较小的,右则找较大的
left1= rect1.p1.x<rect1.p2.x?rect1.p1.x:rect1.p2.x;
right1= rect1.p1.x>rect1.p2.x?rect1.p1.x:rect1.p2.x;
//上边界找y较大的,下则小
bottom1=rect1.p1.y<rect1.p2.y?rect1.p1.y:rect1.p2.y;
top1=rect1.p1.y>rect1.p2.y?rect1.p1.y:rect1.p2.y;
//同理矩形2,只需将rect1改为rect2 即可
int left2,right2,top2,bottom2;
left2= rect2.p1.x<rect2.p2.x?rect2.p1.x:rect2.p2.x;
right2= rect2.p1.x>rect2.p2.x?rect2.p1.x:rect2.p2.x;
bottom2=rect2.p1.y<rect2.p2.y?rect2.p1.y:rect2.p2.y;
top2=rect2.p1.y>rect2.p2.y?rect2.p1.y:rect2.p2.y;
//比较四种不重叠的情况,其余均重叠
//但比较后要return什么呢,根据bool应该是t/f
if(left1>right2) //但多数题目(包括你本题的隐含要求)认为“有公共点就算重叠”。
{
return false;
}
if(left2>right1)
{
return false;
}
if(bottom1>top2)
{
return false;
}
if(bottom2>top1)
{
return false;
}
return true;
}
int main()
{
int t;
cin>>t;
/*while(n--)//n减到0的时候为假,循环停止
{
SRect r1,r2;
cin>>r1.p1.x>>r1.p1.y>>r1.p2.x>>r1.p2.y;
cin>>r2.p1.x>>r2.p1.y>>r2.p2.x>>r2.p2.y;
//bool就相当于一个表达式,真则重叠
//cout<<(isoverlap(r1,r2)?"overlapped":"not overlapped")<<endl;//必须把整个三目运算括起来
//为了符合全部输入再输出,使用数组
}
return 0;*/
SRect r1[1000],r2[1000];//数组定义在外面,才能在第一个循环储存数据,然后实现一起输出!!!
for(int i=0;i<t;i++)
{
cin>>r1[i].p1.x>>r1[i].p1.y>>r1[i].p2.x>>r1[i].p2.y;
cin>>r2[i].p1.x>>r2[i].p1.y>>r2[i].p2.x>>r2[i].p2.y;
}
for(int j=0;j<t;j++)
{
cout<<(isoverlap(r1[j],r2[j])?"overlapped":"not overlapped")<<endl;//必须把整个三目运算括起来
}
return 0;
}
5,指针交换和引用交换
题目描述
首先使用传递指针参数的函数swap1()实现两数据的交换,
再使用传递引用参数的函数swap2()实现两数据的交换
#include<iostream>
using namespace std;
void swap1(int*a,int*b)//不用int因为return只能传递一个值
{
int tem= *a;
*a=*b;
*b=tem;
};
void swap2(int&a,int&b)//用了&后面就不用了,已经说明它的身份
{
int tem=a;
a=b;
b=tem;
};
int main()
{
/*int a1,b1;
cin>>a1>>b1;
int a2,b2;
a2=swap1(&a1,&b1);
b2=swap2(a1,b1);
cout<<"swap1:"<<a2<<endl
<<"swap2:"<<b2<<endl;*/
/*void 函数不能赋值给变量a2 = swap1(...) 和 b2 = swap2(...) 都是非法的,
因为 swap1、swap2 没有返回值。你想要的其实是交换后的 a1 和 b1 的值,它们已经被函数直接修改了,直接使用 a1、b1 即可。*/
int a1,b1;
cin>>a1>>b1;
swap1(&a1,&b1);
cout<<"swap1:"<<a1<<" "<<b1<<endl;//必须分开交换,不然先交换两次再输出又变一样了,注意顺序
swap2(a1,b1);
cout<<"swap2:"<<a1<<" "<<b1<<endl;
return 0;
}
6引用访问数组元素
题目描述
输入n,输入n个数,计算n个数的和并输出。
主函数定义如下,请补齐put函数。
输入
测试次数
每组测试数据一行,正整数n(1~1000),后跟n个整数。
输出
每组测试数据输出一行,即n个整数的和。
#include <iostream>
using namespace std;
#define N 1000
// 补齐put函数
/********** Write your code here! **********/
/*******************************************/
int main()
{
int num[N];
int t, n, sum, i;
cin >> t;
while (t--)
{
cin >> n;
for (i = 0; i < n; i++)
{
cin >> put(num, i);
// 输入num[i]的值,暗示我们要写的put函数,就是输入num,i返回一个数组,又因为函数返回如果是值的话不能被输入,所以改成引用数组就可以输入了,因为引用是个变量!
}
for (sum = 0, i = 0; i < n; i++)
sum += num[i];
cout << "sum=" << sum << endl;
}
return 0;
}
答案:
int& put(int arr[],int i)
{
return arr[i];
}
7何时要加;
分号 ; 和逗号 , 使用速查表
| 场景 | 正确符号 | 例子 | 说明 |
|---|---|---|---|
| 普通语句结尾 | ; |
int a = 10; |
一句话说完就要写分号 |
| 结构体成员 | ; |
int x; int y; |
成员之间用分号隔开,不能用逗号 |
| for 循环三部分 | ; |
for(int i=0; i<10; i++) |
两个分号隔开初始化、条件、迭代 |
do-while 结尾 |
; |
while(条件); |
这个分号不能忘 |
| 函数声明(原型) | ; |
int func(int x); |
只声明不定义时结尾加分号 |
| 函数定义 | ❌ 不加 | int func(int x) { ... } |
大括号后面不要加 ; |
if, while 条件括号后 |
❌ 不加 | if(x>0) { } |
括号后直接跟语句或大括号 |
| 声明多个同类型变量 | , |
int a, b, c; |
用逗号分隔变量名 |
| 函数参数列表 | , |
void f(int x, int y) |
参数之间用逗号 |
| 初始化列表 | , |
int arr[3] = {1, 2, 3}; |
值之间用逗号 |
| 结构体初始化 | , |
Point p = {1, 2}; |
按成员顺序逗号分隔 |
| 多表达式语句 | , |
a=1, b=2; |
一行多个赋值(较少用) |
cin/cout 连续输入输出 |
>> / << |
cin >> a >> b; |
这不需要分号或逗号,用 >> 连接 |
// ❌ 错误:结构体成员用逗号
struct Point {
int x,
int y
};
// ✅ 正确:用分号
struct Point {
int x;
int y;
};
// ❌ 错误:for 循环头用逗号
for (int i = 0, i < n, i++)
// ✅ 正确:用分号
for (int i = 0; i < n; i++)
8结构体
题目描述
分数的分子和分母可用一个结构类型来表示。
编写实现两个分数加(addFS),减(subFS),乘(mulFS),除(divFS)的函数(要求计算结果分数是简化的),以及打印一个分数(printFS),计算两个整数最大公约数的函数(getGCD)。
#include<iostream>
using namespace std;
#include<cstdlib>
struct fraction
{
int num;
int den;
};
//因为公约数是前提,所以先写公约数
int getGCD(int a,int b)//辗转相除法
{
//循环
while(b!=0)
{
//%
int r=a%b;
//交换
a=b;
b=r;
}
return a;
}
//写的顺序看需求,比如我现在想写加减乘除的,那就需要得到已经化到最简的分数进行运算
//用什么类型?应该返回两个数,所以是struct
fraction simplfy(fraction f)
{
if(f.num==0)
{
return f;
}
//分母为绝对值
int com=abs(getGCD(f.num,f.den));
//上下同除最大公约数
f.num=f.num/com;
f.den=f.den/com;
//处理正负数
//负数时,把分母的负数转化为分子的负数,不然在数学意义上除以一个负数不合理
if(f.den<0)
{
f.num=-f.num;//分子变负
f.den=-f.den;//分母变正
}
return f;
}
//+
fraction addFS(fraction a,fraction b)
{
fraction c;//因为只能传一个值,好聪明呀
c.den=a.den*b.den;
c.num=a.num*b.den+b.num*a.den;
//simplfy(c) ;
return simplfy(c);
}
//-
fraction subFS(fraction a,fraction b)
{
fraction c;
c.den=a.den*b.den;
c.num=a.num*b.den-b.num*a.den;
//simplfy(c) ;这样无法返回
return simplfy(c);//不然return的值会飘走!!!
}
//*
fraction mulFS(fraction a,fraction b)
{
fraction c;
c.den=a.den*b.den;
c.num=b.num*a.num;
//simplfy(c) ;
return simplfy(c);
}
///
fraction divFS(fraction a,fraction b)
{
fraction c;
c.den=a.den*b.num;
c.num=a.num*b.den;
//simplfy(c) ;
return simplfy(c);
}
void printFS(fraction a)
{
if(a.den==1)
{
cout<<a.num<<endl;
}
else
{
cout<<a.num<<"/"<<a.den<<endl;
}
}
int main()
{
int t;
cin>>t;
char slash;//为了接受/的输入
fraction add[1000],sub[1000],mul[1000],div[1000];
/*while(t--)
{
fraction a,b;
cin>>a.num>>slash>>a.den;
cin>>b.num>>slash>>b.den;
add[t]=addFS(a,b);
sub[t]=subFS(a,b);
mul[t]=mulFS(a,b);
div[t]=divFS(a,b);//这样就可以两两分别运算,不重叠,并且存好数据
}
while(t--)
{
printFS(add[t]);
printFS(sub[t]);
printFS(mul[t]);
printFS(div[t]);
}*/
//不可以用两次while,t在第二次循环就是负数了
for(int i=0;i<t;i++)
{
fraction a,b;
cin>>a.num>>slash>>a.den;
cin>>b.num>>slash>>b.den;
add[i]=addFS(a,b);
sub[i]=subFS(a,b);
mul[i]=mulFS(a,b);
div[i]=divFS(a,b);
}
for(int i=0;i<t;i++)
{
printFS(add[i]);
printFS(sub[i]);
printFS(mul[i]);
printFS(div[i]);
cout<<endl;
}
return 0;
}
9
题目描述
定义一个结构体,包含年月日,表示一个学生的出生日期。然后在一群学生的出生日期中找出谁的出生日期排行第二
要求:出生日期的存储必须使用结构体,不能使用其他类型的数据结构。
要求程序全过程对出生日期的输入、访问、输出都必须使用结构。
#include<iostream>
#include<algorithm>
using namespace std;
struct birth
{
int year;
int month;
int day;
};
bool cmp(birth a,birth b)
{
if(a.year!=b.year)
{
return a.year<b.year;
}
else
{
if(a.month!=b.month)
{
return a.month<b.month;
}
else
{
if(a.day!=b.day)
{
return a.day<b.day;
}
}
}
}
int main()
{
int t;
cin>>t;
birth arr[1000];
for(int i=0;i<t;i++)
{
cin>>arr[i].year>>arr[i].month>>arr[i].day;
}
sort(arr,arr+t,cmp);
cout<<arr[1].year<<"-"<<arr[1].month<<"-"<<arr[1].day<<endl;
//易错:代码从0开始,老二是1!
return 0;
}
更多推荐



所有评论(0)