#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
руководства — возвращаемое значение fromstrtok
равно «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 Я немного расширил ответ; теперь понятно?