Strtok(3)

Содержание:

Возвращаемое значениеReturn Value

strtod возвращает значение числа с плавающей запятой, за исключением случаев, когда представление приведет к переполнению, в этом случае функция возвращает +/-HUGE_VAL.strtod returns the value of the floating-point number, except when the representation would cause an overflow, in which case the function returns +/-HUGE_VAL. Знак HUGE_VAL соответствует знаку значения, которое не может быть представлено.The sign of HUGE_VAL matches the sign of the value that can’t be represented. strtod возвращает, если не удается выполнить преобразование или происходит потеря значимости.strtod returns if no conversion can be performed or an underflow occurs.

wcstod возвращает значения по аналогии с strtod:wcstod returns values analogously to strtod:

  • Для обеих функций в случае переполнения или потери значимости устанавливается значение ERANGE .For both functions, errno is set to ERANGE if overflow or underflow occurs.
  • Если присутствуют недопустимые Параметры, для параметра « еинвал » задается значение «равно» и вызывается обработчик недопустимых параметров, как описано в разделе Проверка параметров.If there are invalid parameters, errno is set to EINVAL and the invalid parameter handler is invoked, as described in Parameter Validation.

Дополнительные сведения об этих и других кодах возврата см. в разделе _doserrno, Code/Code, _sys_errlist и _sys_nerr.For more information on this and other return codes, see _doserrno, errno, _sys_errlist, and _sys_nerr.

пример

Функция разбивает строку на меньшие строки или жетоны, используя набор разделителей.

Выход:

Строка разделителей может содержать один или несколько разделителей, и с каждым вызовом могут использоваться разные строки разделителя.

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

Обратите внимание: поскольку не выделяет новую память для токенов, она изменяет исходную строку. То есть в приведенном выше примере строка будет обрабатываться для создания маркеров, на которые ссылается указатель, возвращаемый вызовами

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

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

является ни потокобезопасным, ни повторным, поскольку он использует статический буфер при разборе. Это означает, что если функция вызывает , никакая функция, которую она вызывает при использовании также может использовать , и она не может быть вызвана любой функцией, которая сама использует .

Пример, демонстрирующий проблемы, вызванные тем, что не является повторным, выглядит следующим образом:

Выход:

Ожидаемая операция является то , что наружный во цикла должно создать три маркера , состоящие из каждой строки десятичных чисел ( , , ), для каждого из которых предусматривает внутренний цикл должен разделить его на отдельные ( , , , , , ).

Однако, поскольку не является повторным, этого не происходит. Вместо этого первый правильно создает токен «1,2 \ 0», а внутренний цикл правильно создает токены и . Но тогда во внешнем цикле находится в конце строки, используемой внутренним циклом, и немедленно возвращает NULL. Вторая и третья подстроки массива вообще не анализируются.

C11

Стандартные библиотеки C не содержат потокобезопасную или повторную версию, но некоторые другие, например POSIX ‘

Обратите внимание, что в MSVC эквивалент является потокобезопасным

C11

C11 имеет необязательную часть, приложение K, которая предлагает поточно-безопасную и повторную версию с именем . Вы можете протестировать эту функцию с помощью . Эта дополнительная часть не поддерживается широко.

Функция отличается от функции POSIX ее от хранения за пределами токенированной строки и проверяя ограничения времени выполнения. Однако при правильно написанных программах и ведут себя одинаково.

Использование с примером теперь дает правильный ответ, например:

И выход будет:

Previous
Next

Исходный код программы

#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);
        exit(EXIT_FAILURE);
    }
    for (j = 1, str1 = argv; ; j++, str1 = NULL) {
        token = strtok_r(str1, argv, &saveptr1);
        if (token == NULL)
            break;
        printf("%d: %s\n", j, token);
        for (str2 = token; ; str2 = NULL) {
            subtoken = strtok_r(str2, argv, &saveptr2);
            if (subtoken == NULL)
                break;
            printf("	 --> %s\n", subtoken);
        }
    }
    exit(EXIT_SUCCESS);
}

Ещё один пример программы, использующей strtok(), можно найти в
getaddrinfo_a(3).

