Java - Problem with Scanner loop

A place to discuss the implementation and style of computer programs.

Moderators: phlip, Moderators General, Prelates

User avatar
Ishindri
Posts: 534
Joined: Mon Sep 03, 2007 9:52 pm UTC
Location: Maryland, USA

Java - Problem with Scanner loop

Postby Ishindri » Tue Nov 11, 2008 8:42 pm UTC

Okay. So I'm taking an introductory Java course at my high school, and we're covering control statements right now. Basically, I wrote a loop to enter a name and an age until the user wants to quit. (Nothing's done with the data, it just gets overwritten every loop) Problem is, after the first iteration of the loop, it's like the first input statement is skipped completely, as well as in every loop afterward.

Code:

Code: Select all

import java.util.Scanner;

public class AgeInput
{
    public static void main (String[] args)
    {
        Scanner reader = new Scanner (System.in);

        String name;
        int age = 1;

        do
        {
            System.out.print("Please input a name: ");
            name = reader.nextLine();
            System.out.print("Please input an age, or 100 to quit: ");
            age = reader.nextInt();
        }
        while (age != 100);
    }
}


Output:
Spoiler:
Please input a name: Lord British
Please input an age, or 100 to quit: 9001
Please input a name: Please input an age, or 100 to quit: 1
Please input a name: Please input an age, or 100 to quit: 1
Please input a name: Please input an age, or 100 to quit: 1
Please input a name: Please input an age, or 100 to quit: 1
Please input a name: Please input an age, or 100 to quit: 1
Please input a name: Please input an age, or 100 to quit: 1
Please input a name: Please input an age, or 100 to quit: 1
Please input a name: Please input an age, or 100 to quit: 100


I have no idea why this happens. Another person suggested Scanner.reset, which apparently clears the input stream, but it didn't work. Thoughts?

Edit: I should note that no grades or anything are hanging on this, I'd simply like to find out why it doesn't work when by all appearances it should.
All is well. We are not like the others.

User avatar
Berengal
Superabacus Mystic of the First Rank
Posts: 2707
Joined: Thu May 24, 2007 5:51 am UTC
Location: Bergen, Norway
Contact:

Re: Java - Problem with Scanner loop

Postby Berengal » Tue Nov 11, 2008 8:52 pm UTC

You need to tack a reader.nextLine() at the end of that do-while loop. nextInt() actually doesn't advance past the line you're in, so while the contents of the line are empty, the current line itself is still there. When you next call nextLine() it doesn't block, because it has a line already. It's empty, of course, since you read all the characters out of it, so the empty string will be returned.

A good rule of thumb is that you need to call nextLine() for each line you read, regardless of if you read anything from it using e.g. nextInt() or next(). However, this isn't really true all the time either... Welcome to Scanner :/
It is practically impossible to teach good programming to students who are motivated by money: As potential programmers they are mentally mutilated beyond hope of regeneration.

User avatar
Ishindri
Posts: 534
Joined: Mon Sep 03, 2007 9:52 pm UTC
Location: Maryland, USA

Re: Java - Problem with Scanner loop

Postby Ishindri » Tue Nov 11, 2008 9:00 pm UTC

Thank you! It works perfectly. I'll keep that in mind from now on.
All is well. We are not like the others.

Stabable Offense
Posts: 48
Joined: Thu Oct 30, 2008 3:57 am UTC

Re: Java - Problem with Scanner loop

Postby Stabable Offense » Mon Nov 17, 2008 6:06 am UTC

this has to be the first time i've seen a do while loop in years

User avatar
Berengal
Superabacus Mystic of the First Rank
Posts: 2707
Joined: Thu May 24, 2007 5:51 am UTC
Location: Bergen, Norway
Contact:

Re: Java - Problem with Scanner loop

Postby Berengal » Mon Nov 17, 2008 12:02 pm UTC

It's useful for basic keyboard input with error checking, if you ever need a reason to do that. The basic pattern is

Code: Select all

String prompt = ...;
String errorPrompt = ...;
do{
   print(prompt);
   input = readInput();
   prompt = errorPrompt;
} while (invalidInput(input));

I've also heard rumors that "if (check) {do { stuff } while(check)}" is supposedly faster than a regular while, although I doubt this is true except when the code's directly translated to assembly...
It is practically impossible to teach good programming to students who are motivated by money: As potential programmers they are mentally mutilated beyond hope of regeneration.

User avatar
Ephphatha
Posts: 625
Joined: Sat Sep 02, 2006 9:03 am UTC
Location: Bathurst, NSW, Australia

Re: Java - Problem with Scanner loop

Postby Ephphatha » Mon Nov 17, 2008 12:07 pm UTC

I use do while loops occasionally, whenever I know a block of code is going to be executed at least once.
I'm not lazy, I'm just getting in early for Christmas is all...

Rysto
Posts: 1460
Joined: Wed Mar 21, 2007 4:07 am UTC

Re: Java - Problem with Scanner loop

Postby Rysto » Mon Nov 17, 2008 5:12 pm UTC

Berengal wrote:I've also heard rumors that "if (check) {do { stuff } while(check)}" is supposedly faster than a regular while, although I doubt this is true except when the code's directly translated to assembly...

It is, but any decent compiler will do that transformation for you.

gormo
Posts: 4
Joined: Mon Oct 15, 2007 4:18 pm UTC

Re: Java - Problem with Scanner loop

Postby gormo » Fri Nov 21, 2008 5:14 pm UTC

Ephphatha wrote:I use do while loops occasionally, whenever I know a block of code is going to be executed at least once.

do while loops are great when cobbling together command line menus.
boolean quit;
do{
menu options
}while(!quit)

User avatar
psykx
Posts: 408
Joined: Sat Feb 23, 2008 11:24 pm UTC
Location: England
Contact:

Re: Java - Problem with Scanner loop

Postby psykx » Fri Nov 21, 2008 5:39 pm UTC

gormo wrote:
Ephphatha wrote:I use do while loops occasionally, whenever I know a block of code is going to be executed at least once.

do while loops are great when cobbling together command line menus.
boolean quit;
do{
menu options
}while(!quit)



I don't see that that has any benefit that a normal while in that situation. A do while is useful if it is the default action (on false for example) for an action to be completed once.
Berengal wrote:Only if they're killer robots. Legos are happy robots. Besides, even if they were killer robots it wouldn't stop me. You can't stop science and all that.

gormo
Posts: 4
Joined: Mon Oct 15, 2007 4:18 pm UTC

Re: Java - Problem with Scanner loop

Postby gormo » Fri Nov 21, 2008 5:41 pm UTC

psykx wrote:
gormo wrote:
Ephphatha wrote:I use do while loops occasionally, whenever I know a block of code is going to be executed at least once.

do while loops are great when cobbling together command line menus.
boolean quit;
do{
menu options
}while(!quit)



I don't see that that has any benefit that a normal while in that situation. A do while is useful if it is the default action (on false for example) for an action to be completed once.

you're right, i'm having a simple day today.
i should have typed:
char sel;
do{
sel = in.readline.charAt(0);
switch (sel){
//menu options
}
}while(sel != 'Q')

User avatar
psykx
Posts: 408
Joined: Sat Feb 23, 2008 11:24 pm UTC
Location: England
Contact:

Re: Java - Problem with Scanner loop

Postby psykx » Fri Nov 21, 2008 6:33 pm UTC

I guess that makes more sense :p
Berengal wrote:Only if they're killer robots. Legos are happy robots. Besides, even if they were killer robots it wouldn't stop me. You can't stop science and all that.

User avatar
Ephphatha
Posts: 625
Joined: Sat Sep 02, 2006 9:03 am UTC
Location: Bathurst, NSW, Australia

Re: Java - Problem with Scanner loop

Postby Ephphatha » Sat Nov 22, 2008 8:44 am UTC

This was some assignment code I wrote earlier this year.

Code: Select all

int DropFiles(HWND hwnd,
              WPARAM wParam,
              char **destination,
              const int MAXLINES,
              const int LINELENGTH)
{   //Prompts the user to select what file they want to open if they drop more
    //than one file. If they only drop one file, asks for confirmation then
    //opens it. If they continue clicking no, will not open a file.
    //Returns the number of lines filled.
    int i = 0, index = 0;
    char buffer[MAX_PATH]; //Pathname buffer
    HDROP hdrop = (HDROP)wParam; //Handle to dropped file
    int fileCount = DragQueryFile(hdrop, 0xFFFFFFFF, NULL, 0);

    do
    {   //For this function to be called, at least one file was dropped.
        DragQueryFile(hdrop, i, buffer, MAX_PATH);
        //The following test is performed every time the loop is run, hence i
        //is incremented even if either test fails. If this causes i to be
        //incremented above the value of filecount, we assume that means the
    }   //user did not want to open a file.
    while((++i <= fileCount) &&
          (MessageBox(hwnd, buffer, "Would you like to open this file?",
                      MB_YESNO) == IDNO));

    if(i <= fileCount)
    {   //if they wanted to open one of the files.
        FreeArray(destination, MAXLINES);
        index = MyOpenFile(hwnd, buffer, destination, MAXLINES, LINELENGTH);
    }
    DragFinish(hdrop);
    return index;
}

int MyOpenFile(HWND hwnd,
               char *filename,
               char **destination,
               const int MAXLINES,
               const int LINELENGTH)
{   //Retarded name because there's already an OpenFile function?
    //Anyway, takes a filename, destination array, and copies lines from the
    //file to the array until it reaches the limit of lines. Returns the last
    //index it copied to.
    int index = 0;
    FILE *inputFilePtr = fopen(filename, "r");
    if(inputFilePtr && destination)
    {   //If the file exists and the destination isn't null...
        SetWindowText(hwnd, filename);

        do
        {   //Ok, as long as we haven't exceeded the max number of lines,
            //and as long as we haven't hit an error, grab the next line
            //Assuming there is room for at least one line.
            //Index is incremented only if there was no error and we haven't
            //reached the max number of lines.
            destination[index] = fgets((char*)calloc(LINELENGTH, sizeof(char)),
                                        LINELENGTH, inputFilePtr);
        }
        while((index < MAXLINES) && (destination[index] != NULL) && ++index);
        fclose(inputFilePtr); //No need to close the file if it wasn't opened
    }
    return index;
}


The first do while loop was made that way because there would have to be at least one file dropped on the window, the next was because there was at least one index in the array (if it was a pointer declared with calloc(1, sizeof(char*)) for example.

I don't think the marker actually looked at that code, because I shouldn't have used fgets() in that way... Also the odd linebreaks are due to me keeping my lines to 79 characters or less, and I had to carefully order tests.
I'm not lazy, I'm just getting in early for Christmas is all...

User avatar
OOPMan
Posts: 314
Joined: Mon Oct 15, 2007 10:20 am UTC
Location: Cape Town, South Africa

Re: Java - Problem with Scanner loop

Postby OOPMan » Mon Nov 24, 2008 9:00 am UTC

Stabable Offense wrote:this has to be the first time i've seen a do while loop in years


I sometimes use a while loop as a means of processing and array and consuming its contents as I do so...
Image

Image


Return to “Coding”

Who is online

Users browsing this forum: No registered users and 13 guests