Форум программистов, компьютерный форум, киберфорум
Java для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.64/11: Рейтинг темы: голосов - 11, средняя оценка - 4.64
0 / 0 / 0
Регистрация: 20.01.2013
Сообщений: 10

Цикл Do-While исполняется лишний раз

27.10.2021, 22:53. Показов 2622. Ответов 21
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Простецкая демонстрация работы цикла do-while вызвала у меня ступор.

Система просит ввести символ, и, если он не равен заданному, просит ввести снова, и т.д.

Java
1
2
3
4
5
6
7
8
9
10
11
class Main {
    public static void main(String args[])
            throws java.io.IOException {
        char ch;
        do {
            System.out.println("Press any key, then ENTER:  ");
            ch = (char) System.in.read();
        }
        while (ch != 'q');
    }
}
Но он выводит сообщение трижды!
(а в IDEA - почему-то дважды).

Java
1
2
3
4
5
6
7
8
9
10
11
12
13
Press any key, then ENTER:
h
Press any key, then ENTER:
Press any key, then ENTER:
Press any key, then ENTER:
k
Press any key, then ENTER:
Press any key, then ENTER:
Press any key, then ENTER:
t
Press any key, then ENTER:
Press any key, then ENTER:
Press any key, then ENTER:
Далее, если ввести два символа, то строковое сообщение выводится 4 раза:
Java
1
2
3
4
5
jj
Press any key, then ENTER:
Press any key, then ENTER:
Press any key, then ENTER:
Press any key, then ENTER:
Если 5 символов - то 7 раз, и так далее, сообщений на 2 больше, чем символов.

Помогите, пожалуйста, чайнику понять:
1. как вывести строку по одному разу, используя do-while.
2. как количество введенных символов коррелирует с количеством строковых сообщений.
0
Лучшие ответы (1)
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
27.10.2021, 22:53
Ответы с готовыми решениями:

_getch() считывает номер и прогоняет цикл лишний раз
for (int i = 0;i<6; i++) { sim = _getch(); printf("%c ",sim); sim = 0; } Гетч считает три элемента и после каждого...

VBA стандартный поиск .FindNext цикл выполняется лишний раз нормально ли это?
делаю скрипт для нашей бухгалтерии и столкнулся с непонятной фигней: есть таблица в которой могут быть месяца с разными расходами а могут и...

Цикл отрабатывает "лишний" раз
Суть проблемы такова: делаю поисковую форму по записям БД. Вывод информации осуществляется следующим кодом: //$col_res - количество...

21
14 / 11 / 3
Регистрация: 13.07.2018
Сообщений: 37
28.10.2021, 02:55
Вы методом read считываете байт а не символ, попробуйте вывести каждый байт в 16ти ричном формате. Другими словами ваш символ может и 2 байта занимать.
Вы запускаете программу которая читает стандартный ввод, а что ей там на ввод приходит надо тоже понять. Даже когда вы нажали enter это тоже символ перехода.
0
0 / 0 / 0
Регистрация: 20.01.2013
Сообщений: 10
28.10.2021, 14:59  [ТС]
Пример взят из книги Г. Шилдта "Java для начинающих", 2019.

Добавлено через 5 часов 31 минуту
Помогло добавление цикла (стр. 8 - 12).

Но я пока не понял, почему. К сожалению. Может, дальше по книге это будет разъяснено.

Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Main {
    public static void main(String args[])
            throws java.io.IOException {
        char ch, ignore;
        do {
            System.out.println("Press any key, then ENTER:  ");
            ch = (char) System.in.read();
            do {
                ignore = (char) System.in.read();
               }
            while (ignore !='\n');
        }
        while (ch != 'q');
    }
}
Добавлено через 26 минут
Насколько я понял, первый символ считывается в рамках основного цикла, а все остальные отбрасываются, если они не равны '/n', т.е. нажатию ENTER.
0
14 / 11 / 3
Регистрация: 13.07.2018
Сообщений: 37
28.10.2021, 15:18
Лучший ответ Сообщение было отмечено s_grooz как решение

Решение

Все очень просто:
1) System.in это поток стандартного ввода, вы читаете оттуда по 1 байту и это неоспоримый факт.
2) с учетом пункта 1 выходит что туда попадает более 1 символа.
3) Надо задать вопрос, кто туда запихивает более 1 символа?

И вот в пункте 3 возник сам вопрос. Если вы запустите программу и посмотрите кто родитель процесса, то вы узнаете кто владелец потока ввода вашего процесса. Собственно если приходит что-то лишнее, то проблема скорее всего в нем(В процессе - родителе вашего процесса)

