Мой код следовал соответствующей логике - PullRequest
1 голос
/ 09 октября 2009

Причина, по которой я задаю этот вопрос, заключается в том, что я все еще получаю исключение нулевого указателя, даже если я уверен, что проблемы нет, но, как обычно, возможно, я допустил серьезную ошибку: D

Слайд лекции сказал это

1) Используйте переменные для хранения начального индекса и длины последовательности элементов массива, которые должны содержать запись Майка, если она есть.

2) Установите начальный индекс в 0, а длину в длину массива.

3) длина больше 1

a) Сравните Майка с именем в среднем элементе (в start_index + length / 2)

b) Если это раньше, тогда установите длину в length / 2 и оставьте стартовый индекс без изменений.

в) Если оно больше или равно, то добавьте длину / 2 к начальному индексу и вычтите длину / 2 из длины

4) длина теперь равна 1, так что, если он имеет один.

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

258132 Адамс, Аарон

199644 Адамс, Абакук

567480 Адамс, Авраам

810323 Адамс, Адам

444601 Адамс, Адлард

/**
 * Write a description of class Record here.
 * 
 * @author John Bovey 
 * @version 29 September 2009
 */
public class Record
{
    private String name;
    private String number;

    public Record(String name, String number)
    {
        this.name = name;
        this.number = number;
    }

    public String getName()
    {
        return name;
    }

    public String getNumber()
    {
        return number;
    }

}

import java.io.*;
/**
 * @author John Bovey
 * @version 29 September 2009
 */
public class PhoneBook
{
    static final int MAX_RECORDS = 50000;
    private Record list[];
    private int length;

    /**
     * Constructor for objects of class PhoneBook
     */
    public PhoneBook(String file) throws FileNotFoundException
    {
        list = new Record[MAX_RECORDS];
        BufferedReader br = new BufferedReader(new FileReader(file));
        try {
            String s = br.readLine();
            length = 0;
            while (s != null) {
                String[] args = s.split(" ", 2);
                list[length] = new Record(args[1], args[0]);
                s = br.readLine();
                length++;
            }
        }
        catch (IOException e) {
        }
    }

    **/**
     * Look a name and return the number or null if there is no match
     */
       public String search (String name)
       {          
           int startIndex = 0;
           int length = list.length;

           while(length > 1){

               if(name.compareToIgnoreCase(list[startIndex + (length / 2)].getName()) > 0) {
                length = length / 2;
               }          
               else{
                   startIndex = startIndex + (length / 2);
                   length = length - (length / 2);
               }
           }

        return list[startIndex + (length / 2)].getNumber();
    }**


    /**
     * Test the search method by looking up each name in turn
     */
     public void testSearch()
     {
         for (int i = 0; i < length; i++) {
             String name = list[i].getName();
             String num_correct = list[i].getNumber();
             String num_search = search(name);

             if (!(num_correct.equals(num_search))) {
                 System.out.printf("Failed for %s - search returned %s instead of %s\n", name, num_search, num_correct);
                 return;
            }
        }
            System.out.println("Ok.");
    }


}

Ответы [ 6 ]

1 голос
/ 09 октября 2009

Лучше всего запустить отладчик IDE, пройтись по коду и посмотреть, что происходит. Обучение использованию вашего отладчика окупит огромные дивиденды и в ваших будущих проектах.

1 голос
/ 09 октября 2009

Еще одна вещь: никогда не глотайте исключения, подобные этой:

catch (IOException e) {
}

Всякий раз, когда в вашем коде возникает IOException, вы не узнаете об этом, потому что ничего с ним не делаете. Из-за этого очень трудно отследить ошибки, потому что ваш код ведет себя правильно (вы все равно не видите ошибки).

Как минимум выведите след стека:

catch (IOException e) {
    e.printStackTrace();
}

В этом случае вы видите некоторую ошибку на вашей консоли при возникновении IOException.

1 голос
/ 09 октября 2009

Там может быть пустая строка в конце файла, который вы пытаетесь прочитать. В этом случае аргументы будут иметь размер 1, и следующие вызовут исключение:

String[] args = s.split(" ", 2);
list[length] = new Record(args[1], args[0]);

Рекомендуется сначала проверить, что строка имеет правильный формат.

Пожалуйста, также замените:

static final int MAX_RECORDS = 50000;
private Record list[];

с

private List<Record> list = new ArrayList<Record>();

Для массивов

int length = list.length;

вернет MAX_RECORDS, а не количество вставленных вами элементов. Это вызывает ваше исключение.

1 голос
/ 09 октября 2009

Одной из проблем может быть длина вашего массива "list". Вы объявляете это длиной MAX_RECORDS. Вы на самом деле заполняете каждый элемент? Если нет, ваш код будет смотреть на пустые элементы при поиске в вашем массиве. Таким образом, list [n] .getName () выдаст исключение нулевого указателя, потому что list [n] пуст. Это потому, что вы ищете из списка [0..MAX_RECORDS]. Кроме того, вы должны искать только до (MAX_RECORDS-1).

Внутри цикла while в методе search () вы не проверяете случай совпадения имен, т.е. compareToIgnoreCase () возвращает 0. В этом случае вы можете немедленно вернуть совпадение.

Вы можете объединить вышеизложенное с предложениями в других ответах:

  • переключитесь на использование массива - это даст вам переменную длину массива, которая облегчит жизнь
  • печать следов стека для ваших исключений
  • Работайте над улучшением алгоритма search (), как отмечалось выше - бинарное исследование
  • потратьте некоторое время, перебирая алгоритм поиска на бумаге, чтобы убедиться, что он выполняет то, что вам нужно
  • Пройдите через отладчик вашей IDE, если вы все еще не можете найти свою проблему

Надеюсь, все это приведет вас туда.

0 голосов
/ 09 октября 2009

Хотя это не имеет прямого отношения к вашему ответу, вы можете рассмотреть возможность использования java.util.ArrayList вместо своих массивов. Объект ArrayList изменит свою емкость в соответствии с объемом имеющихся у вас данных.

Это означает, что, скажем, вам не понадобится целый мегабайт памяти для хранения двух записей телефонной книги. И если вы решите, что хотите каталогизировать всю телефонную книгу Нью-Йорка, вы не ограничены произвольным максимумом.

0 голосов
/ 09 октября 2009

взгляните на эту строку:

list[startIndex + (length / 2)].getName()

Список [startIndex + (length / 2)] может быть нулевым, поскольку вы создаете массив с размером MAX_RECORDS, и если вы читаете только 5 записей в файле, остальные элементы, т. е. элементы 6th-MAX_RECORDS, имеют значение null, поэтому вызов getName () для null должен привести к исключению NullPointerException.

Если требуется строго использовать массив, вы также можете добавить еще одну переменную (int) ACTUAL_SIZE, а затем увеличивать этот фактический размер каждый раз после допустимого readLine (), Наконец, верхняя граница поиска не должна быть MAX_RECORDS, вместо этого используйте ACTUAL_SIZE.

Или, возможно, присвоить это значение

list[startIndex + (length / 2)] 

в другую переменную, затем сначала проверьте, не равна ли переменная нулю, перед вызовом get или set.

 Object s = list[startIndex + (length / 2)];
 if(s!= null){
     //do the checking here
 }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...