C-определение используемого разделителя-strtok()

допустим, я использую strtok() такой..

char *token = strtok(input, ";-/");

есть ли способ выяснить, какой токен фактически используется? Например, если входные данные были чем-то вроде:

Hello there; How are you? / I'm good - End

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

3 ответов


важно: strtok не является повторным участником, вы должны использовать strtok_r вместо него.

вы можете сделать это, сохранив копию исходной строки и посмотрев смещения текущего токена в эту копию:

char str[] = "Hello there; How are you? / I'm good - End";
char *copy = strdup(str);
char *delim = ";-/";
char *res = strtok( str, delim );
while (res) {
    printf("%c\n", copy[res-str+strlen(res)]);
    res = strtok( NULL, delim );
}
free(copy);

это выводит

;
/
-

демо #1

EDIT: обработка нескольких разделители

Если вам нужно обрабатывать несколько разделителей, определяющих длина текущей последовательности разделителей становится немного сложнее: теперь вам нужно найти следующий токен, прежде чем решать, как долго будет последовательность разделителей. Математика не сложна, пока вы помните, что NULL требует специального лечения:

char str[] = "(20*(5+(7*2)))+((2+8)*(3+6*9))";
char *copy = strdup(str);
char *delim = "*+()";
char *res = strtok( str, delim );
while (res) {
    int from = res-str+strlen(res);
    res = strtok( NULL, delim );
    int to = res != NULL ? res-str : strlen(copy);
    printf("%.*s\n", to-from, copy+from);
}
free(copy);

демо #2


ты не можешь. strtok перезаписывает следующий символ разделителя символом nul (чтобы завершить токен, который он возвращает на этот раз), и он не сохраняет Предыдущее значение, которое он перезаписывает. Первый раз, когда вы звоните strtok в вашей строке примера,; ушел навсегда.

вы можете что-то сделать, если вы держите немодифицированную копию строки, которую вы изменяете с помощью strtok - учитывая индекс Терминатора nul для вашего текущего токена (относительно начало строки), вы можете посмотреть на тот же индекс в копии и посмотреть, что там было.

что может быть хуже, чем просто писать свой собственный код в отдельной строке, конечно. Вы можете использовать strpbrk или strcspn, если вы можете жить с результирующим токеном, не являющимся нулевым для вас.


человек 3 strtok

функции strtok() и strtok_r() возвращают указатель на начало каждого последующего токена в строке после замены сам токен с символом NUL. Когда нет остается больше токенов, возвращается нулевой указатель.

но с небольшой арифметикой указателей вы можете сделать что-то вроде:

char* string = "Hello,World!";
char* dup = strdup(string);

char* world = strtok(string, ",");
char delim_used = dup[world - string];

free(dup);