Вот я немного вставил печати в ваше программу:

Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Main {
    public static void main(String args[])
            throws java.io.IOException {
        char ch, ignore;
        do {
            System.out.println("Press any key, then ENTER:  ");
            ch = (char) System.in.read();
            System.out.println("Ch = " + ch);
            do {
                ignore = (char) System.in.read();
                System.out.printf("ch(hex) = 0x%02x \n", (byte)ignore);
               }
            while (ignore !='\n');
        }
        while (ch != 'q');
    }
}
и вот какой вывод:
PowerShell
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
darkduke@darkduke-pc:/tmp $ java Main 
Press any key, then ENTER:  
df
Ch = d
ch(hex) = 0x66 
ch(hex) = 0x0a 
Press any key, then ENTER:  
g
Ch = g
ch(hex) = 0x0a 
Press any key, then ENTER:  
f
Ch = f
ch(hex) = 0x0a 
Press any key, then ENTER:  
g
Ch = g
ch(hex) = 0x0a 
Press any key, then ENTER:  
h
Ch = h
ch(hex) = 0x0a 
Press any key, then ENTER:  
j
Ch = j
ch(hex) = 0x0a 
Press any key, then ENTER:  
f
Ch = f
ch(hex) = 0x0a 
Press any key, then ENTER:  
j
Ch = j
ch(hex) = 0x0a 
Press any key, then ENTER:
Как видите все так как должно быть:
Когда ввел df: первый символ считало и он тот что надо, второй f - его код 0x66 , и наконец 0x0a это наш '\n'
Когда ввел g: первый g, второй 0x0a это наш '\n'
итд....

По сути вы нашали 2 кнопки, значит получили 2 символа. Запуск я сделал из консоли линукса и если в idea не так, то проблема именно в консоли idea.
1
Эксперт функциональных языков программированияЭксперт Java
 Аватар для korvin_
4575 / 2774 / 491
Регистрация: 28.04.2012
Сообщений: 8,779
28.10.2021, 15:48
Цитата Сообщение от darkduke Посмотреть сообщение
Все очень просто:
1) System.in это поток стандартного ввода, вы читаете оттуда по 1 байту и это неоспоримый факт.
2) с учетом пункта 1 выходит что туда попадает более 1 символа.
3) Надо задать вопрос, кто туда запихивает более 1 символа?
И вот в пункте 3 возник сам вопрос. Если вы запустите программу и посмотрите кто родитель процесса, то вы узнаете кто владелец потока ввода вашего процесса. Собственно если приходит что-то лишнее, то проблема скорее всего в нем(В процессе - родителе вашего процесса)
WTF?

ТС вводит <символ><ENTER> --- это два или три символа в зависимости от ОС/терминала: "q\n" или "q\r\n". Какие процессы, о чём ты вообще?
2
3582 / 2182 / 571
Регистрация: 02.09.2015
Сообщений: 5,510
28.10.2021, 15:58

Не по теме:

Цитата Сообщение от darkduke Посмотреть сообщение
вы читаете оттуда по 1 байту и это неоспоримый факт.
Сейчас бы считать char одним байтом...


0
14 / 11 / 3
Регистрация: 13.07.2018
Сообщений: 37
28.10.2021, 16:10
О том самом, поток ввода процесса у кого? Вы говорите в зависимости от ОС/Терминала, а потом спрашиваете о процессах?
Но вы правильно написали про терминал, странно что вы удивляетесь тому как устроены ОС и их процессы.
Вот пример дерева процессов в линуксе (ps axjf) до java процесса нашей программки:

540- 3924 54626 3923 3923 ? -1 Sl 1000 0:15 \_ /usr/bin/konsole
541- 54626 54639 54639 54639 pts/1 66962 Ss 1000 0:00 \_ /bin/bash
542: 54639 66962 66962 54639 pts/1 66962 Sl+ 1000 0:00 | \_ java Main

Владелец потока bash, а дальше уже зависит от того как реализована консоль внутри. Может там делают обычный dup2() при fork(), а можно и обработать добавив всякий бред. В целом вы правы. Мне же важно донести суть того, как все устроено, т.к. тема для новичков. Надо смотреть глубже а не только в java сидеть.
0
28.10.2021, 16:12

Не по теме:

Цитата Сообщение от Arsegg Посмотреть сообщение
Сейчас бы считать charодним байтом...
Речь про InputStream.read

