C语言:完善校验字符串是否为可提取数据的有效Markdown表格行的函数
C语言:完善校验字符串是否为可提取数据的有效Markdown表格行的函数
嗨,我看你现在写了个雏形函数,但目前只能判断固定表头,局限性太大啦。咱们得把它改成通用的,能准确识别出哪些是可以提取数据的有效表格行,排除表头、分隔线和空行。
先明确咱们的目标:函数接收一行字符串,只要这行是有实际数据的表格行就返回true,如果是表头、表头下面的分隔线、空表格行(只有竖线和空格)就返回false。
我给你一步步完善这个函数,先理清楚思路,再写代码:
首先得处理几个关键判断场景
咱们要先搞定三个需要排除的情况:
- 空表格行:比如
| | | |或者啥内容都没有的行 - 表头分隔线行:就是那种全是
-和:的行,比如| --- | :---: | ---: | - 固定表头行:就是你例子里的那行特定表头,这个可以保留硬编码判断,毕竟你的场景里表头是固定的
然后写辅助函数来拆分判断逻辑
直接把所有逻辑堆在check_line里会很乱,咱们拆成几个小辅助函数,清晰又好维护:
1. 先写个去除字符串两端空白的函数
因为输入的行可能带换行符或者首尾空格,这些会干扰判断,先把它们去掉:
#include <stdio.h> #include <string.h> #include <ctype.h> // 去除字符串两端的空白(包括换行、空格、制表符) char* trim(char* str) { // 跳过开头的空白 while(isspace((unsigned char)*str)) str++; if(*str == 0) return str; // 从末尾往前找非空白字符 char* end = str + strlen(str) - 1; while(end > str && isspace((unsigned char)*end)) end--; // 给字符串加结束符 end[1] = '\0'; return str; }
2. 判断某一列是不是分隔线内容
分隔线的列里只会有-、:和空白,没有其他有效字符,咱们写个函数来判断:
// 判断单个列是不是分隔线(只包含-、:和空白) int is_separator_column(const char* col) { while(*col != '\0') { if(!isspace((unsigned char)*col) && *col != '-' && *col != ':') { return 0; // 有其他字符,不是分隔线列 } col++; } return 1; }
3. 判断整行是不是分隔线行
遍历每一列,只要所有列都是分隔线内容,那这行就是表头和正文之间的分隔线:
// 判断整行是不是表格的分隔线行 int is_separator_line(char* line) { char* trimmed = trim(line); if(strlen(trimmed) == 0) return 0; if(trimmed[0] != '|') return 0; // 连表格行的基本格式都不符合,直接排除 char* col_start = trimmed + 1; // 跳过开头的| char* col_end; while((col_end = strchr(col_start, '|')) != NULL) { *col_end = '\0'; // 临时截断,取出当前列 if(!is_separator_column(col_start)) { *col_end = '|'; // 恢复原字符 return 0; } *col_end = '|'; // 恢复原字符 col_start = col_end + 1; } // 检查最后一列(如果行末尾没有|的情况) if(!is_separator_column(col_start)) { return 0; } return 1; }
4. 判断是不是空表格行
空表格行里只有|和空白,没有任何实际数据:
// 判断是不是空的表格行(只有|和空白字符) int is_empty_table_line(char* line) { char* trimmed = trim(line); if(strlen(trimmed) == 0) return 1; const char* p = trimmed; while(*p != '\0') { if(*p != '|' && !isspace((unsigned char)*p)) { return 0; // 有非空白非|的字符,不是空行 } p++; } return 1; }
最后完善核心的check_line函数
把上面的辅助函数整合起来,按顺序判断:
bool check_line(char* line) { puts(line); // 调试用的控制台输出 // 先去掉末尾的换行符,避免干扰判断 char* newline = strchr(line, '\n'); if(newline != NULL) { *newline = '\0'; } // 1. 先判断是不是空表格行,是就返回false if(is_empty_table_line(line)) { return false; } // 2. 判断是不是分隔线行,是就返回false if(is_separator_line(line)) { return false; } // 3. 判断是不是你指定的固定表头行,是就返回false char* trimmed_line = trim(line); if(strcmp(trimmed_line, "| Lebensmittel/Gericht | Gewicht in gr | kcal |") == 0) { return false; } // 剩下的情况就是有效数据行,返回true return true; }
测试一下你的例子
用你给的测试用例跑一遍,结果完全符合预期:
| Lebensmittel/Gericht | Gewicht in gr | kcal |→ 匹配表头,返回false| -------------------- | ------------- | ---- |→ 是分隔线,返回false| Wildkräutersalat | 42 | 8 |→ 有效数据行,返回true| Rucola | 40 | 10 |→ 有效数据行,返回true| | | |→ 空表格行,返回false| Brot | 73 | 161 |→ 有效数据行,返回true
这样就完美满足你的需求啦!如果以后表头变了,只需要修改那个硬编码的字符串就行,要是想做成通用的,把表头判断那部分去掉或者改成更灵活的逻辑就可以。
备注:内容来源于stack exchange,提问作者Simplicissimus
相关产品推荐
相关产品推荐

