2014-03-04 13 views
5

Es gibt ein paar dieser Themen da draußen, aber dieses Problem hat eine kleine Wendung, die es anders macht..txt-Datei in 2D-Array lesen

Ich bin auf nur die Hälfte eines größeren Problems konzentriert. Ich bin mir sicher, dass viele von Ihnen das magische Quadratproblem kennen.

Prompt:
Es sei angenommen, eine Datei mit Linien und Zahlen in jeder Zeile wie das Quadrat dargestellt. Schreiben Sie ein Programm, das Informationen in ein zweidimensionales Array von IntS liest. Das Programm sollte bestimmen, ob die Matrix ein magisches Quadrat ist oder nicht.

Arbeitslösung:

public static int[][] create2DIntMatrixFromFile(String filename) throws Exception { 
int[][] matrix = {{1}, {2}}; 

File inFile = new File(filename); 
Scanner in = new Scanner(inFile); 

int intLength = 0; 
String[] length = in.nextLine().trim().split("\\s+"); 
    for (int i = 0; i < length.length; i++) { 
    intLength++; 
    } 

in.close(); 

matrix = new int[intLength][intLength]; 
in = new Scanner(inFile); 

int lineCount = 0; 
while (in.hasNextLine()) { 
    String[] currentLine = in.nextLine().trim().split("\\s+"); 
    for (int i = 0; i < currentLine.length; i++) { 
     matrix[lineCount][i] = Integer.parseInt(currentLine[i]);  
      } 
    lineCount++; 
}         
return matrix; 
} 


public static boolean isMagicSquare(int[][] square) { 

    return false; 
} 

Hier ist mein (alter) Code für in einen 2D-Array aus einer Textdatei Informationen zu lesen:

public static int[][] create2DIntMatrixFromFile(String filename) throws Exception { 
    int[][] matrix = {{1}, {2}}; 
    File inFile = new File(filename); 
    Scanner in = new Scanner(inFile); 
    in.useDelimiter("[/n]"); 

    String line = ""; 
    int lineCount = 0; 

    while (in.hasNextLine()) { 
     line = in.nextLine().trim(); 
     Scanner lineIn = new Scanner(line); 
     lineIn.useDelimiter(""); 

     for (int i = 0; lineIn.hasNext(); i++) { 
      matrix[lineCount][i] = Integer.parseInt(lineIn.next()); 
      lineIn.next(); 
     } 

     lineCount++; 
    } 

    return matrix; 
} 

public static boolean isMagicSquare(int[][] square) { 
    return false; 
} 

Und hier ist die Textdatei Ich bin Lesen von. Es hat die Form eines 9x9-2D-Arrays, aber das Programm muss ein Array mehrdeutiger Größe aufnehmen.

37 48 59 70 81 2 13 24 35 
    36 38 49 60 71 73 3 14 25 
    26 28 39 50 61 72 74 4 15 
    16 27 29 40 51 62 64 75 5 
    6 17 19 30 41 52 63 65 76 
    77 7 18 20 31 42 53 55 66 
    67 78 8 10 21 32 43 54 56 
    57 68 79 9 11 22 33 44 46 
    47 58 69 80 1 12 23 34 45 

Es gibt zwei Leerzeichen, die absichtlich jede Zeile durchlaufen.

Bevor ich das genaue Problem angeben, ist dies eine Hausaufgabenvorlage, so dass die Methodendeklaration und Variableninitialisierung vorher festgelegt wurde.

Ich bin nicht sicher, dass die Methode sogar ein 2D-Array korrekt aus der Datei erstellt, weil ich es noch nicht ausführen kann. Das Problem ist, dass "Matrix" aus irgendeinem Grund mit 1 Spalte und 2 Zeilen initialisiert wurde. Aus welchem ​​Grund bin ich nicht sicher, aber um ein Array mit den Zahlen aus der Datei zu füllen, muss ich ein 2D-Array mit Dimensionen erstellen, die der Anzahl der Werte in einer Zeile entsprechen.

Ich hatte vorher Code geschrieben, um einen neuen 2D-Array erstellen

int[line.length()][line.length()] 

aber es hat eine 36x36-Array erstellt, weil das ist, wie viele einzelnen Zeichen in einer Zeile sind. Ich habe das Gefühl, dass es so einfach ist, die erste Zeile zu durchlaufen und einen Zähler zu haben, der jede durch eine Null getrennte Zahlenfolge verfolgt.

Für mich scheint diese Lösung zu ineffizient und zeitaufwendig, nur um die Dimensionen des neuen Arrays zu finden. Was ist der beste Weg, dies zu erreichen? Ohne ArrayLists zu verwenden, da ich dieses Programm nach der Verwendung von ArrayLists neu schreiben muss.

+0

Um die Zahlen in einer bestimmten Zeile zu erhalten, können Sie einfach 'line.split (" ");'. – ggmathur

Antwort

1

Sie sind in der Nähe, aber Ihre while-Schleife wie folgt aussehen ändern:

while (in.hasNextLine()) { 
    Scanner lineIn = new Scanner(line); 
    //The initial case - this first line is used to determine the size of the array 
    if(lineIn.hasNext()) { 
     //Create a String array by splitting by spaces 
     String[] s = lineIn.nextLine().split(" "); 
     //Reinitialize the array to hold all of your subarrays 
     matrix = new int[s.length]; 
     for (int i = 0; i < s.length; i++) { 
      //Reinitialize each subarray to hold the numbers 
      matrix[i] = new int[i]; 
      //Finally, parse your data from the String array 
      matrix[0][i] = Integer.parseInt(s[i]); 
     } 
    } 
    //Repeat the steps now that all of your arrays have been initialized 
    for (int j = 1; j < matrix.length; j++) { 
     String[] s = lineIn.nextLine().split(" "); 
     for (int i = 0; i < s.length; i++) { 
      matrix[j][i] = Integer.parseInt(s[i]); 
     } 
    } 
} 

Die größte Veränderung, die Sie dies einfacher machen können, um auf sich selbst ist Ihre Zahlen line-by-line zu erhalten . Mit jeder Zeile, die Sie erhalten, ist es einfach, sie in ein String-Array zu zerlegen, so dass Sie jede Zahl einzeln analysieren können. Auf diese Weise können Sie dann die gesamte Länge des Arrays auf einmal abrufen, ohne lästige Zähler haben zu müssen.

+0

Ich habe diese Schleife implementiert, aber ich bekomme einen Fehler "No So Element" auf ".nextLine()" und ich bin mir nicht sicher, an welchem ​​Punkt es das Ende der Datei erreicht. – BimmerM3

0

Testen Sie zunächst die Scanner-Ergebnisse. Ich glaube nicht, dass diese Trennzeichen funktionieren. (BTW, Scanner nextInt() Methode ist praktisch.)

Wenn Sie annehmen können, dass die Eingabe eine quadratische Matrix ist, wird beim Scannen der ersten Zeile angezeigt, wie viele Ganzzahlen es enthält. Dann können Sie die Arrays (neu) zuordnen. Verarbeiten Sie dann alle Zeilen, einschließlich der ersten Zeile, die Sie bereits gescannt haben.

Dann können Sie einstellen, matrix = new int[n][n];

5

Ich habe den folgenden 2D-Array aus der Datei, die Sie zur Verfügung gestellt:

37 | 48 | 59 | 70 | 81 | 2 | 13 | 24 | 35 
----+----+----+----+----+----+----+----+---- 
36 | 38 | 49 | 60 | 71 | 73 | 3 | 14 | 25 
----+----+----+----+----+----+----+----+---- 
26 | 28 | 39 | 50 | 61 | 72 | 74 | 4 | 15 
----+----+----+----+----+----+----+----+---- 
16 | 27 | 29 | 40 | 51 | 62 | 64 | 75 | 5 
----+----+----+----+----+----+----+----+---- 
    6 | 17 | 19 | 30 | 41 | 52 | 63 | 65 | 76 
----+----+----+----+----+----+----+----+---- 
77 | 7 | 18 | 20 | 31 | 42 | 53 | 55 | 66 
----+----+----+----+----+----+----+----+---- 
67 | 78 | 8 | 10 | 21 | 32 | 43 | 54 | 56 
----+----+----+----+----+----+----+----+---- 
57 | 68 | 79 | 9 | 11 | 22 | 33 | 44 | 46 
----+----+----+----+----+----+----+----+---- 
47 | 58 | 69 | 80 | 1 | 12 | 23 | 34 | 45 

Die Array-Figuren aus der Größe des Platzes, wenn es die erste Zeile der Datei liest . Das ist sehr dynamisch. Es funktioniert, solange die Eingabedatei ein perfektes Quadrat ist. Ich habe keine weitere Fehlerbehandlung.

Hier ist ein einfacher Ansatz, der sich an Ihre Richtlinien halten sollte.

import java.io.BufferedReader; 
import java.io.InputStream; 
import java.io.InputStreamReader; 

public class ReadMagicSquare { 
    public static int[][] create2DIntMatrixFromFile(String filename) throws Exception { 
     int[][] matrix = null; 

     // If included in an Eclipse project. 
     InputStream stream = ClassLoader.getSystemResourceAsStream(filename); 
     BufferedReader buffer = new BufferedReader(new InputStreamReader(stream)); 

     // If in the same directory - Probably in your case... 
     // Just comment out the 2 lines above this and uncomment the line 
     // that follows. 
     //BufferedReader buffer = new BufferedReader(new FileReader(filename)); 

     String line; 
     int row = 0; 
     int size = 0; 

     while ((line = buffer.readLine()) != null) { 
      String[] vals = line.trim().split("\\s+"); 

      // Lazy instantiation. 
      if (matrix == null) { 
       size = vals.length; 
       matrix = new int[size][size]; 
      } 

      for (int col = 0; col < size; col++) { 
       matrix[row][col] = Integer.parseInt(vals[col]); 
      } 

      row++; 
     } 

     return matrix; 
    } 

