Problem
This program creates an integer array with a random size of 5-50 elements (inclusive). It then fills the array with random numbers between 0 – 100 (inclusive). The interesting part comes when I then have to print the array as a table limited at 5 columns wide. Also, the array must be centered on an output screen 80 characters wide.
My main concern and question is: how do I efficiently move through an array of an unknown size?
My solution is basically to count through each element, keeping track of how many are left and printing new whole rows while there are still any elements left, and checking each element to see if it should be empty or not.
But would division be possible? My main issue with division is if I were to do rows = NUMBERS / 5 + 1
, I would always end up with 1 extra empty row whenever NUMBERS
was divisible by 5.
import java.util.Random;
public class NumberGenerator
{
private static final int MIN_INTS = 5, MAX_INTS = 50; //Range of numbers to be generated
private static final int MIN_RANGE = 0, MAX_RANGE = 100; //Legal range of generated numbers
private static final int TABLE_COLUMNS = 5; //Number of columns in output table
private static Random generator = new Random(); //Random number generator
/**********************************************************
* BEGIN Main
* Calc number of integers to generate between 5 and 50 (inclusive)
* Init array the size of the generated number
* Init current number to 0
* FOR (each number in array) DO
* Assign random number between 0 and 100 to current cell
* END FOR
* Display title
* Display top of table
* WHILE (there are numbers not displayed) DO
* Display left edge of table
* FOR (each cell in table row) DO
* IF (numbers are left in the array)
* Display formatted cell value and cell's right edge
* ELSE
* Display empty cell and cell's right edge
* END IF
* Increment current number
* END FOR
* Display EOL
* END WHILE
* Display bottom of table
* END Main
**********************************************************/
public static void main (String [] args)
{
final int NUMBERS; //Number of integers to generate
final String BORDER = "+-----------------------------+"; //Top and bottom border
final String PAD_FORMAT_STR; //Printf format for left pad
int[] numberList; //Array of generated integers
int tablePadding = 24; //Number of columns in front of output table
int currentNumber; //Current number drawn in table
NUMBERS = generator.nextInt(MAX_INTS - MIN_INTS + 1) + MIN_INTS;
PAD_FORMAT_STR = "%" + tablePadding + "s%s";
numberList = new int[NUMBERS];
for (int i = 0; i < NUMBERS; i++)
{
numberList[i] = generator.nextInt(MAX_RANGE + 1); //+1 to include max bound
}
currentNumber = 0;
System.out.printf("%32s%s", "", "Number Generatornn");
System.out.printf(PAD_FORMAT_STR + "n", "", BORDER);
while (currentNumber < NUMBERS)
{
System.out.printf(PAD_FORMAT_STR, "", "|");
for (int i = 0; i < TABLE_COLUMNS; i++)
{
if (NUMBERS > currentNumber)
{
System.out.printf(" %3d |", numberList[currentNumber]);
}
else
{
System.out.print(" |");
}
currentNumber++;
}
System.out.println();
}
System.out.printf(PAD_FORMAT_STR + "n", "", BORDER);
}
}
An example of output is:
Number Generator +-----------------------------+ | 40 | 3 | 79 | 2 | 37 | | 80 | 2 | 82 | 26 | 89 | | 1 | 88 | 21 | 5 | 45 | | 100 | 5 | 100 | 78 | 94 | | 56 | 31 | | | | +-----------------------------+
Solution
Formatting
-
Generally in Java you follow the “Egyptian” bracing style, which opens braces on the line that introduces the block instead of on a separate line:
public class NumberGenerator { // ... public static void main (String[] args) { //... } }
-
Every declaration should have their own line to facilitate easier reasoning about what variables are declared instead of possibly missing some when skimming over a line initializing two or more
-
SHOUTY_SNAKE_CASE
is reserved for constants or static fields. NeitherNUMBERS
norBORDER
norPAD_FORMAT_STRING
are declared as such.
Commenting
You’re significantly overcommenting. Instead of comments at the end of a line you should be using descriptive variable names. You’re already doing a good job on that though, so I advise you to just remove most of these comments.
This includes that humungous block comment above main that serves no practical purpose whatsoever. Instead of reading that comment, one can just read the code. That’s ad 1) faster and ad 2) guaranteed to describe the actual behaviour of the code.
Unused variables and early declarations.
MIN_RANGE
is not used. remove it.- You seem to be fond of declaring variables up front and then filling them with stuff later on. That makes it hard to follow your initialization logically, since it puts stress on the brain. You need to have each variable in the back of your head and juggle all of them around instead of inspecting each separately and ignoring those that aren’t interesting.
Table printing.
It’s probably easier to print your table with a nested for loop, since a for-loop allows you to increment two variables in the loop statement.
This makes keeping track of the current row significantly easier for your code.
Final result:
import java.util.Random;
public class NumberGenerator {
private static final int MIN_INTS = 5;
private static final int MAX_INTS = 50;
private static final int MAX_RANGE = 100;
private static final String BORDER = "+-----------------------------+";
private static final int TABLE_COLUMNS = 5;
private static final Random GENERATOR = new Random();
public static void main(String[] args) {
final String PAD_FORMAT_STR = "%" + 24 + "s%s";
int[] numberList = new int[GENERATOR.nextInt(MAX_INTS - MIN_INTS + 1) + MIN_INTS];
for (int i = 0; i < numberList.length; i++) {
numberList[i] = GENERATOR.nextInt(MAX_RANGE + 1); //+1 to include max bound
}
System.out.printf("%32s%s", "", "Number Generatornn");
System.out.printf(PAD_FORMAT_STR + "n", "", BORDER);
for (int i = 0; i < numberList.length; i++) {
System.out.printf(PAD_FORMAT_STR, "", "|");
for (int j = 0; j < TABLE_COLUMNS; i++, j++) {
if (i >= numberList.length) {
System.out.print(" |");
} else {
System.out.printf(" %3d |", numberList[i]);
}
}
System.out.println();
}
System.out.printf(PAD_FORMAT_STR + "n", "", BORDER);
}
}