разработал альтернативу strtok - PullRequest
4 голосов
/ 23 марта 2009

Я разработал собственную версию strtok. Просто чтобы попрактиковаться в использовании указателей.

Может кто-нибудь увидеть какие-либо ограничения с этим или в любом случае я могу улучшить.

void stvstrtok(const char *source, char *dest, const char token) 
{
    /* Search for the token. */
    int i = 0;
    while(*source)
    {
        *dest++ = *source++;
        if(*source == token)
        {
            source++;
        }
    }
    *dest++ = '\0';
    }

int main(void)
{
    char *long_name = "dog,sat ,on ,the,rug,in ,front,of,the,fire";
    char buffer[sizeof(long_name)/sizeof(*long_name)];

    stvstrtok(long_name, buffer, ',');

    printf("buffer: %s\n", buffer);

   getchar();

   return 0;
}

Ответы [ 7 ]

7 голосов
/ 23 марта 2009

Примечание: Слово «токен» обычно используется для описания возвращаемых частей строки. Разделитель используется для описания вещи, которая разделяет токены. Поэтому, чтобы сделать ваш код более понятным, вы должны переименовать токен в разделитель и переименовать dest в token_dest.

Различия в вашей функции и strtok:

Есть несколько различий между вашей функцией и strtok.

  • Ваша функция просто удаляет разделители токенов
  • Вы вызываете свою функцию только один раз, чтобы обработать все части строки. С помощью strtok вы вызываете его несколько раз для каждой части строки (последующие времена с NULL в качестве первого параметра).
  • strtok также уничтожает исходную строку, тогда как ваш код использует свой собственный буфер (я думаю, лучше использовать свой собственный буфер, как вы это сделали).
  • strtok сохраняет позицию следующего токена после каждого вызова, где первый параметр равен NULL. Эта позиция затем используется для последующих вызовов. Это не потокобезопасный, хотя и ваша функция будет потокобезопасной.
  • strtok может использовать несколько разных разделителей, тогда как ваш код использует только один.

При этом я дам советы о том, как сделать лучшую функцию, а не функцию, которая ближе к реализации strtok.

Как улучшить свою функцию (не эмулировать strtok):

Я думаю, что было бы лучше внести следующие изменения:

  • Пусть ваша функция просто вернет следующий токен
  • Прервите цикл, когда у вас есть * source или * source == delimiter
  • Возвращает указатель на первый символ вашей исходной строки, который содержит следующий токен. Этот указатель можно использовать для последующих вызовов.
3 голосов
/ 23 марта 2009

Этот код не работает совсем как strtok(). Что именно ты пытался сделать? Но что касается улучшений, в вашем коде есть серьезная ошибка: если длина source, вычтенная из числа вхождений token, больше длины dest, вы получите очень классическую Переполнение стека , что мне покажется несколько ироничным. Этого не произойдет в main, который вы использовали, но использование функции в другом месте неизбежно приведет вас на путь неопределенности и отчаяния.

1 голос
/ 22 мая 2009

Кстати, long_name это указатель на char, а sizeof (long_name) это sizeof (char *). не тот размер, на который указывает длинное имя.

1 голос
/ 23 марта 2009

Кроме того, strtok (...) поддерживает несколько символов-разделителей. Посмотрите определения strspn (...) и strcspn (...), так как они могут быть использованы для повторной реализации strtok (...).

1 голос
/ 23 марта 2009

strtok уничтожает входную строку с символом NUL, что делает ее несколько враждебной.

Вам также нужно рассмотреть в случае "xyz ,, pdq", сколько токенов вытащит strtok из этой строки, если ',' является разделителем.

Что вы хотите, чтобы ваша функция делала в этом случае?

1 голос
/ 23 марта 2009

strtok () сохранит некоторое состояние, поэтому вы можете вызывать его несколько раз, чтобы получить несколько токенов. Кроме того, strtok () будет «разбивать» исходную строку, чтобы вы получили несколько строк назначения, каждая из которых является токеном.

Весь ваш код, насколько я вижу, игнорирует любой входной символ, равный разделителю токенов, и продолжает копирование до нулевого завершения источника.

edit: Кроме того, учтите, что существует два последовательных токена-разделителя: первый будет игнорироваться вашей функцией, второй будет записан в место назначения, тогда как strtok () определит последовательность из 2 или более разделителей как один разделитель (справочная страница: http://man.cx/?page=strtok)

1 голос
/ 23 марта 2009

strtok позволяет перебирать все токены. Он делает это, предполагая, что исходная строка доступна для записи, и вставляя в нее нулевые значения при разрыве токена. Целевой буфер - это указатель на смещение символа в исходном буфере. Вы можете использовать этот факт, чтобы знать, когда вы достигли конца + и также сохранять «состояние» между вызовами.

Strtok не подходит для использования, поскольку уничтожает исходную строку. Это также не повторный вход.

...