Функция strcmp( )

Скрыть рекламу в статье

Функция strcmp( )

     Предположим, что вы хотите сравнить чей-то ответ со строкой, находящейся в памяти:

/* Будет ли это работать? */

#include <stdio.h>

#define ANSWER  » Грант»

main( )

{

char try ;

puts(» Кто похоронен в могиле Гранта?» );

gets(try);

while(try != ANSWER)

puts(» Нет, неверно. Попытайтесь еще раз.» );

gets(try);

} puts(» Правильно.»);

}

     Хотя эта программа и смотрится неплохо, она не будет работать правильно, try и ANSWER на самом деле являются указателями, поэтому сравнение (try != ANSWER) спрашивает не о том, одинаковы ли эти две строки, а одинаковы ли два адреса, на которые ссылаются try и ANSWER. Так как ANSWER и try запоминаются в разных ячейках, эти два указателя никогда не могут быть одним и тем же, и пользователю всегда сообщается, что программа неверна. Такие программы обескураживают людей.

     Нам нужна функция, которая сравнивает содержимое строк, а не их адреса. Можно было бы придумать ее, но это уже сделала за нас функция strcmp( ) (string comparision).

Теперь исправим нашу программу:

/* это будет работать */

#includе <stdio.h>

#define ANSWER » Грант»

main( )

{

char try ;

puts(» Кто похоронен в могиле Гранта?» );

gets(try);

while(strcmp(try, ANSWER) != 0)

{ puts(» Нет, неверно. Попытайтесь еще раз.»);

gets(try);

} puts(» Правильно!»);

}

     Так как ненулевые значения интерпретируются всегда как «true», мы можем сократить оператор while do while(strcmp(try, ANSWER)).

     Из этого примера можно сделать вывод, что strcmp( ) использует два указателя строк в качестве аргументов и возвращает значение 0, если эти две строки одинаковы. Прекрасно, если вы придете к такому выводу.

     Хорошо, что Strcmp( ) сравнивает строки, а не массивы. Поэтому, хотя массив try занимает 40 ячеек памяти, а » Грант» — только 6 (не забывайте, что одна нужна для нуль-символа), сравнение выполняется только с частью try, до его первого нуль-символа. Такую функцию strcmp( ) можно использовать для сравнения строк, находящихся в массивах разной длины.

     А что если пользователь ответил » ГРАНТ» или » грант» или «Улиссес С. Грант» ? Хорошо, если пользователю сказали, что он ошибся? Чтобы сделать программу гибкой, вы должны предусмотреть несколько допустимых правильных ответов. Здесь есть некоторые тонкости. Вы могли бы в операторе #define определить в качестве ответа » ГРАНТ» и написать функцию, которая превращает любой ответ только в это слово. Это устраняет проблему накопления, но остаются другие поводы для беспокойства.

     Между прочим, какое значение возвращает strcmp( ), если строки не одинаковы? Вот пример:

/* возвраты функции strcmp */

#include <a: stdio.h>

main( )

{

printf(» %d n» , strcmp( «A» , » A» ));

printf(» %d n» , strcmp( «A» , » B» ));

printf(» %d n» , strcmp( «B» , » A» ));

printf(» %d n» , strcmp( «C» , «A» ));

printf(» %d n» , strcmp(» apples», » apple»));

}

В результате получаем

0 -1

1

2 115

Как мы и предполагали, сравнение «А» с самим собой возвращает 0. Сравнение «А» с «В» дает -1, а «В» с «А» дает 1. Это наводит на мысль, что strcmp( ) возвращает отрицательное число, если первая строка предшествует второй в алфавитном порядке, или положительное число, если порядок иной. Кроме того, сравнение «С» с «А» дает 2 вместо 1. Картина проясняется: функция возвращает разницу между двумя символами в коде ASCII. В более общем смысле strcmp() передвигается вдоль строк до тех пор, пока не находит первую пару не совпадающих символов; затем она возвращает разницу в кодах ASCII. Например, в самом последнем примере «apples» и «apple» совпадают, кроме последнего символа ‘s’, в первой строке. Он сопоставляется с шестым символом в «apple», который является нуль-символом (0 в ASCII).

