Ваш подход с 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));
}
}
}
Вместо сохраняя смещения в таблице, вы могли бы, конечно, сохранить указатель, как и мы с target
в инструкции switch. Но это потребовало бы прямого указания на что-то вроде &row.rssid
. Возможно, этого достаточно для вас (я подозреваю, что я уже предоставил более чем достаточно).
Но, если быть справедливым, я укажу на этот вариант, который может быть проще, чем использование memcpy
, как указано выше. И я буду рулон в strncpy
материалах, которых я избегаю.
Обратите внимание, что вы имеете в виду «char array» или «string» not «char» - «разделение char на слова» имеет другое более очевидное значение. – spinkus