一、基础习题
1、Problem A:输入输出
题目描述
定义一个结构体student,存储学生的学号、名字、性别和年龄,读入每个学生的所有信息,保存在结构体中,并输出。结构体student的定义如下:
struct student {
int num;
char name[20];
char sex;
int age;
};
本题要求使用指向结构体数组进行输入和输出。
输入
第一行有一个整数n,表示以下有n个学生的信息将会输入。保证n不大于20。
以后的n行中,每一行包含对应学生的学号、名字、性别和年龄,用空格隔开。保证每一个人名都不包含空格且长度不超过15,性别用M和F两个字符来表示。
输出
有n行,每行输出一个学生的学号、名字、性别和年龄,用空格隔开。
请注意行尾输出换行。
样例输入
3
10101 LiLin M 18
10102 ZhangFun M 19
10104 WangMin F 20
样例输出
10101 LiLin M 18
10102 ZhangFun M 19
10104 WangMin F 20
#include<stdio.h>
#include<malloc.h>
struct student {
int num;
char name[20];
char sex;
int age;
};
int main(void)
{
int len,i,j;
struct student * pArr;
struct student t;scanf("%d",&len);
pArr=(struct student *)malloc(len * sizeof(struct student));
for(i=0;i<len;++i)
{printf("num name sex age");
scanf("%d%s%s%d",&pArr[i].num,pArr[i].name,pArr[i].sex,&pArr[i].age);
printf("%d\t%s\t%s\t%d\t",pArr[i].num,pArr[i].name,pArr[i].sex,pArr[i].age);}
return 0;
}
或者
#include <stdio.h>
struct student {
int num;
char name[20];
char sex;
int age;
} stu[20], *p;
int main() {
int n;
scanf("%d", &n);
p = stu;
for(int i = 0; i < n; i++) {
scanf("%d %s %c %d", &p->num, p->name, &p->sex, &p->age);
printf("%d %s %c %d\n", p->num, p->name, p->sex, p->age);
}
return 0;
2、Problem B:逆序输出成绩表
题目描述
输入一组学生的成绩,将输入内容逆序输出。
输入
输入格式为每行两个数值,学号N为10位数字,成绩S取值为整数(0≤S≤100)
读取输入直到输入结束(数据总量不超过50行)
输出
输出格式为每行两个数值,学号N之后有一个空格,成绩值的输出宽度占3个位置
样例输入
2017010405 78
2017010426 80
2017010402 61
2017010377 95
样例输出
2017010377 95
2017010402 61
2017010426 80
2017010405 78
```c
#include<stdio.h>
void main()
{
struct {
int num;
int score;
}stu[3];
for(int i=0;i<3;++i)
scanf("%d%d",&stu.num,&stu.score);
for(i=2;i>=0;i--)
printf("%d%d",stu.num,stu.score);
}
或者
#include <stdio.h>
#include <string.h>
const int N = 50 + 5;
typedef struct student{
char no[15];
int score;
}STU;
int main() {
STU stu[N];
int n = 0;
while(scanf("%s%d",stu[n].no,&stu[n].score) != EOF)
n++;
for(int i = n - 1;i >= 0;i--){
printf("%s %3d\n",stu[i].no,stu[i].score);
}
return 0;
}
3、
【结构体】日期统计
题目描述
定义一个包括年、月、日的结构体变量,读入年、月、日,计算该日在当年中是第几天。注意闰年问题。
输入
三个整数,分别表示年、月、日。保证输入是实际存在的日期,且年份在1000至3000之间(包含1000和3000)。
输出
输出该日期是一年中的第几天。
请注意行尾输出换行。
样例输入
2012 12 21
样例输出
356
#include <stdio.h>
struct date {
int year;
int month;
int day;
} date;
int main() {
int sum = 0,tag;
printf("请输入年月日:\n");
scanf("%d,%d,%d", &date.year, &date.month, &date.day);
switch (date.month) { //先计算月份前面的月份有多少天(不考虑闰年)
case 1:
sum = 0;
break;
case 2:
sum = 31;
break;
case 3:
sum = 59;
break;
case 4:
sum = 90;
break;
case 5:
sum = 120;
break;
case 6:
sum = 151;
break;
case 7:
sum = 181;
break;
case 8:
sum = 212;
break;
case 9:
sum = 243;
break;
case 10:
sum = 273;
break;
case 11:
sum = 304;
break;
case 12:
sum = 334;
break;
default:
printf("the month error");
exit(1);
}
//这里可以写一些日的合法判断
sum += date.day; //加上本月的日期数
if(date.year% 400 == 0 || (date.year % 4==0 && date.year % 100 != 0 )) //闰年
tag = 1;
else
tag = 0;
if(tag == 1 && date.month > 2) //是闰年 月份大于2月 天数加一天
sum++;
printf("这天是当年的第 %d 天。\n",sum);
}
或者
#include<stdio.h>
int main( ){
struct dd{
int y,m,d;
}date;
int i,j,k;
scanf("%d%d%d",&date.y,&date.m,&date.d);
k=date.d;
if(date.m>1) k+=31;
if(date.m>2) k+=28;
if(date.m>3) k+=31;
if(date.m>4) k+=30;
if(date.m>5) k+=31;
if(date.m>6) k+=30;
if(date.m>7) k+=31;
if(date.m>8) k+=31;
if(date.m>9) k+=30;
if(date.m>10) k+=31;
if(date.m>11) k+=30;
if(date.y%4==0&&date.y%100!=0||date.y%400==0) k++;
printf("%d",k);
}
二、提升题
1:灯泡开关
初始时有 n 个灯泡关闭。 第 1 轮,你打开所有的灯泡。 第 2 轮,每两个灯泡你关闭一次。 第 3 轮,每三个灯泡切换一次开关(如果关闭则开启,如果开启则关闭)。第 i 轮,每 i 个灯泡切换一次开关。 对于第 n 轮,你只切换最后一个灯泡的开关。 找出 n 轮后有多少个亮着的灯泡。
示例:
输入: 3
输出: 1
解释:
初始时, 灯泡状态 [关闭, 关闭, 关闭].
第一轮后, 灯泡状态 [开启, 开启, 开启].
第二轮后, 灯泡状态 [开启, 关闭, 开启].
第三轮后, 灯泡状态 [开启, 关闭, 关闭].
你应该返回 1,因为只有一个灯泡还亮着。
#include <stdio.h>
int main()
{
int n,k;
scanf("%d %d",&n,&k);
int a[n+1] = {0}; //0为开灯
for(int i = 2;i <= k;i ++){
for(int j = i;j <= n;j += i){
if(a[j] == 0) a[j] = 1;
else if (a[j] == 1) a[j] = 0;
}
}
for(int l = 1;l <= n;l ++){
if(a[l] == 0) printf("%d ",l);
}
return 0;
}
或者
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
int main(){
//输入案例:8
printf("%d\n", sqrt(8.0));//sqrt():函数需要输入浮点型,你们可以利用强制转换
system("pause");
return 0;
}
2:数组中的最长山脉
我们把数组 A 中符合下列属性的任意连续子数组 B 称为 “山脉”:
• B.length >= 3
• 存在 0 < i < B.length - 1 使得 B[0] < B[1] < … B[i-1] < B[i] > B[i+1] > … > B[B.length - 1]
(注意:B 可以是 A 的任意子数组,包括整个数组 A。)
给出一个整数数组 A,返回最长 “山脉” 的长度。
如果不含有 “山脉” 则返回 0。
示例 1:
输入:[2,1,4,7,3,2,5]
输出:5
解释:最长的 “山脉” 是 [1,4,7,3,2],长度为 5。
示例 2:
输入:[2,2,2]
输出:0
解释:不含 “山脉”。
#include<stdio.h>
#define n 7
void main()
{
int i,j,a[n],m=0,q=0;
for(i=0;i<n;++i)
scanf("%d",&a[i]);
for(i=0;i<n;++i){
if(a[i]<a[i+1])m++;
if(m>0)
if(a[i]>a[i+1])q++;}
if(q==0)printf("0");
else printf("%d",m+q);
}
或者
#include<stdio.h>
#include<stdlib.h>
int max(int a, int b){
return a > b ? a : b;
}
int main(){
//输入案例:[2,1,4,7,3,2,5]
//输出:5
//这个答案不是暴力解法,是用了一种算法解决的,你们有兴趣的可以看看这个代码
int a[] = { 2, 1, 4, 7, 3, 2, 5 };
int n = 7;
int ans = 0;
int left = 0;
int right;
while (left + 2 < n){
right = left + 1;
if (a[left] < a[left + 1]){
while (right < n - 1 && a[right] < a[right + 1]){
right++;
}
if (right < n - 1 && a[right] > a[right + 1]){
while (right < n - 1 && a[right] > a[right + 1]){
right++;
}
ans = max(ans, right - left + 1);
}
else{
right++;
}
}
left = right;
}
printf("%d\n", ans);
system("pause");
return 0;
}