Возвращается значение

‘s’ — » = 115 — 0 = 115,

где 115 является кодом буквы ‘s’ в ASCII.

Обычно вам не нужно точно знать возвращаемое значение. Чаще всего вы только хотите знать, нуль это или нет, т. е. было ли совпадение. Или, может быть, вы пытаетесь отсортировать строки в алфавитном порядке и хотите узнать, в каком случае сравнение дает положительный, отрицательный или нулевой результат.

Можно использовать эту функцию, чтобы проверить, остановится ли программа, читая вводимую информацию:

/* Начало какой-то программы */

#include &stdio.h&

#define SIZE 81

#define LIM 100

#define STOP   »  »  /* нулевая строка */

main( )

{

static char input;

int ct = 0;

while(gets(input) != NUL  && strcmp(input.STOP) !=0

                                && ct++ < LIM)

}

     Программа прекращает чтение вводимой строки, если встречает символ EOF , или если вы нажимаете клавишу в начале строки (т.e. введете пустую строку), или если вы достигли предела LIM. Чтение пустой строки дает пользователю простой способ прекращения ввода.

Давайте перейдем к последней из обсуждаемых нами функций, работающих со строками.

Оглавление книги

Возвращаемое значениеReturn Value

Возвращает указатель на следующий токен, найденный в str.Returns a pointer to the next token found in str. Возвращает значение NULL , если больше не найдено маркеров.Returns NULL when no more tokens are found. Каждый вызов изменяет функцию str , подставляя символ NULL для первого разделителя, который происходит после возвращаемого маркера.Each call modifies str by substituting a null character for the first delimiter that occurs after the returned token.

Ситуации, которые могут привести к ошибкеError Conditions

strstr разделителиdelimiters contextcontext Возвращаемое значениеReturn value errnoerrno
ЗАКАНЧИВАЮЩNULL anyany указатель на указатель NULLpointer to a null pointer ЗАКАНЧИВАЮЩNULL еинвалEINVAL
anyany ЗАКАНЧИВАЮЩNULL anyany ЗАКАНЧИВАЮЩNULL еинвалEINVAL
anyany anyany ЗАКАНЧИВАЮЩNULL ЗАКАНЧИВАЮЩNULL еинвалEINVAL

Если str имеет значение NULL , а контекст является указателем на допустимый указатель контекста, то ошибка отсутствует.If str is NULL but context is a pointer to a valid context pointer, there’s no error.

Description

The strtok() function parses a string into a sequence of tokens. On the first call to strtok() the string to be parsed should be specified in
str. In each subsequent call that should parse the same string, str should be NULL.

The delim argument specifies a set of bytes that delimit the tokens in the parsed string. The caller may specify different strings in delim in
successive calls that parse the same string.

Each call to strtok() returns a pointer to a null-terminated string containing the next token. This string does not include the delimiting byte. If
no more tokens are found, strtok() returns NULL.

A sequence of two or more contiguous delimiter bytes in the parsed string is considered to be a single delimiter. Delimiter bytes at the start or end of the
string are ignored. Put another way: the tokens returned by strtok() are always nonempty strings.

The strtok_r() function is a reentrant version strtok(). The saveptr argument is a pointer to a char * variable that is used
internally by strtok_r() in order to maintain context between successive calls that parse the same string.

On the first call to strtok_r(), str should point to the string to be parsed, and the value of saveptr is ignored. In subsequent calls,
str should be NULL, and saveptr should be unchanged since the previous call.

Different strings may be parsed concurrently using sequences of calls to strtok_r() that specify different saveptr arguments.

Description

The strtok() function parses a string into a sequence of tokens. On the first call to strtok() the string to be parsed should be specified in
str. In each subsequent call that should parse the same string, str should be NULL.

The delim argument specifies a set of bytes that delimit the tokens in the parsed string. The caller may specify different strings in delim in
successive calls that parse the same string.

Each call to strtok() returns a pointer to a null-terminated string containing the next token. This string does not include the delimiting byte. If
no more tokens are found, strtok() returns NULL.

