Как мне сравнить маркированную строку с str «exit»?

#c

#c

Вопрос:

Я не знаю, как сравнить строку со словом «exit», чтобы при вводе с клавиатуры выход из программы завершался. #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," tn");
       (*nwords<MAX_WORDS)amp;amp;(words[*nwords]=strtok(NULL, " tn"));
        *nwords=*nwords 1
    ); /* empty body */
    return;
}
  

Код правильный, но я не знаю, что он делает. Итак, for(words[0]=strtok(line,» t n»); считывает первое слово в строке. «строка» — это ввод с клавиатуры, который пользователь вводит во время выполнения, который представляет собой просто строку типа: hello world blah dee doo. Но после этого следующая строка с nwords<….. ничего не понимаю после строки с for .

Комментарии:

1. Он разбивается line на токены и помещает их в words

2. Возьмите отладчик и выполните его. Это покажет вам, что происходит.

3. Например, допустим, если строка

4. Где мне найти отладчик?

5. Похоже, вам нужно изучить две вещи: что strtok делает и что for делает цикл. Также обратите внимание, что оператор присваивания = возвращает значение левого операнда после выполнения присваивания. Этот способ operator= можно использовать внутри условия.

Ответ №1:

 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," tn");
       (*nwords<MAX_WORDS)amp;amp;(words[*nwords]=strtok(NULL, " tn"));
        *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, " tn");
    while ( 
             *nwords < MAX_WORDS amp;amp; 
             (words[*nwords] = strtok(NULL, " tn")) != NULL
    ) {
        /* empty body */
        *nwords = *nwords   1;
    }
}
  

давайте подробнее рассмотрим это:

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

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

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

  • Сначала nwords инициализируется 1 , и извлекается первый токен words[0] = strtok(line, " tn"); .
  • Затем, пока количество токенов не станет меньше MAX_WORDS , извлекается следующий токен words[*nwords] = strtok(NULL, " tn")
  • Из strtok руководства — возвращаемое значение from strtok равно «NULL, если токенов больше нет». Если strtok возвращает NULL, значит, мы закончили строку — значит, мы возвращаемся из функции.
  • Однако, если количество токенов меньше, MAX_WORDS и мы извлекли следующий допустимый токен, мы увеличиваем количество *nwords = *nwords 1;
  • Вызывающий объект остается words инициализированным указателями внутри line строки, память nwords инициализируется количеством токенов, а line массив модифицируется, чтобы иметь завершающие нули '' вместо разделителей токенов.

Комментарии:

1. Спасибо за помощь, вы сделали это намного проще, я не понял, что для цикла, потому что это только мой второй семестр в программировании, я перешел с java на программирование операционных систем с помощью c.

2. фух, большая головная боль.

Ответ №2:

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

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

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

 void tokenize(char *line, char **words, int *nwords)
{
  int wordCount = 1;
  words[0]=strtok(line," tn");
  while (wordCount < MAX_WORDS) {
    words[wordCount] = strtok(NULL, " tn");
    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 .

Комментарии:

1. если (!words[*nwords]) прерывается; Я не знаю, что это значит?

2. Хорошо! слова [* nwords]) Я в замешательстве по этому поводу.

3. @JustinZhao Я немного расширил ответ; теперь понятно?