简体   繁体   中英

Java 2D Array; Variable Row & Column Length from File Input

For this intro-level assignment, I have to set up a 2D multidimensional array from a file and from a double[][] a and apply several methods to them. For now, I'm mostly concerned with simply initializing the arrays. I'm trying to figure out a way to take a test file, read the first int as the number of rows, the first integer of each line as the number of columns per row, and each double as a member of the array.

 public class MDArray
    {
        static int rowCount;
        static int columnCount;
        private static double[][] mdarray = new double[rowCount][columnCount];

    public MDArray(double[][] a)
    {
        mdarray = a;
    }

    public MDArray(String file)
    {
        Scanner input = null;
        try
        {
            input = new Scanner(new FileInputStream("ragged.txt"));
        }
        catch (FileNotFoundException e)
        {
            System.out.println("File Not Found.");
            System.exit(0);
        }
        while(input.hasNextDouble())
        {
            rowCount = input.nextInt();
            for(int i = 0; i < rowCount; i++)
            {
                columnCount = input.nextInt();
                for(int j = 0; j < columnCount; j++)
                {
                    double value = input.nextDouble();
                    mdarray[i][j] = value;
                }
            }
        }
    }

    public static boolean isRagged()
    {
        for(int i = 0; i < mdarray.length; i++)
        {
            int rowLength1 = mdarray.length;
            for(int j = i + 1; j < mdarray.length; j++)
            {
                int rowLength2 = mdarray.length;
                if(rowLength1 != rowLength2)
                {
                    return true;
                }
            }
        }
        return false;
    }

    public static int getNumberOfRows()
    {
        int numRows = 0;
        for(int i = 0; i < mdarray.length; i++)
        {
            numRows++;
        }
        return numRows;
    }

    public static int getNumberOfCols()
    {
        int numCols = 0;
        for(int i = 0, j = i + 1; i < mdarray.length; i++)
        {
            for(int k = 0; k < mdarray[i].length; k++)
            {
                if(mdarray[i].length > mdarray[j].length)
                {
                    numCols++;
                }
            }
        }
        return numCols;
    }

    public static double getValAt(int i, int j)
    {
        if(i > mdarray.length || j > mdarray[i].length)
        {
            double invalid = Double.NaN;
            return invalid;
        }
        double valAt = mdarray[i][j];
        return valAt;
    }

    public static void sort(boolean byColumn)
    {
        if(isRagged() == true)
        {
            System.out.println("Ragged arrays cannot be sorted by column.");
        }
        else{
            for(int i = 0; i < mdarray.length; i++)
            {
                for(int j = 0; j < mdarray[i].length; j++)
                {
                    for(int k = j + 1; k < mdarray[i].length; k++)
                    {
                        if(mdarray[i][j] < mdarray[i][k])
                        {
                            double temp = mdarray[i][j];
                            mdarray[i][k] = mdarray[i][j];
                            mdarray[i][j] = temp;
                        }
                    }
                }
            }
        }
    }

    public static int hamming(boolean byColumn)
    {
        int hamVal = 0;
        if(isRagged() == true)
        {
            System.out.println("Ragged arrays cannot be sorted by column.");
        }
        else{
            for(int i = 0; i < mdarray.length; i++)
            {
                for(int j = 0; j < mdarray[i].length; j++)
                {
                    for(int k = j + 1; k < mdarray[i].length; k++)
                    {
                        if(mdarray[i][j] < mdarray[i][k])
                        {
                            double temp = mdarray[i][j];
                            mdarray[i][k] = mdarray[i][j];
                            mdarray[i][j] = temp;
                            hamVal++;
                        }
                    }
                }
            }
        }
        return hamVal;
    }

    public static double[] max()
    {
        double[] maxVal = new double[mdarray.length];
        for(int i = 0, j = i + 1; i < maxVal.length; i++)
            {
                for(int k = 0; k < mdarray[i].length; k++)
                {
                    if(mdarray[i][k] > mdarray[j][k])
                    {
                        maxVal = mdarray[i];
                    }
                }
            }
        return maxVal;
    }

    public String toString()
    {
        String arrayString = "";
        for(int i = 0; i < mdarray.length; i++)
        {
            for(int j = 0; j < mdarray[i].length; j++)
            {
                arrayString += ", " + mdarray[i][j];
            }
            arrayString = arrayString + "/n";
        }
        return arrayString;
    }
}

