Вы правы, strtok()
может изменить свой первый строковый аргумент, и мне нравится ваше описание: strtok
оставляет исходную строку заполненной нулевыми символами .
Предлагаемая вами стратегия это интересно и не сложно реализовать, но оно несовместимо с текущей семантикой, определенной стандартом C. Описание очень точное относительно того, где нулевые байты установлены в исходной строке. Также обратите внимание, что ваше предложение по-прежнему имеет два недостатка:
- оно использует скрытое состояние stati c.
- оно изменяет строку аргумента, поэтому не подходит для строковых констант.
- каждый последующий вызов изменяет токены 1015 *, возвращаемые предыдущими вызовами, поскольку нулевые терминаторы постепенно заменяются исходными байтами. Такое поведение будет даже более нелогичным, чем текущие побочные эффекты.
Для выполнения тех же самых задач синтаксического анализа, что и strtok()
без изменений в исходной строке, я предлагаю использовать эти часто пропускаемые, но стандартные строковые функции из <string.h>
:
// return the number of characters at the start of s1 not matching any characters from s2
size_t strcspn(const char *s1, const char *s2);
// return the number of characters at the start of s1 matching one of the characters in s2
size_t strspn(const char *s1, const char *s2);
Например, вот простая функция, которая разбивает свой строковый аргумент на слова, разделенные пробелом или пунктуацией:
void print_words(const char *str) {
const char *separators = " \t\r\n,.:;'-";
int len;
for (;;) {
/* skip separators */
str += strspn(str, separators);
if (*str == '\0')
break;
/* get the word length */
len = strcspn(str, separators);
/* output the word */
printf("%.*s\n", len, str);
/* skip the word */
str += len;
}
}