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

如何用fscanf解析含TAB与空行的Office结构体数据?

问题与解决方案

问题背景

定义了如下C++结构体:

struct Office {
    char city[50];
    int employees;
    char desc[200];
};

struct Office office[100];

需要读取特定格式的文件,将数据填充到office数组中。文件格式如下(城市下一行的员工数前有TAB/4个空格,存在空行分隔):

Toronto
    151: This is HQ

Vancouver
    23: This is branch office

London
    12: This is euro branch

目标解析结果示例:

city = "Toronto"
employees = 151
desc = "This is HQ"

现有实现代码运行异常,核心需求是处理TAB/前置空格和空行。

核心问题与解决方法

1. 空行处理

读取每一行后,先判断是否为空白行(仅含换行、空格、TAB),若是则直接跳过,避免干扰解析逻辑。可以通过遍历行内字符,用isspace判断是否全为空白。

2. TAB/前置空格处理

scanf系列函数的%d格式会自动跳过所有前置空白字符(包括TAB和空格),所以不需要额外处理员工数前的TAB,只需保证格式字符串正确即可。原代码中%d[^:]是错误写法,正确格式应为%d: %[^\n],匹配数字、冒号、空格,然后读取剩余的描述文本。

修正后的完整代码

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

#define MAX_OFFICES 100

struct Office {
    char city[50];
    int employees;
    char desc[200];
};

int LoadOffices(const char *f, struct Office offices[], int *count) {
    *count = 0;
    FILE *fp = fopen(f, "r");
    if (!fp) {
        return 1; // 文件打开失败返回错误码
    }

    char buf[500];
    while (*count < MAX_OFFICES && fgets(buf, sizeof(buf), fp) != NULL) {
        // 跳过空行
        int is_empty = 1;
        for (size_t j = 0; buf[j] != '\0'; j++) {
            if (!isspace((unsigned char)buf[j])) {
                is_empty = 0;
                break;
            }
        }
        if (is_empty) {
            continue;
        }

        // 处理城市名:移除末尾换行符
        buf[strcspn(buf, "\n")] = '\0';
        strncpy(offices[*count].city, buf, sizeof(offices[*count].city) - 1);
        offices[*count].city[sizeof(offices[*count].city) - 1] = '\0'; // 确保字符串终止

        // 读取员工信息行
        if (fgets(buf, sizeof(buf), fp) == NULL) {
            break; // 文件提前结束,终止循环
        }

        // 解析员工数和描述
        int emp;
        char desc[200];
        if (sscanf(buf, "%d: %[^\n]", &emp, desc) == 2) {
            offices[*count].employees = emp;
            strncpy(offices[*count].desc, desc, sizeof(offices[*count].desc) - 1);
            offices[*count].desc[sizeof(offices[*count].desc) - 1] = '\0';
            (*count)++;
        }
    }

    fclose(fp);
    return 0; // 成功返回0
}

关键细节说明

  • 用strcspn快速去除行尾的换行符,避免城市名包含多余的换行字符。
  • sscanf的%d自动跳过前置空白,完美适配员工数前的TAB/空格。
  • 加入数组边界检查,防止offices数组越界访问。
  • 所有字符串拷贝都预留了终止符位置,避免缓冲区溢出。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 00:25:26