虽然strtok 会解决这个问题,但我相信它不会是一个非常可维护的解决方案。我打算指出使用strtok的一些问题,以及这些问题的解决方案。
问题 #1:由于隐藏状态,strtok 不可重入且非线程安全;如果您尝试同时标记两个字符串(例如交织函数调用序列或使用多个线程),您会遇到问题。
解决方案 #1: 可以改用 strchr 和 strcspn 来解决此问题。我已经展示了使用strcspn 阅读其他答案中的行的能力1,2;这些可以很容易地改用strchr,或使用'\n'以外的字符。
问题 #2: strtok、strchr 和 strcspn 都对需要中间数组存在的字符串进行操作。您正在从文件中读取;如果您不需要该中间数组,因为您可以将字段直接读入它们对应的数组中,那么消除它们可能会带来更高级的优化和更简洁、更易于维护的代码。
解决方案#2:以下代码demonstrates使用fscanf直接从文件中执行拆分。
#include <stdio.h>
#define WIDTH_STR(width) #width
#define FIXED_FIELD(width) "%" WIDTH_STR(width)
#define TERMINAL(set) "[^" set "]%*1[" set "] "
#define W 1024
int parse(FILE *f) {
char x[W+1], y[W+1], z[W+1];
if (fscanf(f, FIXED_FIELD(W) TERMINAL(":"), x) <= 0) { return EOF; }
if (fscanf(f, FIXED_FIELD(W) TERMINAL(","), y) <= 0) { return EOF; }
if (fscanf(f, FIXED_FIELD(W) TERMINAL("\n"), z) <= 0) { return EOF; }
printf("<%s>\n", x);
printf("<%s>\n", y);
printf("<%s>\n", z);
return 0;
}
int main(void) {
printf("parse returned: %d\n", parse(stdin));
}
问题 #3: 当您假设字段为固定宽度时,上述所有解决方案都会达到最佳最优性(在可维护性/复杂性和计算效率方面)。一旦该假设失效,更有意义使用fgetc 一次读取和解析一个字节,并根据需要重新分配以适应可变字段。
解决方案#3: 我在another answer 中展示了读取可变长度单词的能力,这很容易适应读取单个标记并将其解析为单独的动态分配。这可能会遭受代价高昂的重新分配的缺点,即允许您的用户输入 巨大的(多兆字节)字段值,这些字段值通常不支持作为具有自动存储持续时间的固定宽度数组。