我有读取.txt
文件的代码:
Pancho: Juanka,Cony
这个想法是找到字符':'
并将其分开保存在字符串数组中。与Juanka
and相同,Cony
但相反,它将在找到','
and时出现'\0'
。
虽然strtok
会解决这个问题,但我相信它不会是一个非常可维护的解决方案。我打算指出一些使用的问题strtok
,以及这些问题的解决方案。
问题#1:由于隐藏状态,strtok
是不可重入和非线程安全的;如果您尝试同时标记两个字符串(例如交织函数调用序列或使用多个线程),您将遇到问题。
解决方案#1: strchr
并且strcspn
可以用来解决这个问题。我已经展示了使用 ; 阅读其他答案1 、 2 中的行的strcspn
能力;这些可以很容易地strchr
改用,或使用 . 以外的字符'\n'
。
问题 #2: strtok
,strchr
并且strcspn
都对需要中间数组存在的字符串进行操作。您正在从文件中读取;如果您不需要该中间数组,因为您可以将字段直接读入其对应的数组中,那么消除它们可能会公开更高级的优化和更清洁、更可维护的代码。
解决方案#2:以下代码演示了使用.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:我在另一个答案中展示了读取可变长度单词的能力,这很容易适应读取单个标记并将其解析为单独的动态分配。这可能会遭受代价高昂的重新分配的缺点,需要允许您的用户输入巨大的(数兆字节)字段值,这些字段值通常不支持作为具有自动存储持续时间的固定宽度数组。