Использование strtok на языке Си - PullRequest
1 голос
/ 26 ноября 2011

У меня проблема с использованием strtok в C. Я получаю пользовательский ввод из командной строки, используя fgets, и я хочу маркировать его с помощью pipe ("|") в качестве разделителя и поместить результат в переменную с двойным указателем. Вот мой код:

char** argv;
char *token;
token = strtok(userInput, "|");
while(token != NULL){
  *(argv++) = token;
   token = strtok(NULL, "|");
}

*argv = '\0';

Затем я использую этот код, чтобы проверить, правильно ли он маркирован

while(*argv!= NULL)
{
   if((strcmp(*argv, "|") == 0){
   count = count + 1;
   }
   argv++;
}
printf("%d pipes", count);

Но это не работает. char ** argv ничего не содержит. Выполнение кода останавливается и возвращается -1. Когда я пытаюсь напечатать argv, argv не содержит значений.

Есть идеи, пожалуйста? Благодарю.

Edit:

Что я хочу сделать, это

userInput = "abc|cde";

После использования strtok. Я хочу иметь ** argv

**argv = "abc";

Ответы [ 4 ]

2 голосов
/ 26 ноября 2011

Одна проблема в том, что вы, похоже, не инициализируете argv. Вам нужно выделить достаточно памяти для того, чтобы он вмещал столько char * с, сколько необходимо. В противном случае вы пишете в какой-то случайный блок памяти. (Это просто, что вы не показали нам соответствующий код?)

Другая проблема заключается в том, что вы на самом деле модифицируете argv, поэтому в конце этого цикла он указывает один за последним токеном (а затем вы устанавливаете *argv в NULL); но ваш проверочный код предполагает, что он указывает на первый токен, и начинает с подтверждения того, что *argv равно , а не NULL. (Это просто, что вы не показали нам какой-то соответствующий код?) Отредактировано, чтобы добавить: Я вижу из вашего комментария выше, что "argv не содержит значений". Я довольно уверен, что это является причиной.

Кстати, вы путаете '\0' (нулевой байт) с NULL (нулевой указатель). Технически это работает правильно & mdash; '\0' повышается до 0, 0 преобразуется в NULL & mdash; но я немного обеспокоен тем, что вы их путаете, поскольку концептуально они совершенно разные. Вы должны написать *argv = NULL вместо *argv = '\0', для ясности, если ничего больше.

0 голосов
/ 23 декабря 2013

проблема в том, что ваш argv не указывает на первый элемент, когда вы пытаетесь получить из него результат.

проблема возникает здесь: * (argv ++) = токен

argv (указатель на char *) увеличивается при добавлении указателя токена в массив argv (я полагаю, вы правильно его инициализировали). Поэтому, когда вы используете вторую часть кода для получения результата, argv уже указывает на последний элемент, в вашем случае '\ 0', который не будет выводить.

И вы смешиваете «\ 0» с NULL, хотя они оба грамматически правильны, но в вашем случае лучше использовать NULL, потому что это означает указатель, а «\ 0» означает нулевое завершение в C -строка

Вы можете изменить свой код на следующее:

/* Init argv array */
char** argv;
size_t argc=0;  // token count
char *token;
token = strtok(userInput, "|");
while(token != NULL){
   argv[argc++] = token;
   token = strtok(NULL, "|");
}
argv[argc] = NULL;  // the last element of argv array is a NULL pointer

/* get result from argv */

while(*argv!= NULL)
{
   if((strcmp(*argv, "|") == 0){
   count = count + 1;
   }
   argv++;
}
printf("%d pipes", count);
0 голосов
/ 23 декабря 2013

я использую этот формат для поиска 300x400. ищем «х», чтобы избавиться от х и использовать обе стороны, 300 и 400. это работает для меня.

 char *tok1, *tok2, *saveptr;

 tok1 = strtok_r(argv, "x", &saveptr);
 tok2 = strtok_r(NULL, "x", &saveptr);

 printf("this tok1 %s this is tok2 %s\n", tok1, tok2);

с использованием функции strtok_r

0 голосов
/ 26 ноября 2011

ваш токенизирующий код работает так: если

userInput = "a|b|c"

тогда

argv = { "a", "b", "c" }

Вы можете ожидать, что

argv = {"a","|","b","|","c"}

Ваш код для подсчета труб должен быть:

while(*argv != NULL)
{
   count = count + 1;
   argv++;
}
printf("%d pipes", count-1);

Я думаю, что это будет работать

...