0
3582 / 2182 / 571
Регистрация: 02.09.2015
Сообщений: 5,510
28.10.2021, 16:13
Цитата Сообщение от s_grooz Посмотреть сообщение
1. как вывести строку по одному разу, используя do-while.
Scanner:
Java
1
2
3
4
final var scanner = new Scanner(System.in);
do {
  System.out.println("Press any key, then ENTER:");
} while (!"q".equalsIgnoreCase(scanner.nextLine()));
BufferedReader:
Java
1
2
3
4
final var br = new BufferedReader(new InputStreamReader(System.in));
do {
  System.out.println("Press any key, then ENTER:");
} while (!"q".equalsIgnoreCase(br.readLine()));
1
14 / 11 / 3
Регистрация: 13.07.2018
Сообщений: 37
28.10.2021, 16:16
Цитата Сообщение от Arsegg Посмотреть сообщение

Не по теме:


Сейчас бы считать char одним байтом...


Что? Рука - лицо? Это форум издевающихся людей и тролей чтоли?
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
    /**
     * Reads the next byte of data from the input stream. The value byte is
     * returned as an <code>int</code> in the range <code>0</code> to
     * <code>255</code>. If no byte is available because the end of the stream
     * has been reached, the value <code>-1</code> is returned. This method
     * blocks until input data is available, the end of the stream is detected,
     * or an exception is thrown.
     *
     * <p> A subclass must provide an implementation of this method.
     *
     * @return     the next byte of data, or <code>-1</code> if the end of the
     *             stream is reached.
     * @exception  IOException  if an I/O error occurs.
     */
    public abstract int read() throws IOException;
0
3582 / 2182 / 571
Регистрация: 02.09.2015
Сообщений: 5,510
28.10.2021, 16:23
darkduke, с тобой все в порядке, когда ты байт из InputStream называешь UTF-16 символом char?
Цитата Сообщение от darkduke Посмотреть сообщение
2) с учетом пункта 1 выходит что туда попадает более 1 символа.
3) Надо задать вопрос, кто туда запихивает более 1 символа?
P. S. Мог бы и намекнуть ТСу про класс InputStreamReader, а не городить ахинею:
An InputStreamReader is a bridge from byte streams to character streams: It reads bytes and decodes them into characters using a specified charset.
Добавлено через 1 минуту
P. P. S. А если бы ТС читал данные из UTF-32 потока? Тоже сказал бы, что 2 символа?
0
14 / 11 / 3
Регистрация: 13.07.2018
Сообщений: 37
28.10.2021, 16:57
Цитата Сообщение от Arsegg Посмотреть сообщение
darkduke, с тобой все в порядке, когда ты байт из InputStream называешь UTF-16 символом char?

P. S. Мог бы и намекнуть ТСу про класс InputStreamReader, а не городить ахинею:


