Alternative way to get the string input from the user [duplicate] - java

This question already has answers here:
Why does input.nextint method have a \n as a leftover?
(2 answers)
What does java.lang.ArrayIndexOutOfBoundsException mean? [duplicate]
(7 answers)
Closed 2 years ago.
I have implemented the following code which takes these values as input:-
3 6
CLICK 1
CLICK 2
CLICK 3
CLICK 2
CLOSEALL
CLICK 1
But for taking string input I tried nextLine() but it is not taking input in that case.If I use next() then it treats CLICK and 1 as two different strings and so I am getting ArrayIndexOutOfBoundsException as I am splitting the string and parsing it to int. What is the alternative to handling such inputs?
import java.util.*;
public class TweetClose {
public static void main(String args[]) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int k = sc.nextInt();
int open = 0;
int a[] = new int[50];
for (int i = 1; i <= n; i++) {
a[i] = 0;
}
for (int i = 0; i < k; i++) {
String s = sc.nextLine();
if (s.equals("CLOSEALL")) {
open = 0;
for (int j = 1; j <= n; j++) {
a[j] = 0;
}
} else {
String[] st = s.split(" ");
int y = Integer.parseInt(st[1]);
if (a[y] != 1) {
a[y] = 1;
open++;
}
}
System.out.println(open);
}
sc.close();
}
}

sc.nextInt() does not scan the carriage return symbol. You need to make sure to scan that before trying to parse the next input.
e.g.:
import java.util.*;
public class TweetClose {
public static void main(String args[]) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
sc.nextLine();
int k = sc.nextInt();
sc.nextLine();
int open = 0;
int[] a = new int[50];
for (int i = 1; i <= n; i++) {
a[i] = 0;
}
for (int i = 0; i < k; i++) {
String s = sc.nextLine();
if (s.equals("CLOSEALL")) {
open = 0;
for (int j = 1; j <= n; j++) {
a[j] = 0;
}
} else {
String[] st = s.split(" ");
int y = Integer.parseInt(st[1]);
if (a[y] != 1) {
a[y] = 1;
open++;
}
}
System.out.println(open);
}
sc.close();
}
}

The problem caused by using nextLine(). You should use next() instead because you want to process the next token.
After processing all tokens, the final line-break of the current line is still in memory. nextLine() returns that line break "\n". Then you process it:
String[] st = s.split(" ");
int y = Integer.parseInt(st[1]);
The split function returns an array with only one element (the "\n"), therefore you cannot parse st[1]. There is no such element, only st[0] exists.
It will work with next() instead of nextLine() because next() skips over the line break and proceeds with the next token of the next line.
This is a very common mistake because there is no nextString() function.

Related

Problems with iterated nextLine function

