Я думаю, strsep
все еще лучший инструмент для этого:
while ((token = strsep(&str, ","))) my_fn(token);
Это буквально одна строка, разделяющая строку.
Дополнительные скобки - это стилистический элемент, указывающий, что мы намеренно проверяем результат присваивания, а не оператор равенства ==
.
Чтобы этот шаблон работал, token
и str
оба имеют тип char *
. Если вы начали со строкового литерала, то сначала вам нужно сделать его копию:
// More general pattern:
const char *my_str_literal = "JAN,FEB,MAR";
char *token, *str, *tofree;
tofree = str = strdup(my_str_literal); // We own str's memory now.
while ((token = strsep(&str, ","))) my_fn(token);
free(tofree);
Если в str
появятся два разделителя, вы получите значение token
, которое будет пустой строкой. Значение str
модифицируется тем, что каждый встреченный разделитель перезаписывается нулевым байтом - еще одна веская причина для копирования строки, которая анализируется первой.
В комментарии кто-то предположил, что strtok
лучше, чем strsep
, потому что strtok
более переносимый. Ubuntu и Mac OS X имеют strsep
; можно догадаться, что и другие Unixy системы тоже. В Windows отсутствует strsep
, но есть strbrk
, что позволяет заменить этот короткий и приятный strsep
:
char *strsep(char **stringp, const char *delim) {
if (*stringp == NULL) { return NULL; }
char *token_start = *stringp;
*stringp = strpbrk(token_start, delim);
if (*stringp) {
**stringp = '\0';
(*stringp)++;
}
return token_start;
}
Здесь - хорошее объяснение strsep
против strtok
. О плюсах и минусах можно судить субъективно; Тем не менее, я думаю, что это красноречивый знак того, что strsep
был разработан как замена для strtok
.