考勤信息(用一个字符串来表示员工的出勤信息)

题目描述

公司用一个字符串来表示员工的出勤信息

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 
#include 
#include 
#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小于数组长度。

  • == 1scanf函数在成功读取并赋值时,会返回成功处理的参数个数。在这里,因为只有一个"%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,则跳出循环,准备读取下一条记录。这样可以确保在处理多条记录时能够正确地分隔每条记录。

文章目录

  • 题目描述
  • 输入描述
  • 输出描述
  • 用例
  • 代码
  • 注意:
    • 1、 while (scanf("%s", records[records_size]) == 1)
    • 2、getchar()

你可能感兴趣的:(刷题,c语言,数据结构,华为od)