I am trying to use user inputted N lines of N characters to do some operations with. But first I need to know N and another int being inputted. When I define N and the other integer K and then write 5 lines (in this case) of 5 characters each the program runs well. But when I use the represented String a (which I then would split into 2 ints, N and K, not shown here to not complicate things), an error occurs. Even if I now input 6 lines, being the 5 last of 5 characters each, the program gives an error of no line found for the multi function. I don't understand what's the problem, and if I remove the string a and just define N and K the program runs well. What's more surprising, the program runs if I use an interactive console instead of text input and write the terms one by one.
static String [][] vetor (int N) {
Scanner scan = new Scanner(System.in);
String[][] multi = new String [N][N];
for (int i = 0 ; i<N ; i++){
String forest = scan.nextLine();
String[] chars = forest.split("");
for (int k=0; k<N; k++){
multi[i][k]= chars [k];
}
}
return multi;
}
public static void main(String args[]) {
Scanner scan = new Scanner(System.in);
String a = scan.nextLine();
int N = 5;
int K = 5;
String [][] multi = vetor(N);
I've tried many things, but I can't make sense of this. I didn't find any similar questions, but feel free to redirect me to an explanation.
Edit: This is a similar program one can run (with a possible input down (K<= N)) :
import java.util.Scanner;
import java.util.Arrays;
public class Main {
static int[] numerificar() {
Scanner myObj = new Scanner(System.in);
String Input = myObj.nextLine();
String[] Inputs = Input.split(" ", 0);
int size = Inputs.length;
int [] a = new int [size];
for(int i=0; i<size; i++) {
a[i] = Integer.parseInt(Inputs[i]);}
return a;
}
static String [][] vetor (int N) {
Scanner scan = new Scanner(System.in);
String[][] multi = new String [N][N];
for (int i = 0 ; i<N ; i++){
String forest = scan.nextLine();
String[] chars = forest.split("");
for (int k=0; k<N; k++){
multi[i][k]= chars [k];
}
}
return multi;
}
public static void main(String args[]) {
Scanner scan = new Scanner(System.in);
int[] a = numerificar();
int N = a[0];
int K = a[1];
int cadeira = 0;
String [][] multi = vetor(N);
for (int i = 0 ; i<N ; i++){
if (cadeira == 1) {
break;
}
for (int k=0; k<N-K+1; k++){
if (cadeira == 1) {
break;
}else if( multi[i][k].equals(".")){
for (int j=0; j<K; j++){
if(multi[i][k+j].equals( "#")){
k+=j;
break;
} else if (j == K-1) {
cadeira = 1;
}
}
}
}
}
System.out.println(cadeira);
}
}
5 3
.#.##
#####
##...
###..
#####
The output should be 1 in this case.
The problem is you are creating more than one Scanner that reads from System.in. When data is readily available, a Scanner object can read more data than you ask from it. The first Scanner, in the numerificar() method, reads more than the first line, and those lines are not available to the second Scanner, in the vetor() method.
Solution: use just one Scanner object in the whole program.
public class Main {
static Scanner globalScanner = new Scanner(System.in);
static int[] numerificar() {
String Input = globalScanner.nextLine();
String[] Inputs = Input.split(" ", 0);

Taking a list of integers and displaying them in reverse using arrays [duplicate]

This question already has answers here:
How do I reverse an int array in Java?
(47 answers)
Closed 3 years ago.
If my input is 1 2 3 the output is also coming out as 1 2 3, how do I make these numbers to display 3 2 1?
public static void main(String[] args) {
// TODO code application logic here
Scanner s = new Scanner(System.in);
String text = s.nextLine();
String[] entries = text.split(" ");
int[] nums = new int[entries.length];
for(int i = 0; i < entries.length; i++){
nums[i] = Integer.parseInt(entries[i]);
}
for(int i = 0; i < entries.length; i++){
System.out.println(nums[i]);
}
}
}
If you want to store numbers in reverse order:
for(int i = 0; i < entries.length; i++)
{
nums[i] = Integer.parseInt(entries[entries.length-i-1]);
}
If you want to just display numbers in reverse order(they'll remain same order in list:
for(int i = entries.length-1; i >= 0; i--)
{
System.out.println(nums[i]);
}
Try below code:
public static void main(String[] args)
{
Scanner s = new Scanner(System.in);
String text = s.nextLine();
String[] entries = text.split(" ");
for(int i = entries.length-1; i >= 0; i--)
{
System.out.print(Integer.parseInt(entries[i])+ " ");
}
}
If you want Java 8 version, here is the code
Scanner s = new Scanner(System.in);
String text = s.nextLine();
String[] entries = text.split("\\s");
List<Integer> integers = Arrays.stream(entries)
.map(Integer::valueOf)
.collect(Collectors.toList());
Collections.reverse(integers);
integers.forEach(integer -> System.out.print(String.format("%d ", integer)));
\\s indicates 'white space' and I suggest you to close Scanner at the end.
You could loop through your entries array backwards. This would involve starting int i at the length of entries minus 1 (as that is your last index in your array - ie your last number). It would also require that you keep looping while i >= 0. Lastly, instead of incrementing your i variable, you need to decrement it. This way your counter i will go from the end of your loop to the start of your array (eg: if you enter "1 2 3", i will go from indexes: 2, 1, 0)
See example below:
public static void main(String[] args) {
// TODO code application logic here
Scanner s = new Scanner(System.in);
String text = s.nextLine();
String[] entries = text.split(" ");
int[] nums = new int[entries.length];
for(int i = 0; i < entries.length; i++) {
nums[i] = Integer.parseInt(entries[i]);
}
for(int i = entries.length-1; i >= 0; i--) {
System.out.println(nums[i]);
}
}

how to ranking of race time

I need to write a program that can ranking race time of 10 runners
so I created 2 arrays
ID of runners (10 runners)
race time of 10 runners (race time must be less than or equal to 20.0 sec)
and I found that my sorting algorithm can't be used correctly, I don't want to use Arrays.sort(x); because I need to sort "those race time and ID" here is my code
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String[] ID = new String[10];
double[] time = new double[10];
for (int i = 0; i < ID.length; i++) {
System.out.print("Please enter ID and times: ");
ID[i] = sc.nextLine();
time[i] = sc.nextDouble();
}
Run a = new Run(ID, time);
System.out.println("Top 3 is ");
a.Sort();
}
}
and
public class Run {
private String[] ID = new String[10];
private double[] time = new double[10];
public Run(String[] ID, double[] time) {
for (int i = 0; i < ID.length; i++) {
this.ID[i] = ID[i];
}
for (int i = 0; i < time.length; i++) {
if (time[i] <= 20.0) {
this.time[i] = time[i];
}
}
}
public void Sort() {
double tem1;
String tem2;
for (int i = 0; i < time.length; i++) {
for (int j = 0; j < time.length; j++) {
if (time[j] > time[j+1]) {
tem1 = time[j];
time[j] = time[j+1];
time[j+1] = tem1;
tem2 = ID[j];
ID[j] = ID[j+1];
ID[j+1] = tem2;
}
}
}
for (int i = 0; i < 3; i++) {
System.out.println(ID[i] + " " + time[i]);
}
}
}
so I need to know why my sorting algorithm can't be used correctly, it's pop an error on my console.
One more question, in the input stage when I input first ID and time, if I press like this
ID[0] -> Enter -> time[0]
then the input is correct but if I press
ID[0] -> Spacebar -> time[0]
then the input is wrong.
Why? And how do I fix it?
First thing I see is that you are passing an array of 10 elements in the constructor of Run; this is not necessary, you can directly pass the arrays:
In main:
Run a = new Run(ID, time);
In run:
public Run(String[] ID, double[] time) {
this.ID = ID;
this.time = time;
}
Can you post the error log?
Read here for the problem in reading the inputs: Read integers and strings from a single line of a console
The problem is that you are trying to get in an array cell that doesn't exist: array.length returns the length of the array, so in that case returns 10.
You are doing a for cycle from 0 to 10, then you are trying to get (in the if statement) inside time[11] (it was time[j+1]).
Change the for cycle to:
for (int i = 0; i < time.length - 1; i++) {
for (int j = 0; j < time.length - 1; j++) {
System.out.println(i + " "+ j);
if (time[j] > time[j+1]) {
tem1 = time[j];
time[j] = time[j+1];
time[j+1] = tem1;
tem2 = ID[j];
ID[j] = ID[j+1];
ID[j+1] = tem2;
}
}
}
#Pleasant94 answered your question regarding the index error.
To answer your question about why you need to enter a new line (press enter) after inputting the ID is because you are scanning the whole line into the ID value using nextLine(). Instead of using nextInt() like you did for time with nextDouble().
like so:
...
ID[i] = sc.nextInt();
time[i] = sc.nextDouble();
...
Check out the Java docs for the scanner class here: https://docs.oracle.com/javase/7/docs/api/java/util/Scanner.html
And because you are now scanning in a int you'll have to update all your ID variables to int. Combining it with Pleasant94's answer you should be able to do just do this:
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int[] ID = new int[10];
double[] time = new double[10];
for (int i = 0; i < ID.length; i++) {
System.out.print("Please enter ID and times: ");
ID[i] = sc.nextInt();
time[i] = sc.nextDouble();
}
Run a = new Run(ID, time);
System.out.println("Top 3 is ");
a.Sort();
}
}
class Run {
private int[] ID = new int[10];
private double[] time = new double[10];
public Run(int[] ID, double[] time) {
for (int i = 0; i < ID.length; i++) {
this.ID[i] = ID[i];
}
for (int i = 0; i < time.length; i++) {
if (time[i] <= 20.0) {
this.time[i] = time[i];
}
}
}
public void Sort() {
double tem1;
int tem2;
for (int i = 0; i < time.length - 1; i++) {
for (int j = 0; j < time.length - 1; j++) {
if (time[j] > time[j+1]) {
tem1 = time[j];
time[j] = time[j+1];
time[j+1] = tem1;
tem2 = ID[j];
ID[j] = ID[j+1];
ID[j+1] = tem2;
}
}
}
for (int i = 0; i < 3; i++) {
System.out.println(ID[i] + " " + time[i]);
}
}
}

