您使用strtok 的方法很好,但也许您想将数据存储到结构中。类似于以下内容。我选择了固定的字符串最大长度,并且刚刚发明了这些长度。
struct row_data {
char bssid[18];
char ch[4];
char cipher[10];
char essid[20];
};
如果您始终确切地知道列的顺序,您可以在这里停下来。只需使用枚举索引列:
enum column_id {
COL_RSSID = 0,
COL_CH = 5,
COL_CIPHER = 8,
COL_ESSID = 10
};
现在像这样可以做到这一点:
int column = 0;
char *target = NULL;
struct row_data row;
struct row_data empty_row = {0};
while( fgets(path, sizeof(path), fp) )
{
row = empty_row;
token = strtok(path, s);
for( column = 0; token; token = strtok(NULL,s), column++ )
{
switch( column )
{
case COL_RSSID: target = row.rssid; break;
case COL_CH: target = row.ch; break;
case COL_CIPHER: target = row.cipher; break;
case COL_ESSID: target = row.essid; break;
default: target = NULL;
}
if( target ) strcpy(target, token);
}
/* do something with row */
printf( "Read rssid=%s ch=%s cipher=%s essid=%s\n",
row.rssid, row.ch, row.cipher, row.essid );
}
创建一个target_length 或类似的可以用作strncpy 的参数并不需要太多额外的工作(我的例子很短,使用strcpy)。或者你可以换个方向,只在结构中存储指针。然后就可以使用动态分配把字符串拷贝进去了。
现在,如果您的列顺序未知,您将不得不进一步抽象这一步。这将首先阅读标题行并查找您感兴趣的部分,并存储它们出现的列索引。这会使您的代码更加复杂,但并非不合理。
起点可能是这样(需要<stdlib.h>):
struct column_map {
const char * name;
size_t offset;
int index;
} columns = {
{ "RSSID", offsetof( struct row_data, rssid ), -1 },
{ "CH", offsetof( struct row_data, ch ), -1 },
{ "CIPHER", offsetof( struct row_data, cipher ), -1 },
{ "ESSID", offsetof( struct row_data, essid ), -1 },
{ NULL }
};
/* first read the header */
token = strtok(header, s);
for( column = 0; token; token = strtok(NULL,s), column++ )
{
for( struct column_map *map = columns; map->name; map++ ) {
if( map->index == -1 && 0 == strcmp(token, map->name) ) {
map->index = column;
}
}
}
你可以看到这是怎么回事。假设您已将标题读入header,现在您已经使用您感兴趣的每一列的列索引填充了columns。因此,在读取其他行时,您这样做而不是切换:
row = empty_row;
token = strtok(path, s);
for( column = 0; token; token = strtok(NULL,s), column++ )
{
for( struct column_map *map = columns; map->name; map++ ) {
if( map->index == column ) {
/* again, if using strncpy, store a length inside the map,
and use MIN(map->length, strlen(token)+1) or similar */
memcpy( (char*)&row + map->offset, token, strlen(token) );
}
}
}
您当然可以存储一个指针,而不是在表中存储偏移量,就像我们在 switch 语句中使用 target 所做的那样。但这需要直接指向&row.rssid 之类的东西。也许这对你来说已经足够了(我怀疑我已经提供了足够多的东西)。
但公平地说,我会指出这个选项,它可能比使用上面的memcpy 更简单。我会加入我一直避免的strncpy。
struct row_data row;
struct column_map {
const char * name;
char *target;
size_t target_size;
int index;
} columns = {
{ "RSSID", row.rssid, sizeof(row.rssid), -1 },
{ "CH", row.ch, sizeof(row.ch), -1 },
{ "CIPHER", row.cipher, sizeof(row.cipher), -1 },
{ "ESSID", row.essid, sizeof(row.essid), -1 },
{ NULL }
};
/* ::: */
if( map->index == column ) {
strncpy( map->target, token, map->target_size );
map->target[map->target_size-1] = '\0'; /* in case of overflow */
}