Formatting and improving current code
I'll show how to solve your problem, but first I would like to point out a few things in your code that could be improved by some formatting, or that perhaps are unnecessary.
Just to help you improve your coding skills, readability is very important! :)
And don't forget, consistency is key! If you like one style better than the more common style, or the preferred style, that's fine as long as you use it throughout your coding. Don't switch between two styles.
If you don't care to read these comments, you can find the solution at the bottom of my answer. Just note that your original code will be different in my solution because I have formatted it to be most readable for me.
Spacing in variable declarations
Original code
int[][] matricea = new int [30][40];
int x=0, y=0;
Spacing modified
int[][] matricea = new int[30][40];
int x = 0, y = 0;
Notice the space removed between int
and [30][40]
, and the space added between the variables and the initialization, i.e. - x=0
=> x = 0
.
Initializing an int array to contain all 0's
Original code
int[] numbers = new int[72]; //each keno draw has 70 numbers
for (int i = 0; i < 71; i++ ){
numbers[i] = 0;
}
Same as
int[] numbers = new int[72]; //each keno draw has 70 numbers
You don't have to set each value to 0
, Java will do that for you. In fact, Java has default values, or null values, for all types. Thanks to Debosmit Ray!
I won't go into the exceptions to this case, or when or why or how, you can read about that in this post, and pay close attention to Aniket Thakur's answer.
But why do you have an array of size 72, if there are only 70 possibilities?
Choosing variable names
Original code
int k=0; // k counts the lines
Same as
int numLines = 0;
You should always make your variables names something meaningful to their purpose. If you ever have to put a comment like k counts the lines
to describe a variable's purpose, consider if a better name would work instead.
Functionalizing code
Original code
while ( (draw = reader.readLine()) != null ) {
String[] pieces = draw.split(" +");
k++;
for (String str : pieces) {
int str_int = Integer.parseInt(str);
matricea[x][y] = str_int;
System.out.print(matricea [x][y] + " ");
y = y + 1;
}
x = x + 1;
System.out.println(" ");
}
Same as
while ( (draw = reader.readLine()) != null ) {
processLine(draw);
}
Of course, you'll have to make the method processLine(String line)
, but that won't be hard. It's just taking what you have and moving it to a separate method.
The original code's while loop is very busy and messy, but with the latter option makes the purpose clear, and the code clean.
Of course each situation is different, and you might find that only removing part of the code into a method would be a better solution. Just play around and see what makes sense.
Error!
Original code
for (int j = 1; j <= 20; j++) {
int drawnNumber = Integer.parseInt(pieces[j]);
numbers[drawnNumber]++;
}
This code should not work, since pieces
is declared in the while loop above it, and is local to that above loop. This for loop is outside the scope of where pieces
exists.
I'll tell you how to fix it, but I'm not sure what the code is supposed to be doing. Just let me know what its purpose is, and I'll provide you with a solution.
After formatting!
This is what the code may look like after applying my above comments. I have added comments to parts that I have changed.
public static void main(String args[]) {
try {
doKenoStuff();
} catch(IOException e) {
System.out.println("There was a problem opening and processing the file.");
}
}
public static void doKenoStuff() throws IOException {
BufferedReader reader = new BufferedReader(
new FileReader("C:\\keno.txt")
);
int[][] matricea = new int[30][40];
int[] numbers = new int[72]; //each keno draw has 70 numbers
// We can clean up our loop condition by removing
// the assignment (draw = reader.readLine) from it.
// Just make sure draw doesn't begin as null.
String draw = "";
int row;
for(row = 0; draw != null; row++) {
draw = reader.readLine();
// We read a line from the file, then send it
// to extractLineData which will collect the info
// from each column, and update matricea and numbers
extractLineData(draw, row, matricea, numbers);
}
System.out.println("Number of lines: " + row);
System.out.println("Each number's drawing stats:");
for (int i = 0; i < 71; i++) {
System.out.println(i + ": " + numbers[i]);
}
reader.close();
}
public static void extractLineData(String line, int row, int[][] matrix, int[] numbers) {
String linePieces = line.split(" +");
for(int column = 0; column < linePieces.length; column++) {
int number = Integer.parseInt(linePieces[column]);
matrix[row][column] = number;
numbers[number]++;
}
}
Solution
Note: I am not perfect, and my code is not either. I'm not trying to say that what I have suggested is in any way the only way to do this. It could definitely be improved, but it is a start. You should take my solution and see how you can improve it yourself.
What can you find that you could code in a cleaner, or faster, or better way?
So, how do we fix the problem?
We have a method that reads from the start of a file, to the end of it, and it logs the data it finds inside matricea
.
A quick and easy solution is to simply make that method take in two parameters, a starting line number, and an ending line number.
public static void doKenoStuff(int start, int end) throws IOException {
Then we simply make a loop to skip over the starting lines! It's that easy!!!
for(int i = 0; i < start - 1; i++) {
reader.readLine();
}
Don't forget that we may not need the big 30 row matricea
to be 30 rows anymore. We can shrink that down to end - start + 1
. That way, if a user wants to read from line 45 to line 45, we only need 45 - 45 + 1 = 1
row in matricea
.
int[][] matricea = new int[end - start + 1][40];
And the very last thing we need to add is a condition in our line reading loop, that prevents us from going past the ending line.
for(row = 0; draw != null, row <= end; row++) {
And there you have it. Simple as that!
Complete solution
public static void main(String args[]) {
int start = 7, end = 18;
try {
doKenoStuff(start, end);
} catch(IOException e) {
System.out.println("There was a problem opening and processing the file.");
}
}
public static void doKenoStuff(int start, int end) throws IOException {
BufferedReader reader = new BufferedReader(
new FileReader("C:\\keno.txt")
);
int[][] matricea = new int[end - start + 1][40];
int[] numbers = new int[72]; //each keno draw has 70 numbers
for(int i = 0; i < start - 1; i++) {
reader.readLine();
}
String draw = "";
int row;
for(row = 0; draw != null, row <= end; row++) {
draw = reader.readLine();
extractLineData(draw, row, matricea, numbers);
}
System.out.println("Number of lines: " + row);
System.out.println("Each number's drawing stats:");
for (int i = 0; i < 71; i++) {
System.out.println(i + ": " + numbers[i]);
}
reader.close();
}
public static void extractLineData(String line, int row, int[][] matrix, int[] numbers) {
String linePieces = line.split(" +");
for(int column = 0; column < linePieces.length; column++) {
try {
int number = Integer.parseInt(linePieces[column]);
matrix[row][column] = number;
numbers[number]++;
} catch (NumberFormatException) {
// You don't have to do anything in this block, but
// you can print out what input gave the exception if you want.
System.out.println("Bad input: \"" + linePieces[column] + "\"");
}
}
}