strtok и разбор на токены
Разделяйте строки
«strtok и разбор на токены» — бесплатный урок C Academy на CoddyKit. Это урок 3 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения C Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс C Academy содержит 4 уроков всего.
Что такое токенизация
Токенизация — это разбиение строки на более мелкие части (токены), разделённые символами-разделителями.
Например, разбиение "a,b,c" по запятым даёт токены a, b и c. В C для этого предусмотрена функция strtok.
#include <stdio.h>
#include <string.h>
int main(void) {
char text[] = "a,b,c";
char *token = strtok(text, ",");
printf("First token: %s\n", token);
return 0;
}Сигнатура strtok
char *strtok(char *str, const char *delim);
При первом вызове передайте строку. При последующих вызовах передавайте NULL, чтобы продолжить с места остановки. Функция возвращает следующий токен или NULL, когда токены закончились.
#include <stdio.h>
#include <string.h>
int main(void) {
char text[] = "red green blue";
char *tok = strtok(text, " ");
while (tok != NULL) {
printf("%s\n", tok);
tok = strtok(NULL, " ");
}
return 0;
}strtok изменяет строку
Важно: strtok изменяет исходную строку. Она заменяет каждый разделитель на '\0' и возвращает указатели на тот же буфер.
Поэтому нельзя токенизировать строковый литерал вроде "a,b", доступный только для чтения.
#include <stdio.h>
#include <string.h>
int main(void) {
char data[] = "x:y:z";
strtok(data, ":");
printf("data[1] is now: %d (the null byte)\n", data[1]);
return 0;
}Создайте изменяемую копию
Поскольку strtok разрушает входные данные, сначала скопируйте строку, если исходная понадобится позже.
Используйте локальный массив char или скопируйте строку с помощью strcpy в буфер.
#include <stdio.h>
#include <string.h>
int main(void) {
const char *original = "one-two-three";
char copy[64];
strcpy(copy, original);
char *tok = strtok(copy, "-");
while (tok) {
printf("%s\n", tok);
tok = strtok(NULL, "-");
}
printf("Original intact: %s\n", original);
return 0;
}Несколько разделителей
Аргумент delim представляет собой множество символов, а не последовательность. Любой символ из этого множества выступает разделителем.
Поэтому " ,;" одновременно разделяет по пробелам, запятым и точкам с запятой.
#include <stdio.h>
#include <string.h>
int main(void) {
char text[] = "a,b;c d";
char *tok = strtok(text, ",; ");
while (tok) {
printf("[%s]\n", tok);
tok = strtok(NULL, ",; ");
}
return 0;
}Идущие подряд разделители
strtok рассматривает последовательности разделителей как один разделитель и пропускает пустые токены.
Так, "a,,b" даёт только a и b, без пустого токена между ними. Помните об этом при разборе CSV, где пустые поля имеют значение.
#include <stdio.h>
#include <string.h>
int main(void) {
char text[] = "a,,b";
char *tok = strtok(text, ",");
while (tok) {
printf("token: %s\n", tok);
tok = strtok(NULL, ",");
}
return 0;
}Подсчёт токенов
Частая задача — подсчитать количество токенов в строке. Увеличивайте счётчик внутри цикла.
#include <stdio.h>
#include <string.h>
int main(void) {
char sentence[] = "the quick brown fox";
int count = 0;
char *tok = strtok(sentence, " ");
while (tok) {
count++;
tok = strtok(NULL, " ");
}
printf("Word count: %d\n", count);
return 0;
}strtok хранит скрытое состояние
strtok хранит свою позицию в статической внутренней переменной. Поэтому передача NULL позволяет продолжить обработку предыдущей строки.
Недостаток в том, что функция не является реентерабельной и не предназначена для безопасной работы в потоках. Нельзя одновременно токенизировать две строки.
#include <stdio.h>
#include <string.h>
int main(void) {
char a[] = "1 2";
char *t = strtok(a, " ");
printf("%s\n", t);
t = strtok(NULL, " ");
printf("%s\n", t);
return 0;
}Сохранение токенов
Чтобы использовать токены после разбиения, сохраните возвращённые указатели в массиве. Они указывают на изменённый исходный буфер, который должен оставаться доступным.
#include <stdio.h>
#include <string.h>
int main(void) {
char csv[] = "name,age,city";
char *fields[10];
int n = 0;
char *tok = strtok(csv, ",");
while (tok && n < 10) {
fields[n++] = tok;
tok = strtok(NULL, ",");
}
for (int i = 0; i < n; i++)
printf("Field %d: %s\n", i, fields[i]);
return 0;
}Реентерабельная альтернатива
POSIX предоставляет strtok_r, которая принимает явный char **saveptr вместо скрытого состояния. Благодаря этому её безопасно вкладывать и использовать в разных потоках.
Для переносимого стандартного C обычная strtok подходит для разбора за один проход.
#include <stdio.h>
#include <string.h>
int main(void) {
char text[] = "p:q:r";
char *save;
char *tok = strtok_r(text, ":", &save);
while (tok) {
printf("%s\n", tok);
tok = strtok_r(NULL, ":", &save);
}
return 0;
}Практика: разбиение пути
Токенизация особенно полезна при разборе структурированного текста, например путей к файлам. Разбиение по / позволяет получить каждый компонент пути.
#include <stdio.h>
#include <string.h>
int main(void) {
char path[] = "usr/local/bin";
char *part = strtok(path, "/");
while (part) {
printf("-> %s\n", part);
part = strtok(NULL, "/");
}
return 0;
}Быстрая проверка
Проверьте, насколько хорошо Вы понимаете работу strtok.
Итоги
Вы научились разделять строки с помощью strtok:
- При первом вызове передаётся строка, при последующих — NULL.
- Функция изменяет ввод, заменяя разделители на
'\0'; сначала копируйте строки, доступные только для чтения. - Аргумент-разделитель является множеством; последовательные разделители объединяются.
- Функция использует статическое состояние и не является потокобезопасной; при необходимости используйте
strtok_r.
Часто задаваемые вопросы
Урок «strtok и разбор на токены» бесплатный?
Да — полный текст урока «strtok и разбор на токены» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс C Academy, подпишись на CoddyKit PRO. Курс C Academy содержит 4 уроков всего.
Чему я научусь в уроке «strtok и разбор на токены»?
Разделяйте строки Ты практикуешь C Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать C Academy?
Предыдущий опыт не требуется. C Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 3 из 4.
Сколько времени занимает урок «strtok и разбор на токены»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке C Academy?
Да. Каждый урок C Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- strlen, strcpy, strcat
- strcmp и сравнение
- strtok и разбор на токены
- memcpy и memset