What should I do to fix this scanner-related bug?

Even though this code compiles:
import java.util.Scanner; // imports the Scanner class from the java.util package
public class ScannerPractice {
public static void main(String args[]) {
Scanner word = new Scanner("word 1 2 3 4"); // creates a new Scanner objecrt with a string as its input
String scaStr = word.nextLine(); // converts scanner to string
String strArr[] = new String[10];
// as long as the scanner has another character...
for (int i = 0; i < scaStr.length(); i++) {
int j = 0;
String k = "";
// if the next token is an integer...
if (word.hasNextInt()) {
j = word.nextInt();
k = String.valueOf(j);
strArr[i] = k;
}
// otherwise, skip over that token
else {
word.next();
}
}
String k = "";
// for each character in charArr
for (int i = 0; i < strArr.length; i++) {
// Accumulate each element of charArr to k
k += " " + strArr[i];
}
System.out.print(k);
}
}
I get this error:
Exception in thread "main" java.util.NoSuchElementException
at java.util.Scanner.throwFor(Unknown Source)
at java.util.Scanner.next(Unknown Source)
at ScannerPractice.main(ScannerPractice.java:28)
The exception refers to line 28, which is:
word.next();
I have tried looking at my for loop that assigns values to the string array, but I still couldn't find the error.
I am racking my brain trying to solve this. Even a hint would be most appreciated.
You already consumed all the strings in your Scanner on this line.
String scaStr = word.nextLine();
So, the scanner doesn't have more characteres and that's why you are getting that error.
I think you don't need to 'convert your scanner to string' in order to iterate over it. You can simply use a while to check if your Scanner has remaining characteres.
while(word.hasNext()) {
int j = 0;
String k = "";
// if the next token is an integer...
if (word.hasNextInt()) {
j = word.nextInt();
k = String.valueOf(j);
strArr[i] = k;
}
// otherwise, skip over that token
else {
word.next();
}
}
Change the loop to check whether the scanner has any more input:
Scanner word = new Scanner("word 1 2 3 4");
String strArr[] = new String[10];
int i = 0;
while (word.hasNext()) {
int j = 0;
String k = "";
if (word.hasNextInt()) {
j = word.nextInt();
k = String.valueOf(j);
strArr[i] = k;
}
else {
word.next();
}
}
It doesn't make sense to iterate over the string you already consumed from the scanner, because then you lose the ability to match tokens. If you wanted to use a string tokenizer you could do that, but then you can drop using the scanner.
If you want your code to run correctly change the input to:
Scanner word = new Scanner("word"+"\n"+"1"+"\n"+"2"+"\n"+"3"+"\n"+"4");
adding newline character solves the problem.

