Ваш код работает более или менее разумно для меня, если я не наберу ни единого слова ввода, за которым не будет пробела (пробел, табуляция, новая строка), прежде чем указать EOF ( Control-D на моем компьютере); если вы используете Control-Z , это предполагает, что вы работаете в Windows). Если вы указываете EOF без последнего пробела, последнее слово не добавляется к гистограмме. Вы, конечно, должны также убедиться, что длина слова не слишком велика, чтобы не индексировать вне массива wordlength
(if (nc > MAXSIZE) nc = MAXSIZE;
для подсчета всех очень длинных слов одинакового размера).
После основного цикла обработки вы должны проверить, является ли nc > 0
, и если да, увеличить соответствующую запись в wordlength
.
Рассмотрите возможность использования isspace()
из <ctype.h>
.
Я использую enum
вместо #define
, когда это возможно, чтобы символы были доступны в отладчике. Вы тщательно избежали одной распространенной ошибки; вы превратили переменную c
в int
, а не char
.
#include <stdio.h>
enum { IN = 1, OUT = 0 }; /* inside, outside a word */
enum { MAXLEN = 50 };
/* count lines, words, and characters in input */
int main(void)
{
int c, i, j, nc, state;
int wordlength[MAXLEN];
state = OUT;
nc = 0;
for (i = 0; i < MAXLEN; i++)
wordlength[i] = 0;
while ((c = getchar()) != EOF)
{
if (c == ' ' || c == '\n' || c == '\t')
{
if (state == IN)
{
if (nc > MAXLEN)
nc = MAXLEN; /* All long words grouped together */
wordlength[nc-1]++;
}
state = OUT;
}
else if (state == OUT)
{
state = IN;
nc = 0;
}
if (state == IN)
++nc;
}
if (nc > 0)
{
if (nc > MAXLEN)
nc = MAXLEN; /* All long words grouped together */
wordlength[nc-1]++;
}
for (j = 0; j < MAXLEN; j++)
printf("\n%d - %d", j, wordlength[j]);
for (i = 10; i >= 0; i--)
{
for (j = 0; j < MAXLEN; j++)
putchar( (wordlength[j] > i) ? '|' : ' ');
printf("\n");
}
return 0;
}
Вы сказали, что у вас проблемы с вашей машиной. Я бы очень осторожно относился к утверждению, что нашел ошибку в системе, особенно при таком очевидном вызове, как getchar()
. Я не могу исключить такую возможность, но это будет последнее, о чем я буду думать. Я бы потратил много времени на то, чтобы понять, что я сделал неправильно, чтобы сломать вещи, прежде чем подумать, что в getchar()
.
В комментариях вас просят сообщить, почему ваша программа не работает в вашей среде. Поскольку вы (пока) формально не определили платформу / среду, в которой вы запускаете свою программу, это невозможно.
Тем не менее, я продемонстрировал, что ваша оригинальная программа «как опубликовано» работает достаточно разумно в Unix-подобной среде (я тестирую на MacOS X 10.7.2, но она будет работать так же для любой другой подобной Unix-подобной системы). ). Пересмотренная версия работает немного лучше; он будет считать последнее введенное слово, даже если за ним не следует пробел или перевод строки.
Если, как следует из вышесказанного, вы работаете в Windows, то модель терминала ввода-вывода может отличаться. В частности, стандарт C требует, чтобы текстовые файлы (возможно, включая ввод с терминала) заканчивались символом новой строки перед EOF; любые символы после последней новой строки могут быть отброшены, но это зависит от платформы. Поведение для двоичных файлов отличается. Если данные после последней новой строки, это будет соответствовать поведению, о котором вы сообщаете. Это вполне может быть ожидаемое поведение - если вы посмотрите документацию для вашей неопознанной системы. Это одна из областей различий между реализациями, указанными П. Дж. Плаугером в его превосходной (но несколько устаревшей) «Стандартной библиотеке С».
Однако, если мои предположения верны, я все же хочу прояснить, что ваш код верен (достаточно); проблема в том, что ваши ожидания не соответствуют задокументированному поведению вашей системы. Обратите внимание, что отчетность о платформе, на которой вы работаете, иногда очень важна Это имеет тенденцию быть более важным, поскольку вы покушаетесь на крайние случаи. И все же крайне маловероятно, что вы обнаружили ошибку в getchar()
.
Между прочим, когда я тестировал, мне нужно было дважды набрать Control-D (и это именно то, что я ожидал сделать). В первый раз символы, которые я ввел в строку (abc
), были сброшены в программу в виде 3-байтового чтения; вторая также сбрасывала введенные мной символы (все их ноль) в программу в виде 0-байтового чтения, которое затем интерпретировалось как EOF как getchar()
. Я также проверил с abc
(пробел в конце), а затем EOF. Ваш код не засчитал abc
без пробела; он действительно считал abc
, когда за ним следовал пробел.