Если вы хотите избежать изменения line
с помощью strtok
, вы можете просто использовать арифметику указателя для копирования либо "first last"
в recTemp.artist
, либо скопировать "name"
в случае, когда в первом нет кавычекполе.Это просто другой подход, который позволяет избежать изменения исходной строки.(и полезное упражнение в использовании указателей)
В случае, когда присутствуют кавычки, вы можете установить указатель (p
) на line + 1
и использовать strstr
, чтобы найти параметр подстроки "\","
указатель конца (endptr
) на закрывающую кавычку.Затем можно позвонить strchar
на p
с помощью ','
, чтобы найти запятую между last, first
и установить другой указатель для перехода к началу имени (firstp
).Как только вы наберете firstp
, указывающее на начало имени, вы можете просто memcpy
от имени до recTemp.artist
, добавить space
, а затем скопировать фамилию, заканчивая нулем после этого.
В случае отсутствия кавычек вам нужно всего лишь использовать strchr
, чтобы найти ','
разделитель полей и вызвать memcpy
, а затем nul-terminate.
Краткий пример:
#include <stdio.h>
#include <string.h>
typedef struct {
char artist[64];
} rec_t;
int main (void) {
#ifndef NOQUOTE
char line[] = "\"Smith, John\",Data1,Data2,Data3";
#else
char line[] = "Dave,Data1,Data2,Data3";
#endif
rec_t recTemp;
if (*line == '\"') { /* if double-quotes are present */
char *p = line + 1, *endptr, *sep; /* ptr, endptr & sep */
if (!(endptr = strstr (p, "\","))) { /* find close quote, validate */
fputs ("error: invalid line format.\n", stderr);
/* handle error as needed, e.g. */
return 1;
}
if ((sep = strchr (p, ','))) { /* locate ',' in last, first */
char *firstp = sep + 1; /* set firstp to next char */
while (*firstp && *firstp == ' ') /* skip any leading spaces */
firstp++;
memcpy (recTemp.artist, firstp, endptr - firstp); /* copy first */
endptr = recTemp.artist + (endptr-firstp); /* set endptr after */
*endptr++ = ' '; /* add a space */
memcpy (endptr, p, sep - p); /* copy last */
*(endptr + (sep - p)) = 0; /* nul-terminate */
}
}
else { /* otherwise - name without quotes */
char *sep = strchr (line, ','); /* find field seperator */
if (!sep) {
fputs ("error: invalid line format.\n", stderr);
/* handle error as needed, e.g. */
return 1;
}
memcpy (recTemp.artist, line, (sep - line)); /* copy name */
*(recTemp.artist + (sep - line)) = 0; /* nul-terminate */
}
printf ("recTemp.artist: '%s'\n", recTemp.artist);
}
Пример использования / Вывод
$ ./bin/rectmp
recTemp.artist: 'John Smith'
Случай без кавычек, скомпилированный с -DNOQUOTE
:
$ ./bin/rectmpnq
recTemp.artist: 'Dave'
Используете ли вы strtok
или пройдите несколько указателей вниз line
, оба в порядке.Если вы хотите сохранить line
без изменений, то либо сделайте копию, прежде чем работать с ней с помощью strtok
, либо просто используйте арифметику указателей.Вы можете сбросить сборку, сгенерированную в обоих методах, чтобы увидеть, обеспечивает ли ваш компилятор преимущество в оптимизации между методами.Разница будет незначительной в великой схеме вещей.