strtok возвращает только один токен - PullRequest
1 голос
/ 09 декабря 2011

Я пишу простую оболочку, которая принимает некоторые стандартные команды, такие как cd и ls в C. Я пытаюсь реализовать функцию, в которой пользователь может ввести «;» между командами, так что куча команд может быть записана в одной строке и выполняться отдельно. Поэтому, если я введу «cd Desktop; ls», оболочка должна перейти к рабочему столу и распечатать содержимое каталога. Проблема в том, что он выполняет только первую команду. Вот мой основной метод:

char input[1024];

while(1)
{
    printf("%s ", prompt);
    fgets(input, 1024, stdin);

    char delims[] = ";";
    char *result = NULL;
    result = strtok( input, delims );

    while( result != NULL )
    {
        printf("%s\n", result);

        char * copy = malloc(strlen(result) + 1); //Create a copy of the input token
        strcpy(copy, result);

        format(copy);

        if(programs)
        {
            handle();
            cleanup(programs);
            programs = NULL;
        }
        free(copy);
        result = strtok( NULL, delims );
        cmdno++;
    }
}

Сначала я пытаюсь разбить входные данные на токены, основываясь на ";" а затем передайте токен методу format (), который выглядит следующим образом:

int format(char input[])
{
    input = strtok(input, "\n");
    ...
}

Я знаю, что strtok вносит изменения в исходную строку, поэтому я сначала создаю копию токена, прежде чем передать его в формат. Что я делаю правильно?

Ответы [ 2 ]

5 голосов
/ 09 декабря 2011

Вы не можете смешивать несколько strtok вызовов. Вот что происходит:

  • Вы начинаете разделять input, поэтому strtok принимает к сведению и хранит содержимое внутри
  • Вы отдыхаете от расщепления input
    • Вы начинаете разделять copy, поэтому снова strtok принимает к сведению, уничтожая тем самым предыдущую информацию
  • На данный момент strtok знает только о бизнесе copy и ничего не знает о первоначальном input.

Основная проблема в том, что strtok не знает, что вы делаете две вещи одновременно . С его точки зрения, вы просто начали обрабатывать другую строку перед завершением первой строки.


Возможные решения:

  • Используйте strtok_r, если он у вас есть. Это не стандартный C (но это стандартный POSIX). r обозначает входящий
  • Используйте свою собственную функцию разделения (strchr / looping и т. Д.)
  • Измените логику вашей программы так, чтобы вам не нужно было разбивать copy перед тем, как заканчивать с input

Об этом последнем пункте:

  • Сохраните массив char * и заполните его strtok, не останавливаясь для разделения под токенов. Таким образом, каждый элемент должен быть отдельной командой
  • Когда вы закончите с ";" split, начните обрабатывать каждый из элементов массива
0 голосов
/ 09 декабря 2011

Что по этому поводу:

char line[1024];
char *token;
while (1) {
  printf("$ ");
  fgets(line, 1000, stdin);
  token = strtok(line, ";");
  while (token != NULL) {
    printf("%s\n", token);
    token = strtok(NULL, ";");
  }
}
...