A sequence of two or more contiguous delimiter bytes in the parsed string is considered to be a single delimiter. Delimiter bytes at the start or end of the
string are ignored. Put another way: the tokens returned by strtok() are always nonempty strings.

The strtok_r() function is a reentrant version strtok(). The saveptr argument is a pointer to a char * variable that is used
internally by strtok_r() in order to maintain context between successive calls that parse the same string.

On the first call to strtok_r(), str should point to the string to be parsed, and the value of saveptr is ignored. In subsequent calls,
str should be NULL, and saveptr should be unchanged since the previous call.

Different strings may be parsed concurrently using sequences of calls to strtok_r() that specify different saveptr arguments.

СинтаксисSyntax

ПараметрыParameters

strTokenstrTokenСтрока, содержащая токен или токены.String containing token or tokens.

стрделимитstrDelimitНабор символов-разделителей.Set of delimiter characters.

localelocaleИспользуемый языковой стандарт.Locale to use.

contextcontextУказывает на память, используемую для хранения внутреннего состояния средства синтаксического анализа, чтобы средство синтаксического анализа можно было продолжить с того места, где он был отключен при следующем вызове wcstok.Points to memory used to store the internal state of the parser so that the parser can continue from where it left off the next time you call wcstok.

Example

The program below uses nested loops that employ strtok_r() to break a string into a two-level hierarchy of tokens. The first command-line argument
specifies the string to be parsed. The second argument specifies the delimiter byte(s) to be used to separate that string into «major» tokens. The third
argument specifies the delimiter byte(s) to be used to separate the «major» tokens into subtokens.

An example of the output produced by this program is the following:

$ ./a.out 'a/bbb///cc;xxx:yyy:' ':;' '/'
1: a/bbb///cc
         --> a
         --> bbb
         --> cc
2: xxx
         --> xxx
3: yyy
         --> yyy

Program source

Another example program using strtok() can be found in getaddrinfo_a(3).

Работа с локалью


char* setlocale (int category, const char* locale);

Устанавливает локаль для данного приложения. Если locale равно NULL, то setlocale может быть использована для получения текущей локали.

Локаль хранит информацию о языке и регионе, специфичную для работы функций ввода, вывода и трансформации строк.
Во время работы приложения устанавливается локаль под названием «C», которая совпадает с настройками локали по умолчанию. Эта локаль содержит минимум информации, и работа программы максимально предсказуема. Локаль «C» также называется «».
Константы category определяют, на что воздействует изменение локали.

Значения параметра category
Имя На что влияет
LC_ALL На всю локаль
LC_COLLATE На поведение strcoll и strxfrm.
LC_CTYPE На поведение функций, работающих с символами.
LC_NUMERIC На десятичный разделитель в числах.
LC_TIME На поведение strftime.

Строка locale содержит имя локали, например «En_US» или «cp1251»

Q&A

Всё ещё не понятно? – пиши вопросы на ящик

RemarksRemarks

Каждая функция преобразует входную строку стрсаурце в .Each function converts the input string strSource to a . Функция strtod преобразует стрсаурце в значение двойной точности.The strtod function converts strSource to a double-precision value. strtod прекращает чтение строки стрсаурце на первом символе, который он не может распознать как часть числа.strtod stops reading the string strSource at the first character it can’t recognize as part of a number. Этот символ может быть завершающим нулевым символом.This character may be the terminating null character. wcstod — это версия strtodдля расширенных символов; его аргумент стрсаурце является строкой расширенных символов.wcstod is a wide-character version of strtod; its strSource argument is a wide-character string. В остальном эти функции ведут себя одинаково.These functions behave identically otherwise.

По умолчанию глобальное состояние этой функции ограничивается приложением.By default, this function’s global state is scoped to the application. Чтобы изменить это, см. раздел глобальное состояние в CRT.To change this, see Global state in the CRT.

Универсальное текстовое сопоставление функцийGeneric-Text Routine Mappings

