Если вы хотите избежать замены line
на strtok
, вы можете просто использовать арифметику указателя, чтобы скопировать либо "first last"
в recTemp.artist
, либо скопировать "name"
в случае, когда в первом поле нет кавычек. Это просто еще один подход, который вы можете использовать, чтобы избежать изменения исходной строки. (и здоровое упражнение в использовании указателей)
В случае, когда присутствуют кавычки, вы можете установить указатель (p
) на line + 1
и использовать strstr
, чтобы найти подстроку "\","
, устанавливающую конечный указатель (endptr
) на закрывающую кавычку. Затем вы можете вызвать strchar
на p
с помощью ','
, чтобы найти запятую между last, first
и установить другой указатель для перехода к началу имени (firstp
). Если у вас есть firstp
, указывающий на начало имени, вы можете просто memcpy
имя до recTemp.artist
, добавить space
, а затем скопировать фамилию, завершая нулем после этого.
В случае отсутствия кавычек вам нужно только использовать strchr
, чтобы найти разделитель полей ','
и вызвать memcpy
, а затем нулевое завершение.
Краткий пример:
#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
, либо просто используйте арифметику указателя. Вы можете создать дамп сборки, сгенерированной обоими методами, чтобы увидеть, обеспечивает ли ваш компилятор преимущество оптимизации между методами. Разница будет незначительной по большому счету.
person
David C. Rankin
schedule
01.02.2019
strtok(line, ", ")
Как вы уже выяснили, первый символ"
, начинать надо со второго символа. - person Gerhardh   schedule 01.02.2019