Bootstrap

C语言编程基础之知识总结

C语言编程基础之知识总结


前言

小编学习C语言也有一段时间啦,这一篇博客就来总结一下所学的知识以及做过的一些程序,作为一个学习路上的小小印记吧。

一、C语言基础思维导图

在这里插入图片描述

二、打卡机制作

1、设计要求
应市场需求,某工程师现设计了一款新上下班打卡机,打卡机具有以下功能:
(1)上班打卡,员工具有编号(首位为 1 的六位编号),输入编号后,再输入校验码,校验码生成规则:员工编号除首位反序,再与员工编号和,如:员工编号,110086,校验码为 178087。校验码错误即打卡失败。记录打卡时间 。
(2)下班打卡,只需输入员工编号即可。记录打卡时间,显示该人员今天上班时长,如果上班时长不够,显示早退 xx 分钟。可以更新下班打卡时间。无下班打卡显示缺卡。
(3)可以设置规定上班时长,如 9 小时
(4)测试需要可以规定 6 秒=实际 1 小时,每次测试,输入指令后,开启打卡机,打卡机开启模拟时间为:周一早上七点。程序运行结束为周五晚 12 点。
(5)实行弹性打卡制,如前一天上班时长超过规定时长 3 小时以上,第二天迟到 2 小时以内不算迟到。
(6)打卡机运行结束之前,每周该打卡机会生成每周考勤周报,显示周平均上班时长,周迟到,早退,缺卡次数等。
要求:合理定义所需函数,主函数中只允许有 clockin_machine_start() 调用。

2、设计思路
在这里插入图片描述
代码实现

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
//测试说明:程序执行一次为一天,上班打卡-下班打卡操作需要执行五次才能输出周报
//声明函数
void get_startwork_time();//获得上班时间
void show_startwork_time();//展示上班时间
void gettime_knock_off();//得到下班时间
void showtime_knock_off();//展示下班时间
//定义结构体,用来储存数据
struct member 
{
	int number;//员工编号
	int staff_code;//校验码
	int hour;//上班时
	int minute;//上班分
	int sec;//上班秒
	int hour_back;//下班时
	int minute_back;//下班分
	int sec_back;//下班秒
}member1;
//定义全局变量
static double working_time,worktime;//工作时间
static int timelate,leave_early,lack_punch_card;//迟到,早退,缺卡
static int buffer_mechanism;

void clockin_machine_start()//主函数部分
{
	
	int staff_code=0,staff_number=0,staff_number_2=0;
    printf("[tips:110086]\n请输入员工编号:");
	scanf("%d",&staff_number);           //staff_number=110086
    member1.number = staff_number;       //将员工编号传给结构体
    staff_number_2=staff_number-100000; //staff_number_2=10086
	while (staff_number_2)             //迭代算法 10086->68001
	{
		staff_code=staff_code*10+staff_number_2%10;
        staff_number_2=staff_number_2/10;
	}
    staff_code=staff_code+staff_number;//staff_code=178087
    member1.staff_code = staff_code;	//将得到的校验码传给结构体
    int verification_code= 0;//定义输入验证码变量
    printf("[tips:178087]\n请输入验证码:");
	scanf("%d",&verification_code);
    while(member1.staff_code != verification_code)//判断输入是否正确,直到输入成功为止->扩展(未实现):三次输入机会,不然就打卡失败。
	{
		printf("校验码错误,请重新输入:");
		scanf("%d",&verification_code);
	}
	printf("正确,打卡成功!\n");
	printf("---------------------------------\n");
	//获取当前上班时间,并传递给结构体
	get_startwork_time();
	//向用户展示当前上班时间和是否迟到
	show_startwork_time();
	printf("---------------------------------\n");
	//下班要求用户输入员工编号完成打卡
	printf("下班请打卡:\n");
	printf("[tips:110086]\n请输入员工编号:\n");
	int number_back = 0;//定义输入变量
	int number = member1.number;//从结构体数据,获取一次员工编号
	do
	{
	   scanf("%d",&number_back);
		if (number_back != member1.number)//判断是否与之前输入的相等,若不相等则重新要求用户输入
		{
			printf("编号错误,请重新输入!\n");
		}
	}while(member1.number != number_back);
	gettime_knock_off();//获取下班时间,并传递给结构体
	if(member1.hour_back == 0)//若没有下班时间,则显示缺卡,且缺卡次数加一,否则显示下班时间、当天的工作时长、是否实行缓冲机制
	{
		printf("缺卡!\n");
		lack_punch_card++;
	}
	else{
		showtime_knock_off();
	}
	printf("---------------------------------\n");
}
//自定义子函数部分
void get_startwork_time()//获取系统时间函数作为上班打卡时间点
{
	//获取上班时间
	time_t t;
	struct tm* It;
	time(&t);
	It = localtime(&t);
	//将时间传递给结构体
	member1.hour = It->tm_hour;
	member1.minute = It->tm_min;
	member1.sec = It->tm_sec;
	//展示当前时间
	printf("当前时间:%d年%d月%d日 星期%d %d:%d:%d\n",(1900 + It->tm_year),(1 + It->tm_mon),It->tm_mday,It->tm_wday,It->tm_hour, It->tm_min, It->tm_sec);
}
void show_startwork_time()//展示上班时间,统计记录时间信息
{
	//展示员工编号和上班时间
	printf("员工编号:%d\n",member1.number);
	printf("上班时间:%d:%d:%d\n",member1.hour,member1.minute,member1.sec);
	//上班时间为7点前,在7点到9点之间属于迟到,9点后属于缺卡
	//如果触发了缓冲机制,则判断上班时间是不是迟到两小时内
	if(member1.hour >= 9)
	{
		printf("上午缺卡\n");
		lack_punch_card++;//缺卡+1次
	}
	else if(member1.hour < 9 && member1.hour >= 7)
	{
		printf("您迟到了!\n");
		printf("迟到:%d小时%d分钟\n",(member1.hour-7),member1.minute);//展示迟到时长
		timelate++;//迟到+1次
	}
	else if(member1.hour < 7 )
	{
		printf("上班打卡成功!\n");
	}
	else
	{
		printf("上班打卡成功!\n");
	}
}

