Пожалуйста, объясните мне, как работает strtok()
функция. В руководстве сказано, что строка разбивается на токены. Я не могу понять из руководства, что он на самом деле делает.
Я добавил часы str
и, *pch
чтобы проверить их работу, когда возник первый цикл while, содержимое str
было только «this». Как результат, показанный ниже, был напечатан на экране?
/* strtok example */
#include <stdio.h>
#include <string.h>
int main ()
{
char str[] ="- This, a sample string.";
char * pch;
printf ("Splitting string \"%s\" into tokens:\n",str);
pch = strtok (str," ,.-");
while (pch != NULL)
{
printf ("%s\n",pch);
pch = strtok (NULL, " ,.-");
}
return 0;
}
Вывод:
Разделение строки "- Это образец строки". в токены: это а образец строка
strtok()
изменяет свою строку аргумента, завершая токены NUL перед возвратом. Если вы попытаетесь исследовать весь буфер (str []), вы увидите, что он изменяется между последовательными вызовамиstrtok()
.str
, смотретьstr[0]
,str[1]
,str[2]
, ...Ответы:
strtok()
делит строку на токены. т.е. начиная с любого из разделителей до следующего будет ваш единственный токен. В вашем случае начальный токен будет с «-» и заканчиваться следующим пробелом «». Тогда следующий токен будет начинаться с "" и заканчиваться ",". Здесь в качестве вывода вы получите «Это». Точно так же остальная часть строки разделяется на токены от пробела к пробелу и, наконец, заканчивается последний токен на "."источник
функция времени выполнения strtok работает так
при первом вызове strtok вы предоставляете строку, которую хотите токенизировать
в приведенном выше строковом пространстве кажется хорошим разделителем между словами, поэтому давайте использовать это:
теперь происходит поиск 's' до тех пор, пока не будет найден символ пробела, возвращается первый токен ('this'), а p указывает на этот токен (строка)
чтобы получить следующий токен и продолжить с той же строкой, NULL передается в качестве первого аргумента, поскольку strtok поддерживает статический указатель на вашу предыдущую переданную строку:
p теперь указывает на "есть"
и так далее до тех пор, пока не перестанут быть найдены пробелы, тогда последняя строка будет возвращена как последняя «строка» токена.
более удобно вы можете написать это так, чтобы распечатать все токены:
РЕДАКТИРОВАТЬ:
Если вы хотите сохранить возвращенные значения,
strtok
вам необходимо скопировать токен в другой буфер, например,strdup(p);
поскольку исходная строка (на которую указывает статический указатель внутриstrtok
) изменяется между итерациями, чтобы вернуть токен.источник
p
указывает на этот токен» , заключается в том, чтоstrtok
необходимо изменить исходную строку, поместив нулевые символы вместо разделителя (иначе другие строковые функции не будут знать, где токен заканчивается). И он также отслеживает состояние с помощью статической переменной.strtok
поддерживает статическую внутреннюю ссылку, указывающую на следующий доступный токен в строке; если вы передадите ему указатель NULL, он будет работать с этой внутренней ссылкой.Это причина того, что
strtok
он не возвращается; как только вы передаете ему новый указатель, эта старая внутренняя ссылка стирается.источник
strtok
сам параметр не меняет (str
). Он сохраняет этот указатель (в локальной статической переменной). Затем он может изменить то, на что указывает этот параметр в последующих вызовах, не передавая параметр обратно. (И он может продвигать этот указатель, но он должен выполнять свои операции.)Со
strtok
страницы POSIX :Существует поточно-ориентированный вариант (
strtok_r
), который не делает этого типа магии.источник
ctime
возврат статической строки - практично (никому не нужно задаваться вопросом, кто должен ее освободить), но не повторным входом и сбивает вас с толку, если вы этого не очень понимаете.strtok
сам параметр не меняет (str
)».puts(str);
печатает "- Это", так какstrtok
измененоstr
.При первом вызове вы предоставляете строку для токенизации
strtok
. А затем, чтобы получить следующие токены, вы просто передаетеNULL
этой функции, если она не возвращаетNULL
указатель.strtok
Функция записывает строку , которую вы указали при первом вызове его. (Что действительно опасно для многопоточных приложений)источник
strtok токенизирует строку, то есть преобразует ее в серию подстрок.
Это делается путем поиска разделителей, разделяющих эти токены (или подстроки). И вы указываете разделители. В вашем случае вы хотите "или", "или". или "-" в качестве разделителя.
Модель программирования для извлечения этих токенов заключается в том, что вы передаете strtok своей основной строке и набору разделителей. Затем вы вызываете его несколько раз, и каждый раз strtok будет возвращать следующий найденный токен. Пока он не достигнет конца основной строки, когда он не вернет нуль. Другое правило заключается в том, что вы передаете строку только в первый раз и NULL в последующие разы. Это способ сообщить strtok, если вы начинаете новый сеанс токенизации с новой строкой или получаете токены из предыдущего сеанса токенизации. Обратите внимание, что strtok запоминает свое состояние для сеанса токенизации. И по этой причине он не является реентерабельным или потокобезопасным (вместо этого вы должны использовать strtok_r). Еще нужно знать, что он фактически изменяет исходную строку. Он пишет '\ 0' для найденных разделителей.
Один из способов кратко вызвать strtok заключается в следующем:
Результат:
источник
strtok изменяет свою входную строку. Он помещает в него нулевые символы ('\ 0'), чтобы он возвращал биты исходной строки как токены. Фактически strtok не выделяет память. Вы можете лучше понять это, если нарисуете строку как последовательность прямоугольников.
источник
Чтобы понять, как
strtok()
работает, сначала нужно знать, что такое статическая переменная . Эта ссылка хорошо это объясняет ....Ключом к работе
strtok()
является сохранение положения последнего разделителя между секцессивными вызовами (поэтомуstrtok()
продолжает анализировать исходную строку, которая передается ему, когда он вызывается с помощьюnull pointer
в последовательных вызовах).Взгляните на мою собственную
strtok()
реализацию, называемуюzStrtok()
, которая имеет несколько другие функции, чем та, что предоставляетсяstrtok()
А вот пример использования
Код взят из библиотеки обработки строк, которую я поддерживаю на Github , и называется zString. Взгляните на код или даже внесите свой вклад :) https://github.com/fnoyanisi/zString
источник
Вот как я реализовал strtok, не так уж и здорово, но после 2 часов работы над ним, наконец, он сработал. Он поддерживает несколько разделителей.
источник
strtok заменяет символы во втором аргументе на NULL, а символ NULL также является концом строки.
http://www.cplusplus.com/reference/clibrary/cstring/strtok/
источник
Вот моя реализация, в которой для разделителя используется хэш-таблица, что означает O (n) вместо O (n ^ 2) (вот ссылка на код) :
источник
strtok () сохраняет указатель в статической переменной, где вы в последний раз остановились, поэтому при втором вызове, когда мы передаем значение null, strtok () получает указатель из статической переменной.
Если указать такое же имя строки, она снова начинается с начала.
Кроме того, strtok () является деструктивным, т. Е. Вносит изменения в исходную строку. поэтому убедитесь, что у вас всегда есть копия оригинального.
Еще одна проблема использования strtok () заключается в том, что, поскольку он сохраняет адрес в статических переменных, в многопоточном программировании вызов strtok () более одного раза вызовет ошибку. Для этого используйте strtok_r ().
источник
Для тех, кому все еще трудно понять эту
strtok()
функцию, взгляните на этот пример pythontutor , это отличный инструмент для визуализации вашего кода C (или C ++, Python ...).Если ссылка не работает, вставьте:
Кредиты принадлежат Андерсу К.
источник
вы можете сканировать массив символов в поисках токена, если вы его нашли, просто напечатайте новую строку, иначе распечатайте символ.
источник
Итак, это фрагмент кода, который поможет лучше понять эту тему.
Печать токенов
Задача: для данного предложения, s, вывести каждое слово предложения с новой строки.
Входные данные:
How is that
Результат:
Объяснение: Итак, здесь используется функция strtok (), и она повторяется с использованием цикла for для печати токенов в отдельных строках.
Функция примет параметры как «строка» и «точка останова» и разорвет строку в этих точках останова и сформирует токены. Теперь эти токены хранятся в 'p' и используются в дальнейшем для печати.
источник