理解题意非常重要,而理解题意要根据它举的例子,可根据它的例子也不一定能完全理解题意。

总之,一个测试用例中的记录不超过 100 条,如果两条错误记录截取后的文件名和错误行号相同,就认为是同一条记录,以该记录第一次出现为基准,将错误发生次数 +1,而不再添加新的记录。

最后,如果错误记录超过 8条,就输出整理后的最新记录的 8条错误记录,否则全部输出。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* 返回septor最后一次出现位置后的子字符串,并作规范化处理:
    即如果字串长度大于16,只保留最后 16 位*/
static char* strlaststr(const char* str, const char septor);


int main() {
    char str[100][100];
    int lnum[100] = {0}, 
        count[100] = {0}, 
        i = 0;    // 最后一条记录的位置
    char septor = '\\';
    char* st;		// 临时字符串指针
    int flag = 0;    // 重复记录标记
    // Initiate
    if (scanf("%s %d", str[i], &lnum[i]) != EOF) {
        st = strlaststr(str[i], septor);
        strcpy(str[i], st);
        count[i++] = 1;
    }

    while (scanf("%s %d", str[i], &lnum[i]) != EOF) {
        char* st = strlaststr(str[i], septor);

        for (int j = 0; j < i; j++) {
            if (strcmp(st, str[j]) == 0 && lnum[j] == lnum[i]) { // 文件名相同
                count[j] ++;
                flag = 1;
            }
        }
        if (flag == 1) {
            flag = 0;
            continue;
        }

        if (i < 100) {
            strcpy(str[i], st);
            count[i++] += 1;
        } else {    // 记录已满,有新记录,整体前移,覆盖旧记录
            for (int j = 1; j < 100; j++) {        // 记录前移
                strcpy(str[j - 1], str[j]);
                count[j - 1] = count[j];
                lnum[j - 1] = lnum[j];
            }
            memset(str[7], '\0', sizeof(str[7])) ;
            strcpy(str[99], st);    // 添加新记录
            count[99] = 1;
            i = 99;
        }
    }

    if ( i < 8) {
        for (int j = 0; j < i; j++) {
            printf("%s %d %d\n", str[j], lnum[j], count[j]);
        }
    } else {
        for (int j = i - 8; j < i; j++) {
            printf("%s %d %d\n", str[j], lnum[j], count[j]);
        }
    }
    return 0;
}

static char* strlaststr(const char* str, const char septor) {
    char* s = str;
    if (str == NULL)
        return NULL;

    int len = strlen(s);
    char* ss;

    int i;
    for (i = len - 1; i >= 0 && s[i] != septor; --i); //  定位 septor 的位置

    if (i == -1) { // 没找到 septor,返回有效字符串
        if (len > 16) {
            ss = s + len - 16;
            return ss;
        }
    }
    // 找到 septor,返回其后有效字符串
    if (len - i - 1 > 16) {  // 子字符串长度大于 16
        ss = s + len - 16;
        return ss;
    } else {
        ss = s + i + 1;
        return ss;
    }
}