Хотя Стефан предоставил вам хороший ответ на проблемы, с которыми вы столкнулись при реализации функции LongestWord
, вы, возможно, слишком усложняете то, что делаете, чтобы найти самое длинное слово.
Чтобы быть полезным, подумайте о том, что вам нужно знать, получая самое длинное слово из предложения. Вы хотите знать (1) какое слово самое длинное; и (2) сколько символов оно содержит? Вы всегда можете вызвать strlen
снова, когда функция вернется, но почему? Вы уже обработали эту информацию в функции, так что вы могли бы также сделать эту информацию доступной обратно в вызывающей стороне.
Вы можете написать свою функцию несколькими способами, чтобы либо вернуть длину самого длинного слова, либо указатель на самое длинное слово, и т. Д. Если вы хотите вернуть указатель на самое длинное слово, вы можете либо передать массив достаточного размера в качестве параметра функции для заполнения внутри функции, или вы можете динамически распределять хранилище внутри функции так, чтобы хранилище сохранилось после возврата функции ( выделено длительности хранения стихи автоматическое срок хранения). Вы также можете объявить массив static
и таким образом сохранить хранилище, но это ограничит вас одним использованием функции в любом одном выражении. Если вы возвращаете указатель на самое длинное слово, чтобы также сделать длину доступной обратно в вызывающей стороне, вы можете передать указатель в качестве параметра и обновить значение по этому адресу в вашей функции, сделав длину доступной обратно в вызывающей функции.
До тех пор, пока вы просто ищете самое длинное слово, самое длинное слово в словаре без ограничений (немедицинское) составляет 29 символов (с общим объемом хранения 30 символов), или для медицинских терминов самое длинное слово - 45- персонаж (всего 46 символов) Поэтому может иметь смысл просто передать массив для заполнения самым длинным словом в качестве параметра, поскольку вы уже знаете, какой будет максимальная длина (достаточно массива из 64 символов - или вдвое больше, чтобы не экономить на размер буфера, ваш звонок).
Вместо того, чтобы использовать несколько массивов, простой цикл и пара указателей - все, что вам нужно, чтобы пройтись по буферу предложений, заключив в скобки начало и конец каждого слова, чтобы выбрать самое длинное. (и преимущество, в отличие от использования strtok
и т. д., заключается в том, что исходное предложение остается неизменным, что позволяет ему быть переданным как const char *
, позволяя компилятору дополнительно оптимизировать код)
Функция longest_word
, которая передает предложение и слово для заполнения в качестве параметров, возвращающих длину самой длинной строки, довольно просто сделать в одном цикле. Слабое название State Loop , где вы используете простой флаг для отслеживания вашего состояния чтения, т. Е. Являетесь ли вы in
словом в предложении или находитесь ли вы в пробеле до, между или после слов в предложении. Простой государственный флаг In / Out.
Затем вы просто используете указатель p
, чтобы найти начало каждого слова, и указатель конца ep
, чтобы продвинуться вниз по предложению, чтобы найти конец каждого слова, проверяя слово с максимальной длиной как вы идете. Вы можете использовать макрос isspace()
, предоставленный в ctype.h
, чтобы найти пробелы между каждым словом.
Сам цикл постоянно выполняет только цикл, пока вы отслеживаете каждый указатель, а затем проверяете, какое слово самое длинное, с помощью простой разницы указателей ep - p
, когда найден конец каждого слова. Если слово длиннее предыдущего max
, скопируйте его в самый длинный массив слов и обновите max
новой максимальной длиной.
Короткая реализация может быть похожа на:
size_t longest_word (const char *sentence, char *word)
{
const char *p = sentence, *ep = p; /* pointer & end-pointer */
size_t in = 0, max = 0; /* in-word flag & max len */
if (!sentence || !*sentence) /* if NULL or empty, set word empty */
return (*word = 0);
for (;;) { /* loop continually */
if (isspace (*ep) || !*ep) { /* check whitespace & end of string */
if (in) { /* if in-word */
size_t len = ep - p; /* get length */
if (len > max) { /* if greater than max */
memcpy (word, p, len); /* copy to word */
word[len] = 0; /* nul-terminate word */
max = len; /* update max */
}
p = ep; /* update pointer to end-pointer */
in = 0; /* zero in-word flag */
}
if (!*ep) /* if end of word, bail */
break;
}
else { /* non-space character */
if (!in) { /* if not in-word */
p = ep; /* update pointer to end-pointer */
in = 1; /* set in-word flag */
}
}
ep++; /* advance end-pointer */
}
return max; /* return max length */
}
Полный пример, в котором предложение читается как ввод пользователя, может быть похож на:
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#define MAXWRD 64 /* longest word size */
#define MAXC 2048 /* max characters in sentence */
size_t longest_word (const char *sentence, char *word)
{
const char *p = sentence, *ep = p; /* pointer & end-pointer */
size_t in = 0, max = 0; /* in-word flag & max len */
if (!sentence || !*sentence) /* if NULL or empty, set word empty */
return (*word = 0);
for (;;) { /* loop continually */
if (isspace (*ep) || !*ep) { /* check whitespace & end of string */
if (in) { /* if in-word */
size_t len = ep - p; /* get length */
if (len > max) { /* if greater than max */
memcpy (word, p, len); /* copy to word */
word[len] = 0; /* nul-terminate word */
max = len; /* update max */
}
p = ep; /* update pointer to end-pointer */
in = 0; /* zero in-word flag */
}
if (!*ep) /* if end of word, bail */
break;
}
else { /* non-space character */
if (!in) { /* if not in-word */
p = ep; /* update pointer to end-pointer */
in = 1; /* set in-word flag */
}
}
ep++; /* advance end-pointer */
}
return max; /* return max length */
}
int main (void) {
char buf[MAXC], word[MAXWRD];
size_t len;
if (!fgets (buf, MAXC, stdin)) {
fputs ("error: user canceled input.\n", stderr);
return 1;
}
len = longest_word (buf, word);
printf ("longest: %s (%zu-chars)\n", word, len);
return 0;
}
Пример использования / Вывод
Введенная строка имеет 2-символьные пробелы в начале, а также 2-символьные пробелы:
$ ./bin/longest_word
1234 123 12 123456 1234 123456789 12345678 1 1234
longest: 123456789 (9-chars)
Это не является заменой ответа Стефана, помогающего решить насущные проблемы в вашей реализации, скорее, это пример, предоставляющий вам альтернативный способ решения проблемы.Как правило, чем проще вы можете выполнить любую задачу по кодированию, тем меньше будет ошибок.Посмотрите его и дайте мне знать, если у вас есть дополнительные вопросы о подходе.