Добавлено через 1 минуту
P. P. S. А если бы ТС читал данные из UTF-32 потока? Тоже сказал бы, что 2 символа?
Про то что символ может занимать более 1 байта, это и так понятно, об этом я написал в самом начале поста посмотрите 2е сообщение. В данном кейсе человек изучает java по книге Герберта Шилда, ищет ответы, а не ждет готовых решений. К тому же если вы не заметили, то символ 'q' считался нормально в первом байте, а значит речь идет явно не о UTF-16 или UTF-32... Откуда столько яда.... не понимаю.... Как только даешь людям знания, уже знающих людей распирает какая то злоба и ненависть.... Не противно самим то?
0
Эксперт PythonЭксперт Java
19530 / 11067 / 2931
Регистрация: 21.10.2017
Сообщений: 23,294
28.10.2021, 17:00
darkduke, так ув.korvin_ в 5-м посте все обосновал, чего непонятного-то? И зачем какой-то огород городить?
0
14 / 11 / 3
Регистрация: 13.07.2018
Сообщений: 37
28.10.2021, 17:13
Цитата Сообщение от iSmokeJC Посмотреть сообщение
darkduke, так ув.korvin_ в 5-м посте все обосновал, чего непонятного-то? И зачем какой-то огород городить?
Хотя бы потому, что родителем java процесса может быть не только консоль, но и другие процессы. Я объяснил в общем, он в более узком понимании ограничившись (OS/Терминалом), но суть та же. Мне сыпятся упреки, а вот зачем это непонятно.. Хочется иногда отправить людей читать Робачевского, но Windows-фанаты обидятся.
0
Эксперт PythonЭксперт Java
19530 / 11067 / 2931
Регистрация: 21.10.2017
Сообщений: 23,294
28.10.2021, 17:16
darkduke, ты же сам выше заострил внимание на том, что ТС только учится, и учится по Шилдту. То бишь основы. Зачем ему лить в уши страшную информацию о процессах и их хозяевах? Пятый пост - все что нужно ТСу на данном этапе.
0
3582 / 2182 / 571
Регистрация: 02.09.2015
Сообщений: 5,510
28.10.2021, 17:17
darkduke, причем тут консоль и процессы, если дело в кодировке потока ввода?
0
14 / 11 / 3
Регистрация: 13.07.2018
Сообщений: 37
28.10.2021, 18:08
Цитата Сообщение от Arsegg Посмотреть сообщение
darkduke, причем тут консоль и процессы, если дело в кодировке потока ввода?
Потому что кодировка в данном кейсе к этому вообще отношения не имеет, тут фишка именно в том, что передает родительский процесс в дескриптор ввода jvm.
В данном случае терминал(процесс - родитель) считает, что надо передать код символа и код '\n' и возможно код символа перевода каретки. Поэтому и сказал распечатать коды того, что считалось дальше. Тогда наглядно видно что происходит. Почему так рассказываю подробно? Потому, что когда джун приходит на собеседование, то его нечего толком спросить и спрашивают основы. И чтобы не было как однажды ко мне пришел собеседоватся бывший 1С программист лет 40...
Спрашиваю:
- какое макс число в Int... ?
- молчание....
-потом сколько байт в int.. ?
- молчание...
(прошло 5 мин но методом перебора угадали... и сошлись на 4х)
- потом сколько бит в Int?
прошло мин 10.... нет ответа...
-Хорошо, давайте так: сколько бит в байте
- 8...
(думаю ура, сейчас мне скажут сколько бит в Int, а там и до 231 - 1) дойдем
- итак в Int 4 байта и по 8 бит в каждом, так сколько будет бит в Int?
- 24..
- Точно?
-Да
- Вы уверены?
-Да, что я таблицу умножения чтоли не знаю???
(Тут я просто скатился под стол еле сдерживая эмоции)
- Мы свяжемся с вами, спасибо за уделенное время....
(Про себя подумал, За что, он так со мною????)
0
3582 / 2182 / 571
Регистрация: 02.09.2015
Сообщений: 5,510
28.10.2021, 18:41
Цитата Сообщение от darkduke Посмотреть сообщение
Потому что кодировка в данном кейсе к этому вообще отношения не имеет
Как же не имеет?
Попробуйте на досуге перенаправить вывод из файла в ввод программы (java YourClass.java < input.txt):
Java
1
2
3
4
5
int i;
do {
    i = System.in.read();
    System.out.println(i);
} while (i >= 0);
Получите интересные результаты работы:
Windows-1251/UTF-8:
Code
1
2
74
-1
UTF-16BE:
Code
1
2
3
4
5
254
255
0
74
-1
Содержимое файла input.txt:
Code
1
J
P. S. Программа должна обрабатывать данные не только с консоли, где, порой, творится полная вакханалия с кодировками и CR/LF/CRLF, но и с любого потока ввода/вывода.

Добавлено через 7 минут
Цитата Сообщение от darkduke Посмотреть сообщение
какое макс число в Int... ?
Вопрос, как по мне, некорректный, т. к. напрашивается сразу встречный вопрос: unsigned или signed int? От этого и будет зависит ответ.
1
14 / 11 / 3
Регистрация: 13.07.2018
Сообщений: 37
28.10.2021, 19:08
Цитата Сообщение от Arsegg Посмотреть сообщение
Как же не имеет?
Попробуйте на досуге перенаправить вывод из файла в ввод программы (java YourClass.java < input.txt):
Java
1
2
3
4
5
int i;
do {
    i = System.in.read();
    System.out.println(i);
} while (i >= 0);
Получите интересные результаты работы:
Windows-1251/UTF-8:
Code
1
2
74
-1
UTF-16BE:
Code
1
2
3
4
5
254
255
0
74
-1
Содержимое файла input.txt:
Code
1
J
P. S. Программа должна обрабатывать данные не только с консоли, где, порой, творится полная вакханалия с кодировками и CR/LF/CRLF, но и с любого потока ввода/вывода.

Добавлено через 7 минут

