LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   Strange java algorithm! (https://www.linuxquestions.org/questions/programming-9/strange-java-algorithm-603752/)

Cyhaxor 12-01-2007 10:18 AM

Strange java algorithm!
 
Code:

import java.util.Scanner;
class test {
        public static void main(String[] args) {
                Scanner sc = new Scanner(System.in);
                int n = 0;
                int i=0;
                System.out.println("How many names?");
                n = sc.nextInt();
                String[] arrayString = new String[n];
                arrayString[i] = sc.nextLine(); // notice this request for input before the loop (seems to be useless)
                for (i=0; i<n; i++) {
                        System.out.println("Give the name:");
                        arrayString[i] = sc.nextLine(); // request for input inside the loop.
                }
               
                for (i=0; i<arrayString.length; i++) {
                        System.out.println(arrayString[i]);
                }
        }
}

Ok the above code is working fine and it got me 30mins to find the right algorithm.

The strange thing is that: Let's rewrite the above code slightly different (see comments):
Code:

import java.util.Scanner;
class test {
        public static void main(String[] args) {
                Scanner sc = new Scanner(System.in);
                int n = 0;
                int i=0;
                System.out.println("How many names?");
                n = sc.nextInt();
                String[] arrayString = new String[n];
                // ***Remove the request before the loop.
                for (i=0; i<n; i++) {
                        System.out.println("Give the name:");
                        arrayString[i] = sc.nextLine(); // ***request for input only inside the loop.
                }
               
                for (i=0; i<arrayString.length; i++) {
                        System.out.println(arrayString[i]);
                }
        }
}

The second program seems more correct. But in fact if you run it it will ask you how many names? Let's say 3...
The result will be something like:

Give the name:
Give the name:
me
Give the name:
and you

me
and you

Notice that the array at the point [0] has been set to An empty string by default. The first program works fine for n=3 again:
Give the name:
Me
Give the name:
and you
Give the name:
3rd name
Me
and you
3rd name

Can anybody give me a comprehensive explanation why that happens? Because believe me.. I might solved out my problem but I still don't realize why I have to put a duplication of input over the loop.

Thanks in advance,
Cyhaxor

koyi 12-01-2007 11:38 AM

I didn't check with the API so this is just a guess :D

I guess that sc.nextInt() only read the next integer, without bothering if there is any character, including newline(\n), following that number.

As a concrete example, say you enter "3" when you are asked to specify the number of names. This input reaches the program as "3\n". When you call sc.nextInt(), it only takes the "3" and leave the "\n" in the scanner's buffer. This "\n" will be read the next time you call sc.nextLine(), which leads to the problem in the second code.

Cyhaxor 12-01-2007 12:45 PM

Hm i don't know if you're right but your answer seems to be logic... Is there any way to change this? Because is a little annoying to put a useless scanner before the loop.. You know is a bad practice! But thanks for your answer anw! :)

Alien_Hominid 12-01-2007 03:32 PM

Just print your line as chars and check what was assigned to the String. Probably koyi is right.

Cyhaxor 12-01-2007 04:58 PM

yeah koyi is right but I am asking if is there any way to get the sc.nextInt(); to handle the "/n" If i do this the scanner over the loop will be non-needed. I have no problem with the program as it works fine, but is a little annoying the scanner over the loop :P

PS:And the solution is not to get the n=3 as a string and convert it to int... This would be even annoying :D

paulsm4 12-01-2007 09:13 PM

Hi -

As koyi said, and as you now realize, the problem is that java.util.Scanner's "nextInt()" function just grabs the characters it needs (for example, "3"), leaving the rest of the line to be parsed by subsequent calls ... including the "\n", which delimits the end of the line.

One solution (since you expect a line)... is to simply ask for a line. In other words, use "nextLine()", and then convert the input:
Code:

import java.util.Scanner;

class Test {
  public static void main(String[] args) {

    Scanner sc = new Scanner(System.in);
    System.out.print ("Enter #/names: ");
    String s = sc.nextLine ();
    int n = Integer.parseInt (s);

    System.out.println ("OK: please enter " + n + " names:");
    String[] arrayString = new String[n];
    for (int i=0; i < n; i++) {
      System.out.print ("name #" + (i+1) + ": ");
      arrayString[i] = sc.nextLine();
    }

    for (int i=0; i<arrayString.length; i++) {
      System.out.println("name[" + i + "]: " + arrayString[i]);
    }
  }
}


Cyhaxor 12-02-2007 08:02 AM

Quote:

Originally Posted by Cyhaxor (Post 2976995)
PS:And the solution is not to get the n=3 as a string and convert it to int... This would be even annoying :D

This would be a nice solution but it still annoying. Look I am not trying to bother you and thanks for your reply but what I am looking for is if is there any way to make the nextInt(); handle the "\n"... If isn't there any solution just tell it to me... ;) Thanks for your support all of you! :)

Alien_Hominid 12-02-2007 05:36 PM

There are InputStreamReaders, but they would be more annoying than paulsm4 solution.

Cyhaxor 12-03-2007 09:31 AM

Hm ok then, thanks for the help and ok I'll put up with java's strange behavior ;)

jay73 12-04-2007 01:57 AM

Strange behaviour? So you'd actually prefer your methods to do more than they should?

Anyway, there is an alternative solution called a StreamTokenizer. It's getting to be legacy but it still comes in handy now and again. In case you wonder, a StreamTokenizer takes input and parses it by taking spaces as delimiters. It can distinguish between numbers, words and Strings but it's up to you to provide the implementation. As you can guess, it involves more coding than Scanner methods.


All times are GMT -5. The time now is 05:35 AM.