Strtok s c описание. Функции для обработки строк. Пример: исходный код программы
#include
Функция strtok() возвращает указатель на следующую лексему в строке, адресуемой параметром str1
. Символы, образующие строку, адресуемую параметром str2
, представляют собой разделители, которые определяют лексему. При отсутствии лексемы, подлежащей возврату, возвращается нулевой указатель.
В версии С99 к параметрам str1
и str2
применен квалификатор restrict .
Чтобы разделить некоторую строку на лексемы, при первом вызове функции strtok() параметр str1
должен указывать на начало этой строки. При последующих вызовах функции в качестве параметра str1
нужно использовать нулевой указатель. Этим способом вся строка разбивается на лексемы.
При каждом обращении к функции strtok() можно использовать различные наборы разделителей.
Пример
Эта программа разбивает строку «Травка зеленеет, солнышко блестит» на лексемы, разделителями которых служат пробелы и запятые. В результате получится
Травка|зеленеет|солнышко|блестит
#include
Описание
Функция strtok выполняет поиск лексем в строке string . Последовательность вызовов этой функции разбивают строку string на лексемы, которые представляют собой последовательности символов, разделенных символами разделителями.
На первый вызов, функция принимает строку string в качестве аргумента, чей первый символ используется в качестве начальной точки для поиска лексем. В последующие вызовы, функция ожидает нулевого указателя и использует позицию сразу после окончания последней лексемы как новое местонахождение для сканирования.
Для определения начала лексемы функция сначала определяет символы, не содержащиеся в строке delim , то есть они являются символами разделителями. А затем посимвольно проверяет остальную часть строки до первого символа-разделителя, который сигнализирует конец лексемы.
Этот конечный маркер автоматически заменяется нулевым символом, и лексема возвращается функцией. После этого, следующие вызовы функции strtok начинаются с этого нулевого символа.
Параметры:
- string
Строка для поиска в ней лексем. Содержание этой строки будет изменено, она разбивается на более мелкие строки (лексемы). Данный параметр может содержать нулевой указатель, в этом случае функция продолжает сканирование с того места, где был остановлен предыдущий успешный вызов функции. - delim
Строка, содержащая разделители. Они могут варьироваться от одного вызова к другому вызову функции.
Возвращаемое значение
Указатель на последнюю найденную лексему в строке.
Возвращается пустой указатель, если нет найденных лексем.
Пример: исходный код программы
//пример использования функции strtok #includeOther 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).
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 |
4 ответа
Две вещи, которые нужно знать о strtok . Как уже упоминалось, он "поддерживает внутреннее состояние". Кроме того, он испортил строку, которую вы ее кормите . По существу, он напишет "\0" , где он найдет маркер, который вы предоставили, и вернет указатель на начало строки. Внутренне он поддерживает расположение последнего токена; и в следующий раз, когда вы его назовете, он начнется оттуда.
Важным следствием является то, что вы не можете использовать strtok для строки типа const char* "hello world"; , так как вы получите нарушение доступа при изменении содержимого строки const char* .
"Хорошая вещь" в strtok заключается в том, что на самом деле она не копирует строки, поэтому вам не нужно управлять дополнительным распределением памяти и т.д. Но если вы не поймете вышеизложенное, у вас возникнут проблемы с его использованием.
Пример. Если у вас есть "это, есть, строка", последовательные вызовы strtok будут генерировать указатели следующим образом (значение ^ - это возвращаемое значение). Обратите внимание, что добавляется "\0" , где найдены токены; это означает, что исходная строка изменена:
T h i s , i s , a , s t r i n g \0 this,is,a,string t h i s \0 i s , a , s t r i n g \0 this ^ t h i s \0 i s \0 a , s t r i n g \0 is ^ t h i s \0 i s \0 a \0 s t r i n g \0 a ^ t h i s \0 i s \0 a \0 s t r i n g \0 string ^
Надеюсь, что это имеет смысл.
Функция strtok() хранит данные между вызовами. Он использует эти данные, когда вы вызываете его с помощью указателя NULL.
Точка, в которой был найден последний токен, хранится внутри с помощью функции, которая будет использоваться при следующем вызове (для предотвращения сбоев данных не требуется реализация конкретной библиотеки).
strtok поддерживает внутреннее состояние. Когда вы вызываете его с не-NULL, он повторно инициализирует себя, чтобы использовать строку, которую вы поставляете. Когда вы вызываете его с помощью NULL , он использует эту строку и любое другое состояние, которое оно в настоящее время получает, чтобы вернуть следующий токен.
В связи с тем, как работает strtok , вам необходимо убедиться, что вы связываетесь с многопоточной версией среды выполнения C, если вы пишете многопоточное приложение. Это гарантирует, что каждый поток получит собственное внутреннее состояние для strtok .
Функция strtok хранит данные во внутренней статической переменной, которая распределяется между всеми потоками.
Для обеспечения безопасности потоков вы должны использовать strtok_r
Взгляните на static char *last;
Char * strtok(s, delim) register char *s; register const char *delim; { register char *spanp; register int c, sc; char *tok; static char *last; if (s == NULL && (s = last) == NULL) return (NULL); /* * Skip (span) leading delimiters (s += strspn(s, delim), sort of). */ cont: c = *s++; for (spanp = (char *)delim; (sc = *spanp++) != 0;) { if (c == sc) goto cont; } if (c == 0) { /* no non-delimiter characters */ last = NULL; return (NULL); } tok = s - 1; /* * Scan token (scan for delimiters: s += strcspn(s, delim), sort of). * Note that delim must have one NUL; we stop if we see that, too. */ for (;;) { c = *s++; spanp = (char *)delim; do { if ((sc = *spanp++) == c) { if (c == 0) s = NULL; else s[-1] = 0; last = s; return (tok); } } while (sc != 0); } /* NOTREACHED */ }
поделиться