Topics › Basics › Things to Know in C++/Java/Python or any language
Input Output
Java source ↗ Edit this article ↗
Jump to code:
What this covers
Every program you will write for a judge, a coding round or a take-home test has the same outer shape: read some input, compute, print an answer. The computing part is what the rest of this course is about. This article makes sure the other two parts never cost you a wrong answer or a time limit: how Java reads tokens and lines, the one Scanner trap that catches everyone once, how to read the standard “n, then n numbers” format and multi-test-case input, and how to produce output that is both correctly formatted and fast.
Every parser below takes a String as its input so that the Java file can test itself without a keyboard. new Scanner(someString) and new Scanner(System.in) expose exactly the same methods, so swapping the argument is the only change needed in a real program.
Reading tokens with Scanner
Scanner splits its input into tokens separated by whitespace. Spaces, tabs and line breaks are all treated the same, which is why you almost never need to care how the input is spread over lines. nextInt() reads the next token and converts it to an int; hasNextInt() tells you whether such a token exists without consuming it.
static long sumOfTokens(String input) {
Scanner sc = new Scanner(input);
long sum = 0;
while (sc.hasNextInt()) sum += sc.nextInt();
return sum;
}
Two details are deliberate. The sum is a long: two values near 2 × 10^9 fit in int individually but their sum does not. And the loop stops the moment a token is not an integer, so a stray word at the end does not crash the program. Other methods follow the same naming: nextLong(), nextDouble(), next() (one whitespace-free word) and nextLine() (everything up to the end of the current line).
The judge’s favourite format: n, then n numbers
Most problems describe their input as “the first line contains n, the second line contains n integers”. Because Scanner ignores line structure, the code is simply: read n, allocate an array of that size, fill it.
static int[] readArray(String input) {
Scanner sc = new Scanner(input);
int n = sc.nextInt();
int[] a = new int[n];
for (int i = 0; i < n; i++) a[i] = sc.nextInt();
return a;
}
It does not matter whether the numbers come on one line or ten. n = 0 is handled for free: new int[0] is a valid empty array and the loop body never runs.
Parsing a line yourself
Sometimes you receive one whole line as a String, for instance because you read it with nextLine() or because the problem hands it to you. Then split does the tokenising: the regular expression "\\s+" means “one or more whitespace characters”, so runs of spaces collapse into a single separator.
static int[] readArraySplit(String line) {
String t = line.trim();
if (t.isEmpty()) return new int[0];
String[] parts = t.split("\\s+");
int[] a = new int[parts.length];
for (int i = 0; i < parts.length; i++) a[i] = Integer.parseInt(parts[i]);
return a;
}
The trim() matters because leading whitespace would otherwise produce an empty first piece, and the isEmpty() guard matters because "".split("\\s+") returns an array containing one empty string, which Integer.parseInt would reject with a NumberFormatException. Both parsers agree on every valid input, which the tests confirm by feeding the same numbers to each.
The nextInt / nextLine trap
nextInt() reads the digits of the number and stops right after them. The line break that follows the number is still sitting in the input. If your next call is nextLine(), it returns the empty remainder of that first line rather than the line you wanted. The fix is to call nextLine() once to throw away the leftover, and then again to read the real line.
static String readAgeThenName(String input) {
Scanner sc = new Scanner(input);
int age = sc.nextInt();
sc.nextLine(); // discard the rest of the first line
String name = sc.nextLine(); // the whole second line, spaces included
return name + " is " + age;
}
Notice that nextLine() keeps interior and leading spaces intact (" Al" stays " Al"), while next() would have returned only Alice out of Alice Smith. Use nextLine() whenever the text may contain spaces; use next() when the problem promises a single word.
Many test cases in one input
Contest input often begins with a count t of independent test cases. The structure is a loop around your single-case code; each case reads its own n and its own numbers. Collect the answers and print them all at the end, or print as you go, but never mix the two.
static long[] sumPerTestCase(String input) {
Scanner sc = new Scanner(input);
int t = sc.nextInt();
long[] answers = new long[t];
for (int tc = 0; tc < t; tc++) {
int n = sc.nextInt();
long sum = 0;
for (int i = 0; i < n; i++) sum += sc.nextInt();
answers[tc] = sum;
}
return answers;
}
A case with n = 0 contributes a sum of 0, and t = 0 yields an empty answer array; both are exercised in the tests.
Output: build first, print once
System.out.println is convenient but comparatively slow: every call is synchronized and may flush the stream. Calling it 10^5 times can take longer than the algorithm itself. The idiom is to assemble the whole output in a StringBuilder and print it with a single call.
static String joinWithSpaces(int[] a) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < a.length; i++) {
if (i > 0) sb.append(' ');
sb.append(a[i]);
}
return sb.toString();
}
The if (i > 0) guard puts a separator before every element except the first, which avoids a trailing space without a special case after the loop. For truly huge outputs, wrapping System.out in a PrintWriter with a BufferedWriter is the next step, but a single StringBuilder print is enough for every problem on these sheets.
Formatting numbers and columns
String.format (and its twin System.out.printf) uses C-style specifiers. %d is an integer, %s a string, %f a floating-point number. A number between % and the letter sets the minimum width; a minus sign left-aligns; .2 after the width fixes the number of decimals.
static String formatRow(String name, int qty, double price) {
return String.format(Locale.US, "%-6s|%4d|%8.2f", name, qty, price);
}
"%-6s" pads pen to six characters on the right, "%4d" right-aligns the quantity in four columns, and "%8.2f" prints 249.999 as ` 250.00, rounding to two decimals in eight columns. Width is a minimum, not a maximum: notebook is longer than six characters and is printed in full. The Locale.US argument is a small but real safeguard: on a machine whose default locale uses a decimal comma, ”%.2f” would print 1,50, which a judge comparing against 1.50` would reject.
Edge cases and pitfalls
- Empty input.
hasNextInt()returnsfalseimmediately, so loops guarded by it terminate;nextInt()on empty input throwsNoSuchElementException. Guard or trust the problem statement, but know which one you are doing. - Sums that overflow. Reading
intvalues is fine; adding10^5of them is not. Accumulate inlong. - The leftover line break. After
nextInt(), callnextLine()once before reading a text line. This is the single most common input bug in Java. - Trailing spaces and separators. Judges usually tolerate a trailing space, but not a missing one. The
if (i > 0)pattern is the safe default. - Locale. Pass
Locale.UStoString.formatwhen printing decimals. - Slow output. Thousands of
printlncalls can exceed the time limit on their own. Build the output in aStringBuilderand print once. - Scanner speed.
Scanneris slower than reading lines with aBufferedReaderand splitting them. For inputs of10^6numbers switch to the latter; for everything on these sheetsScanneris fine.
Related problems
- Cpp Basics explains the primitive types the parsers produce and when
intis not enough. - What are arrays, strings? covers the arrays and
Stringmethods used while parsing. - For loops is the loop form every reader above is built from.