C进阶题工作室4

本文提供了一系列C语言编程题目,包括结构体输入输出、逆序输出成绩表、日期统计等基础习题,以及灯泡开关和最长山脉等提升题。旨在锻炼和提升C语言编程能力。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、基础习题
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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值