Когда этот фрагмент кода встречается с пробелом, он съедает все последующие пробелы и печатает только один пробел.
while((c=getchar()) != EOF) { // As long as we don't reach EOF, get next character
if(c==' ') { // If character is a space,
// then, keep getting characters, as long as they are spaces
while((c=getchar()) == ' '); // This empty-bodied loop will stop when current character is not a space
putchar(' '); // Output a space character
}
}
Итак, если вход содержит десять (например) последовательных ( пробелы, расположенные рядом друг с другом, будет напечатан только один пробел.
Подробнее в K & R Упражнение 1-9 (C) .
нужно объяснение состояния в еде l oop. первый l oop позволяет мне сделать запись, так почему второй просто читает c дальше, а не запрашивает новую запись?
Внешний l oop будет читать символ и ради этого примера, давайте предположим, что это пробел. Он войдет в свое тело и также введет тело оператора if.
Теперь он будет читать следующий символ (во внутреннем l oop), и если это пробел, код в основном будет ничего не делать с этим пробелом, так как тело внутреннего l oop пусто. Он будет go включен, запрашивая следующий символ .. Он будет делать то же самое снова и снова, пока следующий последовательный символ является пробелом.
Когда следующий символ не является пробелом, код выведет пробел (представляющий все недавно обнаруженные пробелы).
Например, предположим, что пользователь вводит три пробела, которые под капотом хранятся в стандартном вводе (STDIN). ) буфер:
----------
|''|''|''|
----------
Первое выполнение внешнего l oop: получает первый символ и сохраняет его в c
, убедившись, что это не EOF. Поток управления нашего кода поступает во внешнее тело l oop. Оператор if подтверждает, что c
является пробелом и входит в его тело. На этом этапе буфер STDIN выглядит следующим образом:
----------
|''|''| |
----------
Теперь мы достигли внутреннего l oop while((c=getchar()) == ' ');
, в котором пустое тело .
getchar()
метод получит следующий символ и сохранит его в c
. Затем он проверит, если это пробел, что верно в нашем случае. Теперь мы входим в пустое тело внутреннего l oop и выходим из него сразу же, поскольку здесь нечего делать.
На этом этапе буфер STDIN выглядит так:
----------
|''| | |
----------
Снова выполняется внутренний l oop, метод получает следующий ожидающий символ в буфере и сохраняет его в c
. Затем он проверит, является ли c
пробелом, и так как это верно и в этом случае, и мы снова введем пустое l oop, ничего не делаем и выйдем из него.
На этом этапе буфер STDIN таков:
----------
| | | |
----------
, который пуст.
Еще раз, внутренний l oop выполняется, метод запрашивает следующий символ, ожидающий в буфере, и сохраняет его в c
. Однако, поскольку больше нет символов для чтения, метод getchar()
возвращает EOF
, поэтому проверка внутри условия l oop внутреннего символа для пробела завершается неудачей, и поток управления нашего кода переходит на следующую строку нашего кода, так как условие внутреннего l oop теперь ложно.
Следующая строка - putchar(' ');
, которая выводит один пробел, не заботясь о количестве пробелов, которые мы читали ранее, что в в этом случае было три.
Наконец, внешний l oop выполняется снова, во второй раз, и getchar()
снова запрашивает следующий символ для чтения, и мы сохраняем его возвращаемое значение в c
. c
равно EOF, что приводит к ложному условию внешнего l oop, что означает, что теперь мы также выходим из внешнего l oop.