This was the file I was testing the MDArray(String file) with:

3

2 4.1 8.9

5 9.5 2.0 7.3 2.1 8.9

3 1.3 5.2 3.4

I think the problem is that the rowCount and columnCount integers are not initialized, but I'm not sure how to initialize them to a variable length with basic array skills. This is also affecting the other constructor as well. Being an intro-level course, I am not supposed to use more advanced techniques such as ArrayList . In addition, I can't verify if the methods are correct, since I don't have an array to test them with.

EDIT: While I did implement many of the suggestions in the answers, such as changing everything to non-static and other changes, I'm still getting a NullPointerException for the line mdarray[i][j] = input.nextDouble();. I assume it has to do with the private double[][] mdarray , which is required in the assignment specifications. Now I'm trying to find a way to initialize it such that it can be overridden in the later methods.

You have to initialize the array in your constructor, since that's when you know the dimensions :

public MDArray(String file)
{
    Scanner input = null;
    try {
        input = new Scanner(new FileInputStream("ragged.txt"));
    }
    catch (FileNotFoundException e) {
        System.out.println("File Not Found.");
        System.exit(0);
    }
    rowCount = input.nextInt(); 
    mdarray = new double[rowCount][]; // init the array
    for(int i = 0; i < rowCount; i++) {
        columnCount = input.nextInt();
        mdarray[i] = new double[columnCount]; // init the current row
        for(int j = 0; j < columnCount; j++) {
            mdarray[i][j] = input.nextDouble();
        }
    }

}

You could initialize your arrays by putting the amount of rows and columns on the first 2 lines of your multidimensional array, if i had 10 rows and 12 columns i could do something like this:

    public void arrayStuff() {
    File fileToRead = new File("YOUR LINK HERE");
    String[][] data;


    try (BufferedReader reader = new BufferedReader(new FileReader(fileToRead))) {

        String line;
        data = new String[Integer.parseInt(reader.readLine())][Integer.parseInt(reader.readLine())];
        while((line = reader.readLine()) != null) {
            // read the rest here..
        }


    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

I am using an AutoCloseable (which is why the try is between these ()'s, but this is so that i don't have to close it afterwards.

Basically, first i read the amount of rows there are and then the amount of columns there are, so if i had this file:

10
12
a b c d e f g h i j
a b c d e f g h i j
a b c d e f g h i j
a b c d e f g h i j
a b c d e f g h i j
a b c d e f g h i j
a b c d e f g h i j
a b c d e f g h i j
a b c d e f g h i j
a b c d e f g h i j
a b c d e f g h i j
a b c d e f g h i j

It'd be able to read all of this, because the amount of rows and columns were defined in the file.

You don't use the fields rowCount and columnCount: you can remove them

The mdarray field should be non-static, so should be the methods that use them (if it was a utility class, you wouldn't have any constructor)

The arrays can be created while reading the file:

Scanner input = null;
try
{
    input = new Scanner(new FileInputStream("ragged.txt"));
}
catch (FileNotFoundException e)
{
    System.out.println("File Not Found.");
    System.exit(0);
}
int rowCount = input.nextInt();
mdarray = new double[rowCount][];
for(int i = 0; i < rowCount; i++)
{
    int columnCount = input.nextInt();
    mdarray[i] = new double[columnCount];
    for(int j = 0; j < columnCount; j++)
    {
        double value = input.nextDouble();
        mdarray[i][j] = value;
    }
}

methods getNumberOfRows() and getNumberOfCols() count be much simpler:

public int getNumberOfRows()
{
    return mdarray.length;
}

public int getNumberOfCols() {
    int result = 0;
    for (double[] col: mdarray) {
        if (col.length > result) {
            result = col.length;
        }
    }
    return result;
}

In getValueAt(), the test is wrong; it should be:

if(i >= mdarray.length || j >= mdarray[i].length)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM