Java: ввод текста из файла с использованием split - PullRequest
2 голосов
/ 25 мая 2010

Я ввожу список смежности для графа. Есть три столбца данных (вершина, место назначения, ребро), разделенных одним пробелом. Вот моя реализация до сих пор:

         FileStream in = new FileStream("input1.txt");
         Scanner s = new Scanner(in);

         String buffer;
         String [] line = null;
        while (s.hasNext()) 
        {       
            buffer = s.nextLine();
            line = buffer.split("\\s+");     
            g.add(line[0]);
            System.out.println("Added vertex " + line[0] + ".");
            g.addEdge(line[0], line[1], Integer.parseInt(line[2]));
            System.out.println("Added edge from " + line[0] + " to " + line[1] + " with a weight of " + Integer.parseInt(line[2]) + ".");                  
         }

         System.out.println("Size of graph = " + g.size());

Вот вывод:

Added vertex a.
Added edge from a to b with a weight of 9.
Exception in thread "main" java.lang.NullPointerException
    at structure5.GraphListDirected.addEdge(GraphListDirected.java:93)
    at Driver.main(Driver.java:28)

У меня сложилось впечатление, что

 line = buffer.split("\\s+");

вернет двумерный массив строк в переменную line. Казалось, сработало в первый раз, но не во второй. Какие-нибудь мысли?

Я также хотел бы получить отзыв о реализации этой проблемы. Есть ли способ лучше? Что-нибудь, чтобы помочь новичку! :)

EDIT:

Я пробовал эту реализацию ранее сегодня, но безуспешно. Я сделал это снова здесь:

FileStream in = new FileStream("input1.txt");
             Scanner s = new Scanner(in).useDelimiter("\\s+");

            while (s.hasNext()) 
            {       
                Scanner line = new Scanner(s.nextLine());
                String vertex = line.next();
                String destination = line.next();
                int weight = line.nextInt();     
                g.add(vertex);
                System.out.println("Added vertex " + vertex + ".");
                g.addEdge(vertex, destination, weight);
                System.out.println("Added edge from " + vertex + " to " + destination + " with a weight of " + weight + ".");                  
             }

             System.out.println("Size of graph = " + g.size()); 

Выход:

Added vertex a.
Exception in thread "main" java.lang.NullPointerException
    at structure5.GraphListDirected.addEdge(GraphListDirected.java:93)
    at Driver.main(Driver.java:22)

Edit2:

Вот функция addEdge. Это не моя собственная реализация, я использую ее, чтобы сэкономить время, когда я слабо пишу свою собственную на этом начальном этапе ...

package structure5;
import java.util.Iterator;


abstract public class GraphList<V,E> extends AbstractStructure<V> implements Graph<V,E>
{
    protected Map<V,GraphListVertex<V,E>> dict; // label -> vertex

    protected boolean directed; // is graph directed?


    protected GraphList(boolean dir)
    {
        dict = new Hashtable<V,GraphListVertex<V,E>>();
        directed = dir;
    }

    public void add(V label)
    {
        if (dict.containsKey(label)) return; // vertex exists
        GraphListVertex<V,E> v = new GraphListVertex<V,E>(label);
        dict.put(label,v);
    }


    abstract public void addEdge(V v1, V v2, E label);
}

Graph.java:

package structure5;
import java.util.Iterator;

public interface Graph<V,E> extends Structure<V>
{
    public void add(V label);


    public void addEdge(V vtx1, V vtx2, E label);
}

Примечание: я опускаю остальные методы, не относящиеся к программе

Edit3: Вот это GraphListDirected.java

public class GraphListDirected<V,E> extends GraphList<V,E>
{
    public GraphListDirected()
    {
        super(true);
    }
    public void addEdge(V vLabel1, V vLabel2, E label)
    {
        GraphListVertex<V,E> v1 = dict.get(vLabel1);
        GraphListVertex<V,E> v2 = dict.get(vLabel2);
        Edge<V,E> e = new Edge<V,E>(v1.label(), v2.label(), label, true);   //Line 93
        v1.addEdge(e);
    }

Ответы [ 2 ]

2 голосов
/ 25 мая 2010

String.split возвращает String[], одномерный массив, никогда не двумерный массив. Вы можете, конечно, далее split a String, который был результатом split (и так далее).

Сказав это, поскольку вы уже используете Scanner, вам никогда не нужно использовать split, Integer.parseInt и т. Д. Просто создайте еще один Scanner для сканирования s.nextLine().

Scanner line = new Scanner(s.nextLine());
String from = line.next();
String to = line.next();
int weight = line.nextInt();

Я не уверен, что вызвало NullPointerException, хотя мы знаем из вашего вывода, что по крайней мере один край был успешно добавлен.

API ссылки

  • Scanner(String source)
    • Создает новый Scanner, который создает значения, отсканированные из указанной строки.

На несколько Scanner

Маленький А-ха !! момент - это осознание того, что, как вы можете split на основе результата предыдущего split, вы можете создать Scanner для сканирования возвращаемых строк от другого Scanner.

    String inputText =
        "Line1 a b\n" +
        "Line2 d e f\n" +
        "Line3";
    Scanner input = new Scanner(inputText);
    while (input.hasNext()) {
        Scanner line = new Scanner(input.nextLine());
        System.out.println("[" + line.next() + "]");
        while (line.hasNext()) {
            System.out.println("  " + line.next());
        }
    }

Вышеуказанные отпечатки фрагментов:

[Line1]
  a
  b
[Line2]
  d
  e
  f
[Line3]

Это простой пример, но вы можете увидеть значение этого метода, когда каждая строка более сложна, например, когда он содержит числа и шаблоны регулярных выражений.


На NullPointerException

Вам нужно add обе начальные и конечные вершины из-за способа реализации addEdge.

            Scanner line = new Scanner(s.nextLine());
            String vertex = line.next();
            String destination = line.next();
            int weight = line.nextInt();     
            g.add(vertex);
            g.add(destination); // <--- ADD THIS LINE!!
            g.addEdge(vertex, destination, weight);

Это должно исправить NullPointerException.

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

0 голосов
/ 25 мая 2010

Как уже упоминалось о полигенных смазочных материалах, split () возвращает String [], а не String [] [].

Обратите внимание, что split () будет перекомпилировать шаблон регулярного выражения при каждой итерации цикла. Если ваш ввод небольшой, это не имеет значения, но если ваш ввод большой (может быть, тысячи итераций), вам лучше использовать второй сканер внутри цикла или шаблон, скомпилированный вне цикла.

Чтобы добраться до сути исключения NullPointerException, я бы предложил использовать отладчик (например, включенный в Eclipse) и установить точку останова в строке 93 GraphListDirected.java (строка, сообщаемая в трассировке стека). Каждый раз, когда breakpiont приостанавливает вашу программу в этой строке, дважды проверяйте все ваши значения, чтобы убедиться, что они соответствуют вашим ожиданиям.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...