strtok - извлечение элементов (токенов) из строки
strtok(3)
извлечение элементов (токенов) из строки
Other Alias
strtok_r
ОБЗОР
#include <string.h>
char *strtok(char *str, const char *delim);
char *strtok_r(char *str, const char *delim, char **saveptr);
Требования макроса тестирования свойств для glibc
(см. feature_test_macros(7)):
strtok_r(): _SVID_SOURCE || _BSD_SOURCE || _POSIX_C_SOURCE >= 1 ||
_XOPEN_SOURCE || _POSIX_SOURCE
ОПИСАНИЕ
Функция
strtok() разделяет строку на последовательность нуля или более
непустых токенов. При первом вызове
strtok() анализируемую строку нужно
указывать в аргументе
str. В каждом последующем вызове, в котором
анализируется эта же строка, значение
str должно быть NULL.
В аргументе delim задаётся набор байт, которые считаются разделителями
токенов в анализируемой строке. Вызывающий может указывать разные строки в
delim в последующих вызовах при анализе той же строки.
Каждый вызов strtok() возвращает указатель на строку, завершающуюся null,
которая содержит следующий токен. Эта строка не включает
байт-разделитель. Если больше токенов нет, то strtok() возвращает NULL.
Последовательность вызовов strtok(), оперирующих одной строкой,
поддерживает указатель, который определяет точку, с которой начинается поиск
следующего токена. Первый вызов strtok() назначает этому указателю ссылку
на первый байт строки. Начало следующего токена определяется поиском вперёд
в str следующего байта не разделителя. Если байт найден, то он берётся в
качестве начала следующего токена. Если такой байт не найден, то токенов
больше нет и strtok() возвращает NULL (для пустой строки или состоящей
только из разделителей в этом случае NULL вернётся при первом вызове
strtok()).
Конец каждого токена находится поиском вперёд, длящемся до тех пор, пока не
будет найден байт-разделитель или завершающий байт null ('\0'). Если
найден байт-разделитель, то он заменяется байтом null для завершения
текущего токена, и strtok() сохраняет указатель на следующий байт; этот
указатель будет использован в качестве начальной точки при поиске следующего
токена. В этом случае strtok() возвращает указатель на начало найденного
токена.
Из описания выше следует, что последовательность из двух и более непрерывных
байтов-разделителей в просматриваемой строке считается одним разделителем, а
байты-разделители в начале или конце строки игнорируются. Другими словами,
токены, возвращаемые strtok() — всегда не пустые строки. То есть,
например, если есть строка «aaa;;bbb,», то последующие вызовы strtok()
с заданными разделителями строк «;,» вернули бы строки «aaa» и
«bbb», а затем указатель null.
Функция strtok_r() является реентерабельной версией strtok(). Аргумент
saveptr является указателем на переменную char *, которая
используется внутри strtok_r() для учёта контекста между последующими
вызовами при анализе одной и той же строки.
При первом вызове strtok_r() значение str должно указывать на
анализируемую строку, а значение saveptr игнорируется. При последующих
вызовах значение str должно быть NULL, а значение saveptr не должно
изменяться с момента предыдущего вызова.
Одновременно могут анализироваться разные строки при нескольких запусках
strtok_r() с различными аргументами saveptr.
ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ
Функции
strtok() и
strtok_r() возвращают указатель на следующий токен
или NULL, если больше токенов нет.
АТРИБУТЫ
Описание терминов данного раздела смотрите в
attributes(7).
Интерфейс Атрибут Значение
strtok()
безвредность в потоках: небезопасно (MT-Unsafe race:strtok)
strtok_r()
безвредность в потоках: безвредно (MT-Safe)
СООТВЕТСТВИЕ СТАНДАРТАМ
strtok()
POSIX.1-2001, POSIX.1-2008, C89, C99, SVr4, 4.3BSD.
strtok_r()
POSIX.1-2001, POSIX.1-2008.
ДЕФЕКТЫ
Используйте данные функции с осторожностью. Учитывайте, что:
Эти функции изменяют свой первый аргумент.
Эти функции не могут использоваться со строками-константами.
Теряется идентичность байта-разделителя.
При анализе функция strtok() использует статический буфер, поэтому не
является безопасной для нитей. Используйте strtok_r() в этом случае.
ПРИМЕР
В программе, представленной далее, используются вложенные циклы, которые
вызывают strtok_r() для разделения строки на составляющие её токены. В
первом параметре командной строки задаётся анализируемая строка. Во втором
параметре задаётся байт(ы)- разделитель, который используется для деления
строки на «составные» токены. В третьем параметре указывается байт(ы)-
разделитель, который используется для разделения «составных» токенов на
подтокены.
Пример результата вывода программы:
$ ./a.out 'a/bbb///cc;xxx:yyy:' ':;' '/'
1: a/bbb///cc
--> a
--> bbb
--> cc
2: xxx
--> xxx
3: yyy
--> yyy
Исходный код программы
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int
main(int argc, char *argv[])
{
char *str1, *str2, *token, *subtoken;
char *saveptr1, *saveptr2;
int j;
if (argc != 4) {
fprintf(stderr, "Использование: %s string delim subdelim\n",
argv[0]);
exit(EXIT_FAILURE);
}
for (j = 1, str1 = argv[1]; ; j++, str1 = NULL) {
token = strtok_r(str1, argv[2], &saveptr1);
if (token == NULL)
break;
printf("%d: %s\n", j, token);
for (str2 = token; ; str2 = NULL) {
subtoken = strtok_r(str2, argv[3], &saveptr2);
if (subtoken == NULL)
break;
printf(" --> %s\n", subtoken);
}
}
exit(EXIT_SUCCESS);
}
Ещё один пример программы, использующей strtok(), можно найти в
getaddrinfo_a(3).