Why Exception in thread "main" java.util.NoSuchElementException?

import java.io.*;
import java.util.*;
public class chopMiddle {
public static void main(String[] args) {
String sample = "1,2,3,4,5";
StringTokenizer tokenizer = new StringTokenizer(sample, ",");
while(tokenizer.hasMoreTokens()) {
int convertedToInt = Integer.parseInt(tokenizer.nextToken());
int [] array = new int [3];
for(int i = 0; i < array.length; i++)
{
array[i] = Integer.parseInt(tokenizer.nextToken());
System.out.println(array[i] + " ");
}
}
}
}
I try to break the string into tokens and uses Integer.parseInt method to convert the tokens into int value.
I want to return an array of size 3 which contains the int values of the 2nd to the 4th integers from the string to the caller. Am i doing something wrong, because it shows below message when i compiled
Exception in thread "main" java.util.NoSuchElementException
at java.util.StringTokenizer.nextToken(StringTokenizer.java:349)
at chopMiddle.main(chopMiddle.java:18)
The problem will be when it gets to the 5th token, it will read it, then create a new array and try to read 3 more.
After you have read the 2nd, 3rd and 4th, you should break both loops.
while(tokenizer.hasMoreTokens()) {
int convertedToInt = Integer.parseInt(tokenizer.nextToken());
int [] array = new int [3];
for(int i = 0; i < array.length && tokenizer.hasMoreTokens(); i++) //check hasMoreTokens
{
array[i] = Integer.parseInt(tokenizer.nextToken());
System.out.println(array[i] + " ");
}
}
you need to check every time when you call: tokenizer.nextToken()
If you check if tokenizer has more elements in the for loop itself then you won't require while loop at all.
try below example :
public static void main(String[] args) {
String sample = "1,2,3,4,5";
StringTokenizer tokenizer = new StringTokenizer(sample, ",");
int[] array = new int[3];
for (int i = 0; i < array.length && tokenizer.hasMoreTokens(); i++) {
array[i] = Integer.parseInt(tokenizer.nextToken());
System.out.println(array[i] + " ");
}
}

Categories

Resources