Как сравнить строку токена с строкой "exit"? - PullRequest
2 голосов
/ 11 апреля 2019

Я не знаю, как сравнить строку со словом «выход», чтобы при выходе из клавиатуры программа выходила. #define MAX_LINE 4096 #define MAX_WORDS MAX_LINE / 2

int main()
{
        char line[MAX_LINE], *words[MAX_WORDS], message[MAX_LINE];
        int stop=0,nwords=0;

        while(1)
        {
                printf("OSP CLI $ ");
        fgets(line,MAX_LINE,stdin);

        if(strcmp(line,"exit")==0)
        {
            exit(0);
        }   
void tokenize(char *line, char **words, int *nwords)
{
    *nwords=1;
    for(words[0]=strtok(line," \t\n");
       (*nwords<MAX_WORDS)&&(words[*nwords]=strtok(NULL, " \t\n"));
        *nwords=*nwords+1
    ); /* empty body */
    return;
}

Код правильный, но я не знаю, что он делает. Таким образом, for (words [0] = strtok (line, "\ t \ n"); читает первое слово в строке. "Line" - это ввод с клавиатуры, который пользователь вводит во время выполнения и представляет собой просто строку типа: hello world blah dee doo. Но после этого следующая строка с nwords <..... ничего не понимает после строки с for. </p>

Ответы [ 2 ]

3 голосов
/ 11 апреля 2019
for (a; b; c) d;

Можно перевести на:

a;
while (b) {
   d;
   c;
}

Итак:

void tokenize(char *line, char **words, int *nwords)
{
    *nwords=1;
    for(words[0]=strtok(line," \t\n");
       (*nwords<MAX_WORDS)&&(words[*nwords]=strtok(NULL, " \t\n"));
        *nwords=*nwords+1
    ); /* empty body */
    return;
}

можно перевести на (с некоторыми другими улучшениями, например, int *a; if (a) совпадает с int *a; if (a != NULL)):

void tokenize(char *line, char **words, int *nwords)
{
    *nwords = 1;
    words[0] = strtok(line, " \t\n");
    while ( 
             *nwords < MAX_WORDS && 
             (words[*nwords] = strtok(NULL, " \t\n")) != NULL
    ) {
        /* empty body */
        *nwords = *nwords + 1;
    }
}

давайте подробнее расскажем:

void tokenize(char *line, char **words, int *nwords)
{
    *nwords = 1;
    words[0] = strtok(line, " \t\n");
    while (*nwords < MAX_WORDS) {
        words[*nwords] = strtok(NULL, " \t\n");
        if (words[*nwords] == NULL) {
            break;
        }
        /* empty body */
        *nwords = *nwords + 1;
    }
}

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

words - это указатель, это массив char* указателей. Длина указателя words кажется, по крайней мере, MAX_WORDS в длину. nwords - указатель на возвращенную длину указателя words. Вызывающая сторона ожидает, что эта функция заполнит words память и nwords память токенами из строки. Предполагается, что все указатели не являются NULL и действительны, MAX_WORDS > 0 и strlen(line) != 0 или что строка line состоит не только из используемых " \t\n" разделителей, так что всегда есть первый токен.

  • Сначала nwords инициализируется 1, а первый токен извлекается words[0] = strtok(line, " \t\n");.
  • Затем, пока количество токенов не станет меньше, чем MAX_WORDS, следующий токен будет извлечен words[*nwords] = strtok(NULL, " \t\n")
  • Из strtok manual - возвращаемое значение из strtok равно «NULL, если токенов больше нет». Если strtok возвращает NULL, значит, мы закончили эту строку - поэтому мы возвращаемся из функции.
  • Если, однако, количество токенов меньше, чем MAX_WORDS, и мы извлекли следующий действительный токен, мы увеличиваем количество *nwords = *nwords + 1;
  • Вызывающий абонент остается с words, инициализированным указателями внутри строки line, память за nwords инициализируется с количеством токенов, а массив line изменяется так, чтобы иметь завершающие нули '\0' на месте разделителей токенов.
2 голосов
/ 11 апреля 2019

Давайте перепишем код, чтобы он был менее лаконичным и более читабельным:

void tokenize(char *line, char **words, int *nwords)
{
  *nwords=1;
  words[0]=strtok(line," \t\n");
  while (*nwords < MAX_WORDS) {
    words[*nwords] = strtok(NULL, " \t\n");
    if (!words[*nwords])
      break;
    *nwords = *nwords + 1;
  }
}

Одна вещь, которая также усложняет понимание этого кода, это тот факт, что он всегда обращается к числу слов косвенночерез указатель nwords.Вот еще одно переписывание без этого сокращения:

void tokenize(char *line, char **words, int *nwords)
{
  int wordCount = 1;
  words[0]=strtok(line," \t\n");
  while (wordCount < MAX_WORDS) {
    words[wordCount] = strtok(NULL, " \t\n");
    if (!words[wordCount])
      break;
    wordCount = wordCount + 1;
  }
  *nwords = wordCount;
}

Наконец, для указателя p тестирование !p аналогично тестированию p == NULL.Таким образом, проверка if (!words[wordCount]) означает «если последний текущий элемент в words является нулевым указателем».Это может произойти, когда strtok возвращает нулевой указатель, указывающий, что он завершил синтаксический анализ.

Надеюсь, теперь это немного яснее.

В общем, функция использует strtok для извлечения словиз line и сохраните их в последовательных элементах массива words, с количеством сохраненных слов, возвращаемых в nwords.

. Он будет многократно извлекать одно слово, сохранять его и увеличивать количество слов.,Это продолжается до тех пор, пока либо:

  • MAX_WORDS не будет извлечено, либо
  • strtok вернет нулевой указатель, означая, что в line.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...