Изменение условия цикла ввода пропускает половину входных значений

#java #loops

#java #циклы

Вопрос:

Итак, я написал программу, которая создает красно-черное дерево и определяет процент красных узлов в дереве. Прямо сейчас я создаю для этого основной метод. Итак, вот что у меня есть прямо сейчас:

 public static void main(String[] args) {
    Scanner s;
    if (args.length > 0){
        try{
            s = new Scanner(new File(args[0]));
        } catch(java.io.FileNotFoundException e){
            System.out.printf("Unable to open %sn",args[0]);
            return;
        }
        System.out.printf("Reading input values from %s.n",args[0]);
    } else {
        s = new Scanner(System.in);
        System.out.printf("Enter a list of non-negative integers. Enter a negative value to end the list.n");
    }
    RedBlackBST<String, Integer> st = new RedBlackBST<String, Integer>();
    int i = 0;
    while ((s.hasNextInt())){
        int key = s.nextInt();
        st.put(key, i);
        i  ;
    }
    double percent = percentRed();
    System.out.println("There are "   redcount   " red nodes so");
    System.out.println(percent   "% of the nodes are red");
    }
  

То, что я пытаюсь сделать, это создать дерево на основе либо файла целых чисел (поэтому, если пользователь запускает программу, введя «java RedBlackBST test10.txt «который будет содержать 10 значений для вставки в дерево) или, если пользователь не укажет файл, тогда пользователю будет предложено ввести свои собственные значения и поставить отрицательное значение в конце, чтобы завершить список. Прямо сейчас ввод ваших собственных значений не работает, но если вы передадите текстовый файл чисел, то все будет работать именно так, как задумано. Теперь, что касается ввода ваших собственных значений, я думал об изменении цикла while, чтобы он выглядел следующим образом:

 while ((s.hasNextInt()) amp;amp; (s.nextInt()) >= 0){
  

Итак, что это должно сделать, это просмотреть список значений, и если вы нажмете отрицательное значение в списке, тогда он перестанет считывать значения. Проблема с этим заключается в том, что по какой-то причине (даже если я передаю файл) он считывает только половину значений для любого массива в целых числах. Итак, почему изменение цикла while теперь привело к тому, что программа считала только половину значений массива?

Также put методом, который я вызываю, является метод insert, который вставляет значения в дерево.

Ответ №1:

Предполагая, что вы буквально внесли точное изменение, о котором вы упомянули, ваш цикл в конечном итоге будет выглядеть так:

 while ((s.hasNextInt()) amp;amp; (s.nextInt()) >= 0){
    int key = s.nextInt();
    st.put(key, i);
    i  ;
}
  

Который вызывается nextInt() дважды за итерацию, что, конечно, пропускает все остальные значения, поскольку nextInt() потребляет входные данные.

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

 int key;
while ((s.hasNextInt()) amp;amp; (key = s.nextInt()) >= 0){ // <- key is assigned *and* tested
    st.put(key, i);
    i  ;
}
  

Таким образом, по одному nextInt() на итерацию.

Комментарии:

1. Но если ключ объявлен вне цикла, а внутри ничего нет, тогда я получаю сообщение об ошибке, в котором говорится, что ключ не был инициализирован.

2. @davidmah Вы бы получили эту ошибку, только если бы попытались использовать key для чего-то после цикла. Ты?

3. Ну, в цикле while я вызываю свой метод insert, который вставляет ключ в красно-черное дерево, что может вызвать проблему, если ключ ничему не назначен. Я думаю, это могло бы сработать, если бы я мог просто назначить ключ первому значению в сканере.

4. @davidmah Нет. Невозможно, чтобы ключ не мог быть назначен чему-либо в этот момент. Оно назначается в условии цикла while ( key = s.nextInt() ) перед его использованием st.put() во всех случаях, и компилятор будет доволен этим, как и должно быть. Я имею в виду, просто убедитесь сами в ошибке.

5. Я думаю, что, возможно, я понял это сам. Что я сделал, так это то, что в цикле while я установил (key = s.nextInt()) > = 0), а затем я установил значение ключа в цикле while, и тогда он не будет вызываться дважды.