Как разбить строку на токены в C?
Как разбить строку на токены '&'
в С?
5 ответов
char *token;
char *state;
for (token = strtok_r(input, "&", &state);
token != NULL;
token = strtok_r(NULL, "&", &state))
{
...
}
Я бы сделал это примерно так (используя strchr()
):
#include <string.h>
char *data = "this&&that&other";
char *next;
char *curr = data;
while ((next = strchr(curr, '&')) != NULL) {
/* process curr to next-1 */
curr = next + 1;
}
/* process the remaining string (the last token) */
strchr(const char *s, int c)
возвращает указатель на следующее местоположение c
в s
, или же NULL
если c
не найден в s
,
Вы могли бы использовать strtok()
Однако мне не нравится strtok()
, так как:
- он изменяет токенизируемую строку, поэтому он не работает для литеральных строк или не очень полезен, если вы хотите сохранить строку для других целей. В этом случае вы должны сначала скопировать строку во временную.
- он объединяет соседние разделители, поэтому, если ваша строка была
"a&&b&c"
возвращенные токены"a"
,"b"
, а также"c"
, Обратите внимание, что нет пустого токена после"a"
, - это не потокобезопасно.
Вы можете использовать функцию strok(), как показано в примере ниже.
/// Function to parse a string in separate tokens
int parse_string(char pInputString[MAX_STRING_LENGTH],char *Delimiter,
char *pToken[MAX_TOKENS])
{
int i;
i = 0;
pToken[i] = strtok(pInputString, Delimiter);
i++;
while ((pToken[i] = strtok(NULL, Delimiter)) != NULL){
i++;
}
return i;
}
/// The array pTokens[] now contains the pointers to the start of each token in the (unchanged) original string.
sprintf(String,"Token1&Token2");
NrOfParameters = parse_string(String,"&",pTokens);
sprintf("%s, %s",pToken[0],pToken[1]);
Для меня, используя
strtok()
функция не интуитивно понятна и слишком сложна, поэтому мне удалось создать свою. В качестве аргументов он принимает строку для разделения, символ, определяющий пробелы между токенами, и указатель, представляющий количество найденных токенов (полезно при печати этих токенов в цикле). Недостатком этой функции является фиксированная максимальная длина каждого токена.
#include <stdlib.h>
#include <string.h>
#define MAX_WORD_LEN 32
char **txtspt(const char *text, char split_char, int *w_count)
{
if(strlen(text) <= 1)
return NULL;
char **cpy0 = NULL;
int i, j = 0, k = 0, words = 1;
//Words counting
for(i = 0; i < strlen(text); ++i)
{
if(text[i] == split_char && text[i + 1] != '\0')
{
++words;
}
}
//Memory reservation
cpy0 = (char **) malloc(strlen(text) * words);
for(i = 0; i < words; ++i)
{
cpy0[i] = (char *) malloc(MAX_WORD_LEN);
}
//Splitting
for(i = 0; i < strlen(text) + 1; ++i)
{
if(text[i] == split_char)
{
cpy0[k++][j] = '\0';
j = 0;
}
else
{
if(text[i] != '\n') //Helpful, when using fgets()
cpy0[k][j++] = text[i]; //function
}
}
*w_count = words;
return cpy0;
}
Это довольно просто:
char str[] = "&a&&b&c"; // a mutable string
for (char *cp = str; (cp = strtok(cp, "&")) != NULL; cp = NULL) {
/* do something with the token */
}
Имеется один вызов , один экземпляр строки-разделителя и область действияcp
содержится внутри этого цикла.
Предложение использоватьstrchr()
не учитывает несколько символов-разделителей. Возможно, было бы лучше, если бы это предложилиstrcspn()
. Обратите внимание, что последний токен должен быть обработан ПОСЛЕ завершения цикла. Не очень удачный дизайн...
Преимуществоstrtok()
заключается в том, что токены были изолированы в своем текущем местоположении. Если их адреса сохраняются в массиве указателей, их можно использовать повторно, не изолируя их снова и снова.