题目描述
公司用一个字符串来表示员工的出勤信息
absent:缺勤
late:迟到
leaveearly:早退
present:正常上班
现需根据员工出勤信息,判断本次是否能获得出勤奖,能获得出勤奖的条件如下:
缺勤不超过一次;
没有连续的迟到/早退;
任意连续7次考勤,缺勤/迟到/早退不超过3次。
输入描述
用户的考勤数据字符串
记录条数 >= 1;
输入字符串长度 < 10000;
不存在非法输入;
如:
2
present
present absent present present leaveearly present absent
输出描述
根据考勤数据字符串,如果能得到考勤奖,输出”true”;否则输出”false”,
对于输入示例的结果应为:
true false
用例
输入
2
present
present present
输出
true true
输入
2
present
present absent present present leaveearly present absent
输出
true false
代码
// 定义最大记录数为100,每条记录的最大长度为100
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_RECORDS 100
#define MAX_LENGTH 100
// 定义一个函数
// `can_receive_award`,用于判断给定的出勤记录数组是否满足获得出勤奖的条件
int can_receive_award(char records[][MAX_LENGTH], int count) {
// 初始化缺勤次数计数器
int absent_count = 0;
// 遍历整个出勤记录数组
for (int i = 0; i < count; i++) {
// 检查当前记录是否为“absent”(缺勤)
if (strcmp(records[i], "absent") == 0) {
absent_count++;
// 如果缺勤超过一次,则直接返回不能获得出勤奖(false)
if (absent_count > 1) {
return 0;
}
}
// 检查当前记录是否为“late”或“leaveearly”(迟到/早退)
if (strcmp(records[i], "late") == 0 ||
strcmp(records[i], "leaveearly") == 0) {
// 如果当前记录是迟到/早退,并且上一条记录也是迟到/早退,则返回不能获得出勤奖(false)
if (i > 0 && (strcmp(records[i - 1], "late") == 0 ||
strcmp(records[i - 1], "leaveearly") == 0)) {
return 0;
}
}
// 当遍历到第6条记录之后,开始检查连续7天内的违规情况
if (i >= 6) {
int count_in_7_days = 0;
// 遍历连续7天的记录
for (int j = i - 6; j <= i; ++j) {
// 若当天不是正常上班("present"),则违规次数+1
if (strcmp(records[j], "present") != 0)
++count_in_7_days;
}
// 如果连续7天内违规次数超过3次,则返回不能获得出勤奖(false)
if (count_in_7_days > 3) {
return 0; // false
}
}
}
// 所有条件都满足后,返回能获得出勤奖(true)
return 1;
}
int main() {
// 读取用户输入的记录组数
int n;
scanf("%d", &n);
// 遍历每一组记录
for (int i = 0; i < n; i++) {
// 初始化记录数组和记录数量计数器
char records[MAX_RECORDS][MAX_LENGTH];
int count = 0;
// 逐条读取用户的考勤记录,直到遇到换行符或者无法读取为止
while (scanf("%s", records[count]) == 1) {
count++;
// 判断是否读取到换行符,如果是,则跳出循环
if (getchar() == '\n')
break;
}
// 根据读取到的记录调用 `can_receive_award` 函数并输出结果
printf("%s ", can_receive_award(records, count) ? "true" : "false");
}
return 0;
}
注意:
1、 while (scanf(“%s”, records[records_size]) == 1)
这段代码是C语言中用于读取输入流(通常是标准输入,即键盘输入)的循环结构。while
循环会一直执行,只要从输入流成功读取一个字符串到数组records
中且返回值为1。
详细解释如下:
scanf("%s", records[records_size])
:scanf
是C语言中的格式化输入函数,这里的"%s"表示按照字符串格式读取输入。records
是一个字符数组,records[records_size]
代表将读取的字符串存放在数组的records_size
索引位置。注意,这里没有检查数组越界问题,实际使用时应确保records_size
小于数组长度。== 1
:scanf
函数在成功读取并赋值时,会返回成功处理的参数个数。在这里,因为只有一个"%s"格式说明符,所以当成功读取一个字符串时返回1。如果遇到文件结束符(如按下回车键但未输入任何字符串)、读取错误或输入与格式不符等情况,scanf
会返回非1的值(通常是EOF或0)。
因此,整个while
循环的意思是:只要能成功从输入流读取一个字符串并存入records
数组中,就继续循环。这样可以连续不断地读取多个字符串,直到无法成功读取为止。
2、getchar()
getchar()
是C语言中用于从标准输入(通常是键盘)读取单个字符的标准库函数。每次调用时,它会等待用户输入并返回一个字符。
在上述代码中:
while (scanf("%s", records[count]) == 1) {
count++;
if (getchar() == '\n')
break;
}
这段代码首先使用scanf
读取一个字符串到records
数组中,然后立即调用getchar()
来读取下一个字符。这里的目的是处理换行符的问题。当用户在输入字符串后按下回车键时,scanf
会读取整个字符串但不会读取回车符,而回车符会被留在输入缓冲区中。getchar()
在此处的作用就是读取并检查这个可能存在的回车符。如果读取到的字符是换行符\n
,则跳出循环,准备读取下一条记录。这样可以确保在处理多条记录时能够正确地分隔每条记录。