Подпрограмма TCHAR.HTCHAR.H routine _UNICODE и _MBCS не определены_UNICODE & _MBCS not defined _MBCS определено_MBCS defined _UNICODE определено_UNICODE defined
_tcstod_tcstod strtodstrtod strtodstrtod wcstodwcstod
_tcstod_l_tcstod_l _strtod_l_strtod_l _strtod_l_strtod_l _wcstod_l_wcstod_l

Параметр категории LC_NUMERIC текущего языкового стандарта определяет распознавание символа точки основания в стрсаурце.The LC_NUMERIC category setting of the current locale determines recognition of the radix point character in strSource. Дополнительные сведения см. в разделе setlocale.For more information, see setlocale. Функции без суффикса _l используют текущий языковой стандарт; _strtod_l идентичен _strtod_l за исключением того, что они используют переданный языковой стандарт .The functions without the _l suffix use the current locale; _strtod_l is identical to _strtod_l except they use the locale passed in instead. Для получения дополнительной информации см. Locale.For more information, see Locale.

Если ендптр не равно NULL, то указатель на символ, который остановил просмотр, хранится в расположении, на которое указывает ендптр.If endptr isn’t NULL, a pointer to the character that stopped the scan is stored at the location pointed to by endptr. Если не удается выполнить преобразование (не найдены допустимые цифры или указана недопустимая база), значение стрсаурце хранится в расположении, на которое указывает ендптр.If no conversion can be performed (no valid digits were found or an invalid base was specified), the value of strSource is stored at the location pointed to by endptr.

strtod ждет, что стрсаурце указывает на строку одной из следующих форм:strtod expects strSource to point to a string of one of the following forms:

{цифры | цифрысистемы счисления } цифры] {0x | 0x} {хексдигитс | основание системы счисления hexdigits] цифры] {INF | бесконечность} NaN {digits | radix digits} digits] {0x | 0X} {hexdigits | radix hexdigits} digits] {INF | INFINITY} NAN

Example

The program below uses nested loops that employ strtok_r() to break a string into a two-level hierarchy of tokens. The first command-line argument
specifies the string to be parsed. The second argument specifies the delimiter byte(s) to be used to separate that string into «major» tokens. The third
argument specifies the delimiter byte(s) to be used to separate the «major» tokens into subtokens.

An example of the output produced by this program is the following:

$ ./a.out 'a/bbb///cc;xxx:yyy:' ':;' '/'
1: a/bbb///cc
         --> a
         --> bbb
         --> cc
2: xxx
         --> xxx
3: yyy
         --> yyy

Program source

Another example program using strtok() can be found in getaddrinfo_a(3).

EXAMPLES top

       The program below uses nested loops that employ strtok_r() to break a
       string into a two-level hierarchy of tokens.  The first command-line
       argument specifies the string to be parsed.  The second argument
       specifies the delimiter byte(s) to be used to separate that string
       into "major" tokens.  The third argument specifies the delimiter
       byte(s) to be used to separate the "major" tokens into subtokens.

       An example of the output produced by this program is the following:

           $ ./a.out 'a/bbb///cc;xxx:yyy:' ':;' '/'
           1: a/bbb///cc
                    --> a
                    --> bbb
                    --> cc
           2: xxx
                    --> xxx
           3: yyy
                    --> yyy

   Program source

       #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, "Usage: %s string delim subdelim\n",
                       argv);
               exit(EXIT_FAILURE);
           }

           for (j = 1, str1 = argv; ; j++, str1 = NULL) {
               token = strtok_r(str1, argv, &saveptr1);
               if (token == NULL)
                   break;
               printf("%d: %s\n", j, token);

               for (str2 = token; ; str2 = NULL) {
                   subtoken = strtok_r(str2, argv, &saveptr2);
                   if (subtoken == NULL)
                       break;
                   printf(" --> %s\n", subtoken);
               }
           }

           exit(EXIT_SUCCESS);
       }

       Another example program using strtok() can be found in
       getaddrinfo_a(3).

Esempio

La funzione spezza una stringa in stringhe più piccole, o token, usando un set di delimitatori.

Produzione:

La stringa di delimitatori può contenere uno o più delimitatori e diverse stringhe delimitatori possono essere utilizzate con ogni chiamata a .