    public static void printMatrix(int[][] matrix) { 
     String str = ""; 
     int size = matrix.length; 

     if (matrix != null) { 
      for (int row = 0; row < size; row++) { 
       str += " "; 
       for (int col = 0; col < size; col++) { 
        str += String.format("%2d", matrix[row][col]); 
        if (col < size - 1) { 
         str += " | "; 
        } 
       } 
       if (row < size - 1) { 
        str += "\n"; 
        for (int col = 0; col < size; col++) { 
         for (int i = 0; i < 4; i++) { 
          str += "-"; 
         } 
         if (col < size - 1) { 
          str += "+"; 
         } 
        } 
        str += "\n"; 
       } else { 
        str += "\n"; 
       } 
      } 
     } 

     System.out.println(str); 
    } 

    public static void main(String[] args) { 
     int[][] matrix = null; 

     try { 
      matrix = create2DIntMatrixFromFile("square.txt"); 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 

     printMatrix(matrix); 
    } 
} 

Dieser Ansatz ist mehr verfeinert und optimiert.

import java.io.BufferedReader; 
import java.io.IOException; 
import java.io.InputStream; 
import java.io.InputStreamReader; 

public class ReadMagicSquare { 

    private int[][] matrix; 
    private int size = -1; 
    private int log10 = 0; 
    private String numberFormat; 

    public ReadMagicSquare(String filename) { 
     try { 
      readFile(filename); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 

    public void readFile(String filename) throws IOException { 
     // If included in an Eclipse project. 
     InputStream stream = ClassLoader.getSystemResourceAsStream(filename); 
     BufferedReader buffer = new BufferedReader(new InputStreamReader(stream)); 

     // If in the same directory - Probably in your case... 
     // Just comment out the 2 lines above this and uncomment the line 
     // that follows. 
     //BufferedReader buffer = new BufferedReader(new FileReader(filename)); 

     String line; 
     int row = 0; 

     while ((line = buffer.readLine()) != null) { 
      String[] vals = line.trim().split("\\s+"); 

      // Lazy instantiation. 
      if (matrix == null) { 
       size = vals.length; 
       matrix = new int[size][size]; 
       log10 = (int) Math.floor(Math.log10(size * size)) + 1; 
       numberFormat = String.format("%%%dd", log10); 
      } 

      for (int col = 0; col < size; col++) { 
       matrix[row][col] = Integer.parseInt(vals[col]); 
      } 

      row++; 
     } 
    } 

    @Override 
    public String toString() { 
     StringBuffer buff = new StringBuffer(); 

     if (matrix != null) { 
      for (int row = 0; row < size; row++) { 
       buff.append(" "); 
       for (int col = 0; col < size; col++) { 
        buff.append(String.format(numberFormat, matrix[row][col])); 
        if (col < size - 1) { 
         buff.append(" | "); 
        } 
       } 
       if (row < size - 1) { 
        buff.append("\n"); 
        for (int col = 0; col < size; col++) { 
         for (int i = 0; i <= log10 + 1; i++) { 
          buff.append("-"); 
         } 
         if (col < size - 1) { 
          buff.append("+"); 
         } 
        } 
        buff.append("\n"); 
       } else { 
        buff.append("\n"); 
       } 
      } 
     } 

     return buff.toString(); 
    } 

    public static void main(String[] args) { 
     ReadMagicSquare square = new ReadMagicSquare("square.txt"); 
     System.out.println(square.toString()); 
    } 
} 
+0

Ich schätze, dass dies wirklich die einzige Antwort ist, die das Problem löst, aber wir wurden nie in Puffer eingeführt und müssen noch Klassen mit Hilfsmethoden schreiben. Ich bin mir bewusst, dass dies die richtige Antwort liefern wird, aber ich denke, dass ich es auf eine rudimentärere Weise erreichen muss. – BimmerM3

+0

Was ist, wenn die Eingabe mehr Spalten (9) als Zeilen (1) hat? Sie würden die Matrix mit 1 Zeile und 1 Spalte initialisieren und schließlich mit der ArrayindexExtroverbundenen Ausnahme enden. –

+0

Hast du gelesen, was ich gesagt habe? "Das ist sehr dynamisch. *** Es funktioniert, solange die Eingabedatei ein perfektes Quadrat ist. *** Ich habe keine weitere Fehlerbehandlung." –

0

Mit Java 8 und es ist Streams:

static public int[][] create2DIntMatrixFromFile(Path path) throws IOException { 
    return Files.lines(path) 
     .map((l)->l.trim().split("\\s+")) 
     .map((sa)->Stream.of(sa).mapToInt(Integer::parseInt).toArray()) 
     .toArray(int[][]::new); 
    } 

Dies ist nur für den 'Lesen' Teil der Frage.