last day (15 days later) » 

16:10
-2
Q: В цикле while не работает функция getchar()

СергейВ основном цикле while есть вложенный цикл while. При первом проходе функция getchar() работает корректно, т.е. получает символы с потока и помещает их в буфер. Но при последующих проходах основного цикла в переменной ch появляется перевод строки "\n" который я не вводил, и сgetchar() во вложенно...

Дух сообщества
Пожалуйста, исправьте вопрос, чтобы он отражал конкретную проблему с достаточным количеством деталей для возможности дать адекватный ответ.
пока добавьте обнуление ch = 0 ; i = 0 ; while ((i < 20) .. и проверьте
Возможно переполнение буфера на 1 символ. Нельзя читать char с форматом %d. Непонятно, какая логика у цикла - при каком условии он должен закончиться?
Обновил вопрос и изменил код примера пока вопрос остался
переменная int i; имеет неопределённое начальное значение. Её надо инициализировать нулём перед сравнением.
16:10
Поставил обнуление перед вложенным циклом. Не помогло.
Ввод в буфер прекрасно работает, перевод строки в буфер не попадает. Вот почему дальше scanf не работает нормально - это я уже не знаю.
ну ещё пару ошибок справьте, а дальше посмотрим : 1. переполнение буфера char buffer[21], и 2. неопределённый порядок выполнения кто первый присваивание или сравнение (ch = getchar()) != EOF && (ch != '\n')
К функции scanf вопросов нет. Пробовал вводить два символа, при этом буфер никак не переполнится, все равно в переменной появляется перевод строки. По поводу очередности условий, а какая разница если заход в цикл будет осуществлен если все условия будут выполнены. Спасибо за ответ.
1. если i=20 то цикл выйдет и buffer[i] = '\0'; приведёт к переполнению массива и неопределённому поведению. 2. если сначала будет сравнение ch != '\n' то ввёдённый ентер при последующем ch = getchar() второй раз проверять символ уже не будет и запишет его в массив.
Не пытайтесь запихнуть всю логику в одну строку, как вы делаете в гигантском while. Это не влияет на время выполнения. Разбейте его на несколько простых и понятных команд.
16:10
@AlexGlebe Обычно всё-таки во всех языках логические операторы "ленивые" и выполняются слева направо, на это много где логика завязана. Не уверен конкретно про C, но обычно порядок проверок фиксирован поэтому, иначе придётся слишком много лишних проверок придётся делать, если не полагаться на именно такой порядок. Ну или делать вложенные if-ы придётся, что выглядит не так уже компактно.
В режиме отладки проверял переполнение буфера, его нет. А вот откуда берется перевод строки '\n' в переменной ch придется выяснять на уровне ассемблера.
@CrazyElf да, && выполняется слева на право, забыл.
char ch; — неверно, надо int ch;. EOF - это именно int, а не какой-то из обычно вводимых символов...
О переводе строки. Когда завершается вложенный цикл? Когда в ch символ \n (случай i>=20 не рассматриваем). Что не так?
Все так случай (i>=20 не рассматриваем)., дело в том что при повторном использовании ch = getchar() в переменную ch сразу попадает '\n' и цикл прекращается. Вопрос откуда берется перевод строки если я ничего еще не вводил.
Можно точный пример ввода? Чтоб повторить?
16:10
Точный ввод: ввожу пять символов чтобы не переполнить буфер. При первом проходе основного цикла вложенный работает как надо, при последующих в переменную ch сразу попадает '\n' и цикл прекращается. При этом я ничего не вводил.
Дополнение к основному вопросу.. Если из основного цикла убрать scanf("%d", &check), вложенный цикл работает как надо. Вероятно функции getchar() и scanf() используют общий буфер, пока непонятною. Правильность работы основного цикла значения не имеет так как без scanf() он зациклен.
А вы эту программу как вообще запускаете, в какой IDE или из командной строки или как вообще?
Запускаю в Visual Studio Code
У вас там есть scanf("%d", &check);, так что дайте ТОЧНЫЙ ввод, который вам не нравится. не просто "5 символов" - это может быть и abcde, и 12345, а это принципиально разные вещи!! Может, вы вводите не число, и чтения вообще нет! Может, вводите число, и тогда оставшийся в буфере \n считывается сразу же, первым... Кстати, похоже, что именно в этом ваша проблема, так что это просто дубль...
@Harry Ну да, это дубль. scanf запихивает не подходящий ему \n обратно в поток ввода и его нужно оттуда как-то чистить.
@CrazyElf Да как-то так вопрос был изложен, что я сразу не понял даже, о чем речь...
 
2 hours later…
18:04
Вопрос был задан нормальный. Откуда берется перенос строки '\n' после второго и последующих проходов в цикле. Опытным путем определено что на это влияет функция scanf. Теперь возник вопрос как из потока убрать перенос строки после scanf или перед getchar. Что не понятно? Всем участвующим спасибо, особенно CrazyElf.

last day (15 days later) »