void gettime_knock_off()//获取下班时间
{
	time_t t;
	struct tm* It;
	time(&t);
	It = localtime(&t);
	//下班时间传递给结构体
	member1.hour = It->tm_hour;
	member1.minute = It->tm_min;
	member1.sec = It->tm_sec;
	//方便调试,6秒钟等于1小时
	
   //ti->tm_sec = ti->tm_sec*600;
	
	//member1.hour_back = ti->tm_hour + ((ti->tm_sec - member1.sec));
	printf("---------------------------------\n");
	//展示当前时间
	printf("当前时间:%d年%d月%d日 星期%d %d:%d:%d\n",(1900 + It->tm_year),(1 + It->tm_mon),It->tm_mday,It->tm_wday,It->tm_hour, It->tm_min, It->tm_sec);
}

void showtime_knock_off()
{
	
	printf("员工编号:%d\n",member1.number);//展示员工编号,下班时间,打卡成功
	printf("下班时间:%d:%d:%d\n",member1.hour_back , member1.minute_back , member1.sec_back);
	printf("下班打卡成功!\n");
	//worktime += (member1.hour_back - member1.hour)*60 + (member1.minute_back - member1.minute);//累计每天的上班时间,在周报里展示
	//将上班时长传给结构体
	//member1.worktime += worktime;
	//printf("work=%d",worktime);
	//上班时长为9小时
	int time = 9;
	//获得用户上班时长
	int tmp = member1.hour_back - member1.hour;
	switch(tmp){
		//上班时长为0\1\2\3\4\5\6\7小时的用户
		case 0:
		case 1:
		case 2:
		case 3:
		case 4:
		case 5:
		case 6:
		case 7:
			//上班时间刚好为n小时
			if(member1.minute_back == member1.minute)
			{
				printf("早退:%d小时%d分钟\n",(time - (member1.hour_back - member1.hour)),member1.minute - member1.minute_back);
			}
			//上班时间不足n小时
			else if(member1.minute_back < member1.minute)
			{
				printf("早退:%d小时%d分钟\n",time - (member1.hour_back - member1.hour),member1.minute - member1.minute_back);
			}
			//上班时间超过n小时,但不足n+1小时
			else
			{
				printf("早退:%d小时%d分钟\n",(time - (member1.hour_back - member1.hour)) , 60 - (member1.minute_back - member1.minute));
			}
			//以上时段都为早退,则早退次数加一
			leave_early++;
			break;
		case 8:
			//上班时间不足8小时
			if(member1.minute > member1.minute_back)
			{
				printf("早退:%d小时%d分钟\n",time - 1 , member1.minute - member1.minute_back);
			}
			//上班时间刚好或超过8小时
			else
			{
				printf("早退:%d分钟\n",(member1.minute + (60 - member1.minute_back)));
	       	}
	       	//为早退,早退次数加一
			leave_early++;
			break;
	 	case 9:
			//上班时间不足9小时,为早退,早退次数加一
			if(member1.minute > member1.minute_back){
				printf("早退:%d\n",member1.minute - member1.minute_back);
				leave_early++;
			}
			//上班时长超过9小时,正常下班,打印上班时长
			else
			{
				printf("上班时长:%d小时%d分钟\n",time , member1.minute_back - member1.minute);
			}
			break;
		case 10:
		case 11:
		case 12:
			//上班时长还没超过缓冲机制时间
			if(member1.minute > member1.minute_back)
			{
				printf("上班时长:%d小时%d分钟\n",member1.hour_back - member1.hour - 1 , 60 - member1.minute + member1.minute_back);
			}
			else
			{
				printf("上班时长:%d小时%d分钟\n",member1.hour_back - member1.hour , member1.minute_back - member1.minute);
			}
			break;
		case 13:
		case 14:
		case 15:
		case 16:
			//上班时长超过缓冲机制时间
			if(member1.minute > member1.minute_back)
			{
				printf("上班时长:%d小时%d分钟\n",member1.hour_back - member1.hour - 1 , 60 - member1.minute + member1.minute_back);
			}
			else{
				printf("上班时长:%d小时%d分钟\n",member1.hour_back - member1.hour , member1.minute_back - member1.minute);
				buffer_mechanism = 1;
				printf("上班时长超过3小时及以上,第二天迟到2小时以内不算迟到!\n");
			}
			break;
		//工作超过17小时的属于下午缺卡
		default:
			printf("下午缺卡!\n");
			lack_punch_card++;
	}			
}