Вопрос, как по мне, некорректный, т. к. напрашивается сразу встречный вопрос: unsigned или signed int? От этого и будет зависит ответ.
Вопрос был именно про знаковый int))) Если бы без знаковый я бы написал unsigned int, но все это фигня по сравнению 4*8 = 24.... мы с коллегой просто в этот момент заклинили, и слова даже сказать не могли.... К сожалению, часто вижу в коде как джуны пишут int, там где надо бы использовать long. Они даже не задумываются. Хотя от джунов требуются хорошие теор. знания, практику с них все равно не получишь т.к. ее априори нет. При этом просят на старте они 100к+. А про кодировки автор поста позже прочитает в полноценной книжке Герберда Шилда (Java Полное Руководство), там на это серьезный акцент.
0
3582 / 2182 / 571
Регистрация: 02.09.2015
Сообщений: 5,510
28.10.2021, 19:26

Не по теме:

Цитата Сообщение от darkduke Посмотреть сообщение
Вопрос был именно про знаковый int)))
Integer.MAX_VALUE)))




Добавлено через 4 минуты

Не по теме:

Цитата Сообщение от darkduke Посмотреть сообщение
но все это фигня по сравнению 4*8 = 24....
На дизморали кандидат. Зачем доводить соискателей до такого? Уровня, а какое максимальное число можно сохранить в BigInteger/BigDecimal/long/float/double и т. п. Знание абсолютно бесполезное, имхо.



Добавлено через 8 минут

Не по теме:

Цитата Сообщение от darkduke Посмотреть сообщение
К сожалению, часто вижу в коде как джуны пишут int, там где надо бы использовать long.
От джунов, как по мне, это не должно требоваться - код ревью есть для этого.
P. S. Взять, например, переполнение счетчика просмотров (int) клипа Gangnam Style на Youtube. Это ошибка джуна?

0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
28.10.2021, 19:26
Помогаю со студенческими работами здесь

Счетик не работает, код исполняется только один раз
помогите пожалуйста! ]$b For ($i=0; $i –lt 20; $i++) {$b += (measure-Command {Get-Childitem &quot;C:\games\Ll&quot; -Filter ″*.txt″...

WM_SHOWWINDOW - код исполняется много раз и приложение подвисает
Добрый день. Описание проблемы: код должен исполнятся только 1 раз а он исполняется много раз. Приложение при этом подвисает. По...

В Паскале цикл for исполняется с шагом 1 (-1). А как выполнить любой другой шаг?
В Паскале цикл for исполняется с шагом 1 (-1). А как выполнить любой другой шаг?

Лишний цикл
Доброго времени суток! Возникла весьма интересная ситуация, в методе paintComponent возникла проблема в элементарнейшем цикле ...

Как убрать лишний цикл
Sub CopyDoc() Dim d As Document Dim s As Shape Dim Lg As Layer Set s = ActiveShape For Each d In Application.Documents For...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
Семь CDC на одном интерфейсе: 5 U[S]ARTов, 1 CAN и 1 SSI
Eddy_Em 18.02.2026
Постепенно допиливаю свою "многоинтерфейсную плату". Выглядит вот так: https:/ / www. cyberforum. ru/ blog_attachment. php?attachmentid=11617&stc=1&d=1771445347 Основана на STM32F303RBT6. На борту пять. . .
Символьное дифференцирование
igorrr37 13.02.2026
/ * Программа принимает математическое выражение в виде строки и выдаёт его производную в виде строки и вычисляет значение производной при заданном х Логарифм записывается как: (x-2)log(x^2+2) -. . .
Камера Toupcam IUA500KMA
Eddy_Em 12.02.2026
Т. к. у всяких "хикроботов" слишком уж мелкий пиксель, для подсмотра в ESPriF они вообще плохо годятся: уже 14 величину можно рассмотреть еле-еле лишь на экспозициях под 3 секунды (а то и больше),. . .
И ясному Солнцу
zbw 12.02.2026
И ясному Солнцу, и светлой Луне. В мире покоя нет и люди не могут жить в тишине. А жить им немного лет.
«Знание-Сила»
zbw 12.02.2026
«Знание-Сила» «Время-Деньги» «Деньги -Пуля»
SDL3 для Web (WebAssembly): Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 12.02.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами и вызывать обработчики событий столкновения. . . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 11.02.2026
Содержание блога Библиотека SDL3 содержит встроенные инструменты для базовой работы с изображениями - без использования библиотеки SDL3_image. Пошагово создадим проект для загрузки изображения. . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL3_image
8Observer8 10.02.2026
Содержание блога Библиотека SDL3_image содержит инструменты для расширенной работы с изображениями. Пошагово создадим проект для загрузки изображения формата PNG с альфа-каналом (с прозрачным. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru