Для цикла в Java запускается 3 раза, прежде чем принимать следующий ввод

Я новичок в Java и изучаю его. Я пробовал код, чтобы увидеть, как цикл for-each работает на Java. Но я столкнулся с проблемой. Мой код прост:

class ForEach
{
public static void main(String[] args) throws java.io.IOException
{
    char[] array = new char[10];

    for(int i = 0; i < 10; i++)
    {
        System.out.println("Enter Character " + i);
        array[i] = (char)System.in.read();
    }

    System.out.println("Displaying characters in array : ");

    for(char i : array)
    {
        System.out.println(i);
    }
}
}

но выход неудобен. Я уверен, что с моим кодом что-то не так. Я не могу просто найти его. Результат этого кода:

Enter Character 0
a
Enter Character 1
Enter Character 2
Enter Character 3
b
Enter Character 4
Enter Character 5
Enter Character 6
c
Enter Character 7
Enter Character 8
Enter Character 9
d
Displaying characters in array :
a


b


c


d

Я не понимаю, почему цикл for работает трижды, прежде чем он берет другой вход от пользователя?

Любая помощь? Заранее благодарю вас.

Ответ 1

Я предполагаю, что вы работаете в Windows, потому что это поведение похоже на Windows.

Когда вы вводите символ, вы делаете что-то вроде этого:

  • Нажмите a
  • Нажмите return

Шаг 2 передает последовательность разделителей строк, которая указывает на введенную консоль ввода, которая сообщает консоли, что вы закончили ввод этой строки ввода. Таким образом консоль передает всю строку в вашу программу.

Эта последовательность разделителей строк в Windows состоит из символа возврата каретки '\r', за которым следует символ новой строки '\n'. Итак, ваша линия действительно "a\r\n".

Что System.in.read() делает, читается один байт из входной консоли. Поскольку символы, которые вы вводите, вписываются в один байт, то, что делает ваша программа, потребляет введенные символы один за другим, так что это примерно так:

Output: Enter Character 0
> User inputs: "a\r\n" // You only entered 'a', the other two characters are from the enter key
array[0] = System.in.next(); // sets array[0] to 'a', "\r\n" are still "waiting" on the input stream

Output: Enter Character 1
> String "\r\n" is still on input, so read from those:
array[1] = System.in.next(); // sets array[1] to '\r', "\n" is still "waiting"

Output: Enter Character 2
> String "\n" is still on input, so read from that
array[2] = System.in.next(); // sets array[2] to '\n', input source is now empty

Output: Enter Character 3
> Nothing is waiting on the input stream, so program waits for user input

... and so on

То, что вы хотите сделать, это сделать Scanner, и сразу прочитать целую строку, так что единственным персонажем, который вы обрабатываете, является введенный вами контент:

Scanner scanner = new Scanner(System.in); // Creates a new scanner that reads from System.in
String line = scanner.nextLine(); // Reads an entire line from console, **not including newline breaks at the end of a line**
// use line.charAt(i) to get individual characters, or use line.toCharArray() to get the string backing char[]

Если вы должны были печатать целые значения каждого из элементов в вашем массиве, вы фактически увидите числа, в которых ваша консоль выводит пустые строки. Эти числа представляют собой числовые эквиваленты ASCII для символов '\r' и '\n'.

Интересно, я считаю, что если бы вы запускали это в системе * nix, вы бы пропустили только одну строку вместо двух. Это связано с тем, что * nix-системы используют только '\n' в качестве своего разделителя строк, поэтому у вас будет только один дополнительный символ в конце вашей строки.

Кроме того, я не совсем уверен, почему ваша консоль выводит строку для '\r' и '\n'; может быть, что Java разбивает строки для обоих символов внутри, а Windows - нет. Таким образом, вы можете получить разные результаты, если попытаетесь запустить это в оболочке Windows.

Ответ 2

Из API Java:

Считывает следующий байт данных из входного потока.

Что происходит, когда вы вводите a, за которым следует новая строка, на самом деле есть три байта для чтения (я предполагаю a, за которым следует возврат каретки и новая строка). Следовательно, вводимый вами ввод достаточно, чтобы read() выполнял три итерации.

Вместо этого я рекомендую использовать Scanner для ввода.