Loading

C语言入门学习-统计合法MAC地址数

#include <stdio.h>      // 标准输入输出库
#include <string.h>     // 字符串操作库
#include <ctype.h>      // 字符处理库(如tolower, isdigit等)
#include <stdbool.h>    // 布尔类型支持
#include <stdlib.h>     // 内存分配和释放函数
#include "uthash.h"     // 轻量级哈希表库

#define MAX_MAC_LENGTH 17       // MAC地址的标准长度(12个十六进制字符+5个分隔符)
#define MAX_INPUT_LENGTH 1000   // 输入字符串的最大长度限制

// 定义哈希表结构体
typedef struct {
    char mac[MAX_MAC_LENGTH + 1];  // 存储MAC地址的字符串(+1用于存放字符串结束符'\0')
    UT_hash_handle hh;             // uthash库所需的哈希表处理句柄
} MacEntry;

MacEntry *mac_table = NULL;  // 全局哈希表指针,初始化为NULL

/**
 * @brief 检查字符是否为合法的十六进制字符
 * @param c 待检查的字符
 * @return true 如果是合法的十六进制字符(0-9, a-f, A-F)
 * @return false 如果不是合法的十六进制字符
 */
bool is_hex_char(char c) {
    return isdigit(c) || (tolower(c) >= 'a' && tolower(c) <= 'f');
}

/**
 * @brief 检查子串是否为合法的MAC地址
 * @param substr 待检查的子串(长度必须为17)
 * @return true 如果是合法的MAC地址
 * @return false 如果不是合法的MAC地址
 */
bool is_valid_mac(const char *substr) {
    // 检查分隔符是否合法(只能是'-'或':')
    char separator = substr[2];
    if (separator != '-' && separator != ':') {
        return false;
    }

    // 检查所有分隔符是否一致且位置正确(第2、5、8、11、14位)
    for (int i = 2; i <= 14; i += 3) {
        if (substr[i] != separator) {
            return false;
        }
    }

    // 检查非分隔符的字符是否都是合法的十六进制字符
    for (int i = 0; i < MAX_MAC_LENGTH; i++) {
        // 跳过分隔符的位置
        if (i == 2 || i == 5 || i == 8 || i == 11 || i == 14) {
            continue;
        }
        if (!is_hex_char(substr[i])) {
            return false;
        }
    }

    return true;
}

/**
 * @brief 标准化MAC地址(统一为小写字母和统一的分隔符)
 * @param mac 待标准化的MAC地址(长度必须为17)
 * @param separator 统一使用的分隔符('-'或':')
 */
void normalize_mac(char *mac, char separator) {
    for (int i = 0; i < MAX_MAC_LENGTH; i++) {
        if (i == 2 || i == 5 || i == 8 || i == 11 || i == 14) {
            mac[i] = separator;  // 统一分隔符
        } else {
            mac[i] = tolower(mac[i]);  // 转换为小写字母
        }
    }
}

/**
 * @brief 统计输入字符串中唯一合法的MAC地址数量
 * @param inputStr 输入的字符串
 * @return int 唯一合法的MAC地址数量
 */
int count_unique_mac_addresses(const char *inputStr) {
    int len = strlen(inputStr);
    // 如果输入字符串长度小于MAC地址的标准长度,直接返回0
    if (len < MAX_MAC_LENGTH) {
        return 0;
    }

    // 滑动窗口遍历所有可能的17字符子串
    for (int i = 0; i <= len - MAX_MAC_LENGTH; i++) {
        char substr[MAX_MAC_LENGTH + 1];  // 临时存储子串
        strncpy_s(substr, &inputStr[i], MAX_MAC_LENGTH);  // 复制子串
        substr[MAX_MAC_LENGTH] = '\0';  // 添加字符串结束符

        // 检查子串是否为合法的MAC地址
        if (is_valid_mac(substr)) {
            char separator = substr[2];  // 获取分隔符
            normalize_mac(substr, separator);  // 标准化MAC地址

            // 检查哈希表中是否已存在该MAC地址
            MacEntry *entry = NULL;
            HASH_FIND_STR(mac_table, substr, entry);
            // 如果不存在,则添加到哈希表
            if (entry == NULL) {
                entry = (MacEntry *)malloc(sizeof(MacEntry));
                strcpy(entry->mac, substr);
                HASH_ADD_STR(mac_table, mac, entry);
            }
        }
    }

    // 获取哈希表中唯一MAC地址的数量
    int count = HASH_COUNT(mac_table);
    // 清空哈希表,释放内存
    HASH_CLEAR(hh, mac_table);

    return count;
}

/**
 * @brief 测试函数
 */
int main() {
    // 测试用例1:合法的MAC地址(使用'-'分隔符)
    const char *test1 = "00-11-aa-BB-FF-Ed";
    // 测试用例2:合法的MAC地址(使用':'分隔符,应与测试用例1视为相同)
    const char *test2 = "00:11:aa:BB:FF:Ed";
    // 测试用例3:不合法的MAC地址(混用分隔符)
    const char *test3 = "00-11-aa-BB:FF-Ed";
    // 测试用例4:两个合法的MAC地址
    const char *test4 = "00-11-aa-BB-FF-Ed 00-11-aa-BB-FF-Ee";
    // 测试用例5:输入字符串太短
    const char *test5 = "short";

    // 执行测试并打印结果
    printf("测试1: %d\n", count_unique_mac_addresses(test1)); // 预期输出:1
    printf("测试2: %d\n", count_unique_mac_addresses(test2)); // 预期输出:1
    printf("测试3: %d\n", count_unique_mac_addresses(test3)); // 预期输出:0
    printf("测试4: %d\n", count_unique_mac_addresses(test4)); // 预期输出:2
    printf("测试5: %d\n", count_unique_mac_addresses(test5)); // 预期输出:0

    return 0;
}

posted @ 2025-07-10 01:21  Sunyaa  阅读(11)  评论(0)    收藏  举报