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) { ... } 大括号后面不要加 ;
ifwhile 条件括号后 ❌ 不加 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;
}

更多推荐