int main(int argc,char *argv[])
{
	//累加上班天数,一周五天
	int j=6;
	for(int i=0;i<j;i++)
	{
	 clockin_machine_start();
	}
	//计算平均上班时长
	worktime = (worktime / 5) / 60;
	//打印周报
	printf("打卡周报:\n");
	printf("上班平均时长:%f小时\n",working_time);//功能未实现
	printf("周迟到数:%d次\n",timelate);
	printf("早退次数:%d次\n",leave_early);
	printf("缺卡次数:%d次\n",lack_punch_card);
	return 0;
}

这是个基础版的打卡机,还有一些bug,有待进一步改善…

三、日历实现

设计要求:
编写一个日历程序
以1990年为基准(1990年第一天为星期一),要求输入一个年月,输出对应月份的日历表
技能目标:
综合运用循环、判断分支结构,对程序进行格式化输入、输出,结构化编程

#include<stdio.h>
#include<stdlib.h>

int mon[2][13] = { { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
{ 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 } };
//判断闰年,是闰年,如果是返回1,不是返回0
int isleap(int year)
{
    if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0)
        return 1;
    else
        return 0;
}
//年份的第一天
int first_day_of_year(int year)
{
    int base_year = 1990;  //定义一个基准年1990年
    int first_day = 1;     //基准天:1990年1月1号是星期1
    int i = 0;
    int total = 0;          //天数总和
    for (i = base_year; i < year; i++)
    {
        total = total + 365 + isleap(i);  //isleap函数用于判断年份是否是闰年,如果是返回1,不是返回0
    }
    return (total+first_day)%7;
}
//月份第一天
int first_day_of_month(int year, int month, int first_year)
{
    int total = 0;  //天数和
    int i = 0;
    for(i = 1; i < month; i++)
    {
        total = total + mon[isleap(year)][i];
    }
    return (total + first_year) % 7;
}
//展示日历
void show(int year,int  month, int first_month)
{
    int i = 0;
    printf("一   二   三   四   五   六  日\n");
    for (i = 0; i < first_month-1; i++)
    {
        printf("     ");     //月份第一天是从first_month开始的,所以首先打印first_month-1个空格
    }
    for (i = 1; i <= mon[isleap(year)][month]; i++)
    {
        printf("%-5d", i);
        if ((first_month-1+i) % 7 ==0) //如果(数字+空格数)%7==0,则换行
            printf("\n");
    }
    printf("\n");
}
int main()
{
    int year, month;
    printf("请按以下格式输入年月:year/month:");  //输入你想打印的年份
    scanf("%d/%d", &year, &month);
    printf("%d年%d月:\n",year, month);
    int first_year = first_day_of_year(year);//年份第一天
    int first_month = first_day_of_month(year, month, first_year);//月份第一天
    show(year, month, first_month);
    system("pause");
    return 0;
}

运行结果
在这里插入图片描述

四、数字排序

设计要求:
写一段程序,将3,1,5,6,7这5个数进行排序,排序方式不限,形式不限、运用学习的基本变量、基本运算、基本结构的知识完成。


#include<stdio.h>
//将数字由小到大依次输出
int main()
{
    int i,j,a[5] = {3,1,5,6,7};//将五个数进行比较,从小到大排序
    for ( i = 0; i < 4; i++)//两个数之间比较,需要比较5-1次
    {
        if(a[i]>a[i+1])//将两个数比较,前面一个数比后面一个数大就进行值交换
        {
            j=a[i+1];
            a[i+1]=a[i];
            a[i]=j;
        }
    }
    for(i=0;i<5;i++)//循环输出已经排好序的数字
    {
        printf("%d\t",a[i]);
    }  
    return 0;
}

运行结果
在这里插入图片描述

本次博客分享就到这里啦,谢谢你的过往。

;