You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C语言将文本文件中MAC地址与设备名存入结构体数组的问题排查

C语言读取MAC地址与设备名时结构体字段赋值错误的排查与解决

问题描述

尝试用C语言读取Inet.txt中的MAC地址(分段格式,如AA:BB:CC:DD:EE:FF)和设备名,存入自定义结构体数组:

typedef struct list {
    char a[3];  // 存储MAC第一段(最多2字符,留1位存结束符)
    char b[3];
    char c[3];
    char d[3];
    char e[3];
    char f[3];  // 注:原描述的a-g为笔误,MAC仅6段,故调整为a-f
    char alias[33];  // 设备名最多32字符,留1位存结束符
} list;

程序通过fgetc逐字符读取文件,逻辑为:

  • 将MAC分段分配到结构体对应字段
  • 读取到连续2个以上非:/空格的字符时,判定为设备名并存储

但运行后结构体中MAC分段(a-f)赋值混乱,出现错误拼接,无法正确输出MAC地址与设备名。

常见问题排查点及解决方法

1. 结构体字段未初始化

结构体数组未初始化时,字段内存会残留垃圾值,导致输出混乱。

  • 解决:定义数组后用memset初始化,或声明时直接赋值:
    list devices[100];
    memset(devices, 0, sizeof(devices));
    

2. MAC分段的字符边界处理错误

逐字符读取时,未正确识别:作为分段分隔符,或未及时给当前分段添加字符串结束符'\0',导致分段拼接混乱。

  • 解决:每读取1个MAC分段的字符,在满2个或遇到:时,立即给对应字段加上'\0',同时切换到下一个分段的存储位置。

3. 设备名触发逻辑模糊

原逻辑“读取到超过2个非:或空格字符时存储”边界模糊,容易误将MAC分段字符判定为设备名,或设备名读取时未正确终止。

  • 解决:先完整读取6段MAC地址,再读取后续设备名;或用fgets先读取整行,再拆分每行的MAC与设备名,比逐字符读取更易控制。

4. 逐字符读取的状态机逻辑混乱

未维护清晰的读取状态(如正在读取MAC第几段、是否读取设备名),导致字符存储错位。

  • 解决:用变量标记当前读取的MAC分段序号(0-5对应a-f),遇到:时切换分段,完成6段后切换到设备名读取状态。

修正后的示例代码

#include <stdio.h>
#include <string.h>

typedef struct list {
    char a[3];
    char b[3];
    char c[3];
    char d[3];
    char e[3];
    char f[3];
    char alias[33];
} list;

int main() {
    FILE *fp = fopen("Inet.txt", "r");
    if (!fp) {
        perror("Failed to open file");
        return 1;
    }

    list devices[100];
    memset(devices, 0, sizeof(devices));
    int dev_idx = 0;
    int mac_segment = 0;  // 0:a,1:b,...5:f
    int char_count = 0;   // 当前分段的字符数
    int in_device_name = 0;  // 是否处于设备名读取状态

    int ch;
    while ((ch = fgetc(fp)) != EOF) {
        if (ch == '\n') {
            // 换行表示当前设备记录结束,重置状态
            mac_segment = 0;
            char_count = 0;
            in_device_name = 0;
            dev_idx++;
            if (dev_idx >= 100) break;  // 防止数组越界
            continue;
        }

        if (!in_device_name) {
            // 读取MAC地址
            if (ch == ':') {
                // 分段结束,添加结束符,切换到下一段
                switch(mac_segment) {
                    case 0: devices[dev_idx].a[char_count] = '\0'; break;
                    case 1: devices[dev_idx].b[char_count] = '\0'; break;
                    case 2: devices[dev_idx].c[char_count] = '\0'; break;
                    case 3: devices[dev_idx].d[char_count] = '\0'; break;
                    case 4: devices[dev_idx].e[char_count] = '\0'; break;
                    case 5: devices[dev_idx].f[char_count] = '\0'; break;
                }
                mac_segment++;
                char_count = 0;
                // 6段MAC读完后,切换到设备名读取
                if (mac_segment >= 6) {
                    in_device_name = 1;
                }
                continue;
            }
            // 跳过空格,直到遇到MAC字符
            if (ch == ' ') continue;

            // 存储当前MAC字符到对应分段
            switch(mac_segment) {
                case 0: if (char_count < 2) devices[dev_idx].a[char_count++] = ch; break;
                case 1: if (char_count < 2) devices[dev_idx].b[char_count++] = ch; break;
                case 2: if (char_count < 2) devices[dev_idx].c[char_count++] = ch; break;
                case 3: if (char_count < 2) devices[dev_idx].d[char_count++] = ch; break;
                case 4: if (char_count < 2) devices[dev_idx].e[char_count++] = ch; break;
                case 5: if (char_count < 2) devices[dev_idx].f[char_count++] = ch; break;
            }
        } else {
            // 读取设备名,跳过开头空格,最多存32字符
            static int alias_count = 0;
            if (ch == ' ' && alias_count == 0) continue;
            if (alias_count < 32) {
                devices[dev_idx].alias[alias_count++] = ch;
            }
        }
    }

    // 输出测试
    for (int i = 0; i < dev_idx; i++) {
        printf("MAC: %s:%s:%s:%s:%s:%s | 设备名: %s\n",
               devices[i].a, devices[i].b, devices[i].c,
               devices[i].d, devices[i].e, devices[i].f,
               devices[i].alias);
    }

    fclose(fp);
    return 0;
}

额外优化建议

优先用fgets读取整行,再用sscanf拆分MAC和设备名,代码更简洁易维护:

char line[100];
while (fgets(line, sizeof(line), fp)) {
    list dev = {0};
    sscanf(line, "%2s:%2s:%2s:%2s:%2s:%2s %[^\n]",
           dev.a, dev.b, dev.c, dev.d, dev.e, dev.f, dev.alias);
    devices[dev_idx++] = dev;
}

这种方式避免了逐字符读取的复杂状态机逻辑,大幅降低出错概率。

内容的提问来源于stack exchange,提问作者coconut crab

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 17:35:33