patternjavaMinor
A way to handle integer input
Viewed 0 times
inputwayintegerhandle
Problem
I'm working on simple code that is to read input where:
Possible input:
Possible output (just some multiplication example):
Questions:
-
What could be done to make this code more universal? For example, there is a variable
-
What validation should be implemented (if someone gives bad input, maybe it could be done in X ways (the handling))?
```
import java.io.IOException;
import java.util.Scanner;
import java.util.Arrays;
public class Main {
public static void main(String[] args) throws IOException {
/ Reading number of tests (NO VALIDATION) /
/ nextInt() doesnt read the last newline character of input /
Scanner read = new Scanner(System.in);
int numberOfTests = read.nextInt();
/ Consuming newline character/
read.nextLine();
String line[] = new String[numberOfTests];
/ Reading line excluding line separator at the end (NO VALIDATION) /
for (int i = 0; i < numberOfTests; i++)
line[i] = read.nextLine();
/ Printing array of String(lines) /
System.out.print(Arrays.toString(line));
/ Creating the array of ints (NO VALIDATION) /
int lineLength = 3;
int num[][] = new int[numberOfTests][lineLength];
/ Extracting integers from line /
for (int i = 0; i < numberOfTests; i++) {
int k = 0;
for (int j = 0; j < lineLength; j++) {
if (Character.isSpaceChar((line[i].charAt(j))) != true) {
num[i][k++] = Character.getNumericValue(line[i].charAt(j));
}
}
}
/ Printing array of integers to test /
int numToTests = 2;
for (int i = 0; i < numberO
- The first line is a number of cases to consider.
- The next lines are integers separated by a space that will be tested lately.
Possible input:
2
3 4
4 5Possible output (just some multiplication example):
12
20Questions:
- I would like to know if there are 'better' ways to handle this kind of input.
-
What could be done to make this code more universal? For example, there is a variable
int lineLength=3 and I have to modify It for other similar input (where lineLength is bigger):2
3 4 5
4 5 6-
What validation should be implemented (if someone gives bad input, maybe it could be done in X ways (the handling))?
- Do I break any good-programming rules? (I intended to write this only in class
Main)
```
import java.io.IOException;
import java.util.Scanner;
import java.util.Arrays;
public class Main {
public static void main(String[] args) throws IOException {
/ Reading number of tests (NO VALIDATION) /
/ nextInt() doesnt read the last newline character of input /
Scanner read = new Scanner(System.in);
int numberOfTests = read.nextInt();
/ Consuming newline character/
read.nextLine();
String line[] = new String[numberOfTests];
/ Reading line excluding line separator at the end (NO VALIDATION) /
for (int i = 0; i < numberOfTests; i++)
line[i] = read.nextLine();
/ Printing array of String(lines) /
System.out.print(Arrays.toString(line));
/ Creating the array of ints (NO VALIDATION) /
int lineLength = 3;
int num[][] = new int[numberOfTests][lineLength];
/ Extracting integers from line /
for (int i = 0; i < numberOfTests; i++) {
int k = 0;
for (int j = 0; j < lineLength; j++) {
if (Character.isSpaceChar((line[i].charAt(j))) != true) {
num[i][k++] = Character.getNumericValue(line[i].charAt(j));
}
}
}
/ Printing array of integers to test /
int numToTests = 2;
for (int i = 0; i < numberO
Solution
Behaviour
I assume that you are writing this code in preparation for some programming challenges involving an online judge. In that case, it's unconventional that you are producing a matrix of digits. That is, each element is a single digit, no negative numbers, and no numbers larger than 9.
Usually, each line represents an independent test case. You should be able to compute a result for each line of input without waiting for all of the input to be read first.
Abstraction
If you want to focus on input-handling as a problem to be solved, then the "proper" solution would be to provide a convenient way for your computation code to fetch its input. The goal would be to enable simple code like:
Here is a class that could achieve that:
In total, this results in a lot more code than your in your original question. However, once the calculations start getting more complicated, you may find that getting the input routines out of the way is worthwhile.
I assume that you are writing this code in preparation for some programming challenges involving an online judge. In that case, it's unconventional that you are producing a matrix of digits. That is, each element is a single digit, no negative numbers, and no numbers larger than 9.
Usually, each line represents an independent test case. You should be able to compute a result for each line of input without waiting for all of the input to be read first.
Abstraction
If you want to focus on input-handling as a problem to be solved, then the "proper" solution would be to provide a convenient way for your computation code to fetch its input. The goal would be to enable simple code like:
public class Multiply {
public static int product(int[] numbers) {
int product = 1;
for (int n : numbers) {
product *= n;
}
return product;
}
public static void main(String[] args) {
IntTestCaseInput input = new IntTestCaseInput(System.in);
for (int[] multProblem : input) {
System.out.println(product(multProblem));
}
}
}Here is a class that could achieve that:
import java.io.*;
import java.util.*;
public class IntTestCaseInput implements Iterable {
private class Iter implements Iterator {
public int cases = -1;
@Override
public void remove() {
throw new UnsupportedOperationException();
}
@Override
public boolean hasNext() {
try {
maybeInitialize();
return cases > 0;
} catch (IOException e) {
return false;
}
}
@Override
public int[] next() {
try {
maybeInitialize();
if (cases == 0) {
throw new NoSuchElementException();
}
cases--;
String[] strings = IntTestCaseInput.this.in.readLine().split("\\s+");
int[] numbers = new int[strings.length];
for (int i = 0; i iterator() {
return new Iter();
}
}In total, this results in a lot more code than your in your original question. However, once the calculations start getting more complicated, you may find that getting the input routines out of the way is worthwhile.
Code Snippets
public class Multiply {
public static int product(int[] numbers) {
int product = 1;
for (int n : numbers) {
product *= n;
}
return product;
}
public static void main(String[] args) {
IntTestCaseInput input = new IntTestCaseInput(System.in);
for (int[] multProblem : input) {
System.out.println(product(multProblem));
}
}
}import java.io.*;
import java.util.*;
public class IntTestCaseInput implements Iterable<int[]> {
private class Iter implements Iterator<int[]> {
public int cases = -1;
@Override
public void remove() {
throw new UnsupportedOperationException();
}
@Override
public boolean hasNext() {
try {
maybeInitialize();
return cases > 0;
} catch (IOException e) {
return false;
}
}
@Override
public int[] next() {
try {
maybeInitialize();
if (cases == 0) {
throw new NoSuchElementException();
}
cases--;
String[] strings = IntTestCaseInput.this.in.readLine().split("\\s+");
int[] numbers = new int[strings.length];
for (int i = 0; i < strings.length; i++) {
numbers[i] = Integer.parseInt(strings[i]);
}
return numbers;
} catch (IOException e) {
throw new NoSuchElementException(e.getMessage());
}
}
/**
* On first use, find out how many test cases to expect.
*/
private void maybeInitialize() throws IOException {
if (cases < 0) {
cases = Integer.parseInt(IntTestCaseInput.this.in.readLine());
}
}
}
private BufferedReader in;
public IntTestCaseInput(InputStream in) {
this(new InputStreamReader(in));
}
public IntTestCaseInput(Reader in) {
this.in = (in instanceof BufferedReader) ?
(BufferedReader)in : new BufferedReader(in);
}
@Override
public Iterator<int[]> iterator() {
return new Iter();
}
}Context
StackExchange Code Review Q#75855, answer score: 8
Revisions (0)
No revisions yet.