Le chiamate a per continuare a tokenizzare la stessa stringa sorgente non dovrebbero passare di nuovo la stringa sorgente, ma passare come primo argomento. Se viene passata la stessa stringa sorgente, il primo token verrà invece ridenominato. Cioè, dati gli stessi delimitatori, restituirebbe semplicemente il primo token di nuovo.

Notare che come non alloca nuova memoria per i token, modifica la stringa di origine . Cioè, nell’esempio precedente, la stringa verrà manipolata per produrre i token a cui fa riferimento il puntatore restituito dalle chiamate a . Ciò significa che la stringa di origine non può essere (quindi non può essere una stringa letterale). Significa anche che l’identità del byte di delimitazione viene persa (cioè nell’esempio il «,» e «!» Vengono effettivamente eliminati dalla stringa di origine e non è possibile stabilire quale carattere delimitatore corrisponde).

Si noti inoltre che più delimitatori consecutivi nella stringa di origine vengono considerati come uno; nell’esempio, la seconda virgola viene ignorata.

non è né thread-safe né ri-entrant perché usa un buffer statico durante l’analisi. Ciò significa che se una funzione chiama , nessuna funzione che chiama mentre sta usando può anche usare , e non può essere chiamata da alcuna funzione che sta usando .

Un esempio che dimostra i problemi causati dal fatto che non è rientrante è il seguente:

Produzione:

L’operazione prevista è che il ciclo esterno crei tre token costituiti da ogni stringa decimale ( , , ), per ognuno dei quali lo chiama il ciclo interno dovrebbe dividerlo in un separato stringhe di cifre ( , , , , , ).

Tuttavia, poiché non è rientranti, ciò non si verifica. Invece il primo crea correttamente il token «1.2 \ 0» e il ciclo interno crea correttamente i token e . Ma poi lo nel ciclo esterno è alla fine della stringa usata dal ciclo interno e restituisce immediatamente NULL. La seconda e la terza sottostringa dell’array non vengono affatto analizzate.

C11

Le librerie C standard non contengono una versione thread-safe o re-entrant ma altre, come POSIX ‘ . Nota che su MSVC l’equivalente , è thread-safe.

C11

C11 ha una parte opzionale, Annex K, che offre una versione thread-safe e re-entry chiamata . Puoi provare la funzione con . Questa parte facoltativa non è ampiamente supportata.

La funzione differisce dalla funzione POSIX dall’archiviazione all’esterno della stringa che viene tokenizzata e controllando i vincoli di runtime. Sui programmi scritti correttamente, però, e comportano allo stesso modo.

Usando con l’esempio ora si ottiene la risposta corretta, in questo modo:

E l’output sarà:

Previous
Next

ТребованияRequirements

ПодпрограммаRoutine Обязательный заголовокRequired header
strtok_sstrtok_s <string.h><string.h>
_strtok_s_l_strtok_s_l <string.h><string.h>
wcstok_s,wcstok_s,_wcstok_s_l_wcstok_s_l <string.h> или <wchar.h><string.h> or <wchar.h>
_mbstok_s,_mbstok_s,_mbstok_s_l_mbstok_s_l <mbstring.h><mbstring.h>

Дополнительные сведения о совместимости см. в статье Compatibility.For additional compatibility information, see Compatibility.

Универсальное текстовое сопоставление функцийGeneric-Text Routine Mappings

Подпрограмма TCHAR.HTCHAR.H routine _Юникод & _MBCS не определен_UNICODE & _MBCS not defined _Определенный MBCS_MBCS defined _UNICODE определено_UNICODE defined
_tcstok_s_tcstok_s strtok_sstrtok_s _mbstok_s_mbstok_s wcstok_swcstok_s
_tcstok_s_l_tcstok_s_l _strtok_s_l_strtok_s_l _mbstok_s_l_mbstok_s_l _wcstok_s_l_wcstok_s_l

Example

The function breaks a string into a smaller strings, or tokens, using a set of delimiters.

Output:

The string of delimiters may contain one or more delimiters and different delimiter strings may be used with each call to .

Calls to to continue tokenizing the same source string should not pass the source string again, but instead pass as the first argument. If the same source string is passed then the first token will instead be re-tokenized. That is, given the same delimiters, would simply return the first token again.

Note that as does not allocate new memory for the tokens, it modifies the source string. That is, in the above example, the string will be manipulated to produce the tokens that are referenced by the pointer returned by the calls to . This means that the source string cannot be (so it can’t be a string literal). It also means that the identity of the delimiting byte is lost (i.e. in the example the «,» and «!» are effectively deleted from the source string and you cannot tell which delimiter character matched).

Note also that multiple consecutive delimiters in the source string are treated as one; in the example, the second comma is ignored.

is neither thread safe nor re-entrant because it uses a static buffer while parsing. This means that if a function calls , no function that it calls while it is using can also use , and it cannot be called by any function that is itself using .

An example that demonstrates the problems caused by the fact that is not re-entrant is as follows:

Output:

The expected operation is that the outer loop should create three tokens consisting of each decimal number string (, , ), for each of which the calls for the inner loop should split it into separate digit strings (, , , , , ).

However, because is not re-entrant, this does not occur. Instead the first correctly creates the «1.2\0» token, and the inner loop correctly creates the tokens and . But then the in the outer loop is at the end of the string used by the inner loop, and returns NULL immediately. The second and third substrings of the array are not analyzed at all.

C11

The standard C libraries do not contain a thread-safe or re-entrant version but some others do, such as POSIX’ . Note that on MSVC the equivalent, is thread-safe.

C11

C11 has an optional part, Annex K, that offers a thread-safe and re-entrant version named . You can test for the feature with . This optional part is not widely supported.

The function differs from the POSIX function by guarding against storing outside of the string being tokenized, and by checking runtime constraints. On correctly written programs, though, the and behave the same.

Using with the example now yields the correct response, like so:

And the output will be:

Previous
Next

Remarks

The strtok function finds the next token in strToken. The set of characters in strDelimit specifies possible delimiters of the token to be found in strToken on the current call. wcstok and _mbstok are wide-character and multibyte-character versions of strtok. The arguments and return value of wcstok are wide-character strings; those of _mbstok are multibyte-character strings. These three functions behave identically otherwise.

The two argument version of wcstok is not standard. If you need to use that version, you’ll need to define before you (or ).

Important

These functions incur a potential threat brought about by a buffer overrun problem. Buffer overrun problems are a frequent method of system attack, resulting in an unwarranted elevation of privilege. For more information, see Avoiding Buffer Overruns.

On the first call to strtok, the function skips leading delimiters and returns a pointer to the first token in strToken, terminating the token with a null character. More tokens can be broken out of the remainder of strToken by a series of calls to strtok. Each call to strtok modifies strToken by inserting a null character after the token returned by that call. To read the next token from strToken, call strtok with a NULL value for the strToken argument. The NULL strToken argument causes strtok to search for the next token in the modified strToken. The strDelimit argument can take any value from one call to the next so that the set of delimiters may vary.

The output value is affected by the setting of the LC_CTYPE category setting of the locale. For more information, see setlocale.

The versions of these functions without the _l suffix use the current locale for this locale-dependent behavior. The versions with the _l suffix are identical except that they use the locale parameter passed in instead. For more information, see Locale.

Note

Each function uses a thread-local static variable for parsing the string into tokens. Therefore, multiple threads can simultaneously call these functions without undesirable effects. However, within a single thread, interleaving calls to one of these functions is highly likely to produce data corruption and inaccurate results. When parsing different strings, finish parsing one string before starting to parse the next. Also, be aware of the potential for danger when calling one of these functions from within a loop where another function is called. If the other function ends up using one of these functions, an interleaved sequence of calls will result, triggering data corruption.

By default, this function’s global state is scoped to the application. To change this, see Global state in the CRT.

Generic-Text Routine Mappings

TCHAR.H routine _UNICODE & _MBCS not defined _MBCS defined _UNICODE defined
_tcstok strtok _mbstok wcstok
_tcstok _strtok_l _mbstok_l _wcstok_l
Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *