#include
Функция strtok() возвращает указатель на следующую лексему в строке, адресуемой параметром str1
. Символы, образующие строку, адресуемую параметром str2
, представляют собой разделители, которые определяют лексему. При отсутствии лексемы, подлежащей возврату, возвращается нулевой указатель.
В версии С99 к параметрам str1
и str2
применен квалификатор restrict .
Чтобы разделить некоторую строку на лексемы, при первом вызове функции strtok() параметр str1
должен указывать на начало этой строки. При последующих вызовах функции в качестве параметра str1
нужно использовать нулевой указатель. Этим способом вся строка разбивается на лексемы.
При каждом обращении к функции strtok() можно использовать различные наборы разделителей.
Пример
Эта программа разбивает строку «Травка зеленеет, солнышко блестит» на лексемы, разделителями которых служат пробелы и запятые. В результате получится
Травка|зеленеет|солнышко|блестит
#include
Other Alias
strtokОБЗОР
#include
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Ещё один пример программы, использующей strtok (), можно найти в getaddrinfo_a (3).
char far * far _fstrtok(const char far *str1, const char far *str2)
Описание:
Функция strtok() возвращает указатель на следующую лексему в строке, на которую указывает str1. Символы из строки, на которую указывает str2, используются как ограничители, определяющие лексему. Если лексема не найдена, возвращается NULL.
Во время первого вызова функции strtok() в качестве указателя в самом деле используется str1. При последующих вызовах в качестве первого аргумента используется NULL. Таким образом вся строка может быть разбита на лексемы.
Важно понимать, что функция strtok() модифицирует строку, на которую указывает str1. Каждый раз, когда найдена лексема, на месте, где был найден ограничитель, помещается нулевой символ. Таким образом strtok() продвигается вдоль строки.
При каждом вызове strtok() можно варьировать набор ограничителей.
Функция _fstrtok() является FAR-версией рассматриваемой функции.
Следующая программа разбивает на лексемы строку «The summer soldier,
the sunshine patriot»,
используя в качестве ограничителей пробелы и запятые. В результате работы программы будет сформирована строка следующего вида:
«The |
summer |
soldier |
the |
sunshine |
patriot».
#include
#include
int
main(void
)
{
char
*
p;
p =
strtok
("The summer soldier, the sunshine patriot"
,
" "
)
;
printf
(p)
;
do
{
p=
strtok
("\0
"
,
", "
)
;
if
(p)
printf
("|% s"
,
p)
;
}
while
(p)
;
return
0
;
}
Языки программирования могут включать специальные функции для работы со строками, избавляя тем самым программиста от необходимости писать собственные функции обработки строк. Например, часто требуется определить длину строки, и поэтому в языках предусмотрена функция, измеряющая ее длину.
В языке программирования C функции для работы со строками объявляются в заголовочном файле string.h, который надо не забывать подключать к своему исходному коду. Существует около двадцати функций для работы со строками. Среди них есть те, которые осуществляют поиск символов в строке, функции сравнения, копирования строк, а также более специфические. Перечень и описание большинства существующих на данный момент в языке C функций можно найти в приложении книги Б. Кернигана, Д. Ритчи "Язык программирования C. Второе издание".
Все функции, объявленные в string.h, в процессе своей работы могут изменять или не изменять одну из переданных по указателю строк. Это зависит от назначения функции. Однако большинство из них что-то возвращают: либо указатель на символ, либо целое. При этом если функция меняет один из своих параметров и ради этого была вызвана, тогда то, что она возвращает, можно проигнорировать (т.е. ничему не присваивать в вызывающей функции).
Например, функция strcpy() имеет такое объявление: char *strcpy (char *, const char*) . Она копирует строку, на которую указывает второй параметр, в строку, на которую указывает первый параметр. Таким образом первый параметр изменяется. Кроме того, функция возвращает указатель на первый символ строки:
char s1[ 10 ] , s2[ 10 ] ; char * s3; s3 = s2; gets (s1) ; s3 = strcpy (s2, s1) ; puts (s2) ; puts (s3) ; printf ("%p, %p\n " , s2, s3) ;
Здесь s2 и s3 указывают на один и тот же символ (printf() выводит одинаковые адреса). Однако то, что возвращает strcpy() , нельзя присвоить массиву. Результат работы этой функции обычно ничему не присваивают; бывает достаточно того, что она просто изменяет одну из переданных по указателю строк.
Другое дело, такие функции как strlen() или strcmp() , которые не изменяют параметры, а вызываются ради результата. Функция strcmp() сравнивает две строки-аргумента по буквам (лексикографически) и возвращает 0, -1 или 1. Например, вызов strcmp("boy", "body") вернет 1, т.к. код буквы "y" больше буквы "d". Вызов strcmp("body", "boy") вернет -1, т.к. первый аргумент лексикографически меньше второго.
Функция strtok()
С помощью функции strtok() можно разбить строку на отдельные части (лексемы). Объявление этой функции выглядит так char *strtok (char *, const char *) . При первом вызове функции в качестве первого параметра указывается строка, которую требуется разбить. Вторым параметром указывается строка-разделитель. При последующих вызовах функции для этой же строки первым параметром должен быть NULL, т.к. функция уже "запомнила" с чем работает. Рассмотрим пример:
char str = "one, two, three, four, five" ; char * sp; sp = strtok (str, ", " ) ; while (sp) { puts (sp) ; sp = strtok (NULL, ", " ) ; }
В результате выполнения данного кода на экран в столбик выводятся слова:
One two three four five
При первом вызове strtok() в функцию передается указатель на первый символ массива и строка-разделитель. После этого вызова массив str изменяется, в нем остается только слово "one", также функция возвращает указатель на это слово, который присваивается sp.
Хотя мы потеряли остаток массива в вызывающей функции, однако внутри strtok() сохраняется указатель на остаток массива. Когда передается NULL, функция "знает", что надо работать с этим "хвостом".
Копирование частей строк
Когда требуется просто соединить две строки, то проблема легко решается с помощью вызова функции strcat() , которая к концу первого аргумента присоединяет второй. Похожая функция strncat() присоединяет n символов второй строки к первой. n указывается в качестве третьего параметра.
Что если ситуация более сложная? Например, есть две непустые строки и надо соединить начало первой и конец второй. Сделать это можно с помощью функции strcpy() , если передавать ссылки не на первые символы строк:
char s1[ 20 ] = "Peter Smith" , s2 = "Julia Roberts" ; strcpy (s1+ 5 , s2+ 5 ) ; puts (s1) ;
В данном случае на экране будет выведено "Peter Roberts". Почему так произошло? В функцию strcpy() был передан указатель на шестой символ первой строки. Это привело к тому, что при копировании символы этой строки затираются только начиная с 6-го, т.к. strcpy() о предыдущих символах ничего не "знает". В качестве второго аргумента также передается только часть строки, которая и копируется в первую.
Как вставить одну строку в середину другой? Можно решить эту задачу, используя третью "буферную" строку, куда можно сначала скопировать первую строку, потом вторую, затерев конец первой, потом присоединить конец первой. Но можно поступить и так:
char s1[ 20 ] = "one three" , s2[ 20 ] = "two" ; strcpy (s2+ 3 , s1+ 3 ) ; strcpy (s1+ 4 , s2) ; puts (s1) ;
Здесь сначала во вторую строку копируется конец первой, получается "two three". Затем в первую строку, минуя ее начало, копируется вторая.
Описание некоторых функций для работы со строками
Задание
Ниже представлены описания некоторых функций, выполняющих операции над строками. Придумайте и напишите маленькие программы, иллюстрирующие работу этих функций.
- char *strchr (const char *, int c) . Возвращает указатель на первое вхождение символа с в строку. Возвращает NULL, если такого символа в строке нет.
- char *strstr (const char *s2, const char *s1) . Возвращает указатель на первое вхождение строки s1 в строку s2. Если совпадений нет, возвращает NULL.
- char *strncpy (char *, const char *, size_t n) . Копирует n символов второй строки в первую.
- size_t strspn (const char *, const char *) . Возвращает длину начала первой строки, в которую входят символы, из которых состоит вторая строка.
1) Находит следующий токен в строке байта с нулевым завершением, на который указывает str . Символы разделителя идентифицируются нулевой строкой байта, на которую указывает delim .
Эта функция называется многократным умножением для получения последовательных токенов из одной и той же строки.
- Если str ! = NULL str ! = NULL , вызов обрабатывается как первый вызов strtok для этой конкретной строки. Функция выполняет поиск первого символа, который не содержится в delim .
- Если такого символа не было найдено, то в нем нет токенов, а функция возвращает нулевой указатель.
- Если такой символ был найден, это будет начало токена . Затем функция выполняет поиск с этой точки для первого символа, который содержится в delim .
- Если такой символ не найден, str имеет только один токен, а будущие вызовы strtok возвращают нулевой указатель
- Если такой символ был найден, он заменяется нулевым символом "\0" и указатель на следующий символ сохраняется в статическом месте для последующих вызовов.
- Затем функция возвращает указатель на начало токена
- Если str == NULL , вызов обрабатывается как последующие вызовы strtok: функция продолжается от того места, где она осталась в предыдущем вызове. Поведение такое же, как если бы ранее сохраненный указатель передавался как str .
Поведение не определено, если str или delim не является указателем на строку байта с нулевым завершением.
2) То же, что и (1) , за исключением того, что на каждом шаге записывается количество символов, оставшихся для просмотра в str на *strmax и записывает внутреннее состояние токенизатора в *ptr . Повторные вызовы (с нулевой strmax) должны передавать strmax и ptr со значениями, сохраненными предыдущим вызовом. Кроме того, во время выполнения обнаруживаются следующие ошибки и вызывается текущая установленная функция обработчика ограничений , не сохраняя ничего в объекте, на который указывает ptr
- strmax , delim или ptr - нулевой указатель
- при не начальном вызове (с нулевой str), *ptr - нулевой указатель
- при первом вызове *strmax равен нулю или больше, чем RSIZE_MAX
- поиск конца токена достигает конца исходной строки (как измеряется начальным значением *strmax)), не встречая нулевого терминатора
Поведение не определено, если обе str указывает на массив символов, который не имеет нулевого символа, и strmax указывает на значение, которое больше размера этого массива символов. Как и все связанные с проверкой границ функции, strtok_s гарантированно будет доступен только в том случае, если __STDC_LIB_EXT1__ определяется реализацией, и если пользователь определяет __STDC_WANT_LIB_EXT1__ для целочисленной константы 1 прежде чем включать string.h .
параметры
Возвращаемое значение
Возвращает указатель на начало следующего токена или NULL если больше нет токенов.
Заметка
Эта функция разрушительна: она записывает символы "\0" в элементах строки str . В частности, строковый литерал не может использоваться в качестве первого аргумента strtok .
Каждый вызов strtok изменяет статическую переменную: не является потокобезопасной.
В отличие от большинства других токенизаторов, разделители в strtok могут быть разными для каждого последующего токена и могут даже зависеть от содержимого предыдущих токенов.
Функция strtok_s отличается от функции POSIX strtok_r ее от хранения за пределами токенированной строки и проверяя ограничения времени выполнения.
пример
#define __STDC_WANT_LIB_EXT1__ 1
#include
Возможный выход:
Parsing the input string "A bird came down the walk" A bird came down the walk Contents of the input string now: "A\0bird\0came\0down\0the\0walk\0" Parsing the input string "A bird came down the walk" A bird came down the walk Contents of the input string now: "A\0bird\0came\0down\0the\0walk\0"
- C11 (ISO / IEC 9899: 2011):
- 7.24.5.8 Функция strtok (p: 369-370)
- K.3.7.3.1 Функция strtok_s (p: 620-621)
- C99 (ISO / IEC 9899: 1999):
- 7.21.5.8 Функция strtok (p: 332-333)
- C89 / C90 (ISO / IEC 9899: 1990):
- 4.11.5.8 Функция strtok
находит первое местоположение любого символа в одной строке, в другой строке (функция) |
|
только символов, не найденных в другой строке байта (функция) |
|
возвращает длину максимального начального сегмента, которая состоит из только символов, найденных в другой строке байта (функция) |
|
(C95) (C11) | находит следующий токен в широкой строке (функция) |
Документация C ++ для strtok |