Still in while loop hell, Now with refined question!

Discussion in 'Java' started by mmoski, Sep 17, 2007.

  1. mmoski

    mmoski Guest

    I've refined my code to make it nice and basic.

    import java.util.Scanner;

    public class Parse {

    public static void main (String[] args) {

    Scanner sc = new Scanner(System.in);

    Node head = null;
    Node prev = null;
    String read = sc.next();
    Node a = new Node();

    while(sc.hasNext()){ // <-- PROBLEM AREA.

    a.data = read;

    if(head == null){
    head = a;
    }else{
    prev.next = a;
    }
    prev = a;
    read = sc.next();
    }

    for(Node pointer = head; pointer != null; pointer = pointer.next)
    {
    System.out.println(pointer.data);
    }

    }
    }

    class Node{
    public Node next;
    public String data;
    }

    First off, the list has to be of my own design, so the linkedList
    class is useless here. My problem is the while loop. I know that the
    scanner usually blocks for whatever reason. My question is, does
    anybody have a suggestion for me? If the scanner stalls waiting for
    more input, how do I make it un-stall?
     
    mmoski, Sep 17, 2007
    #1
    1. Advertising

  2. mmoski wrote:

    > First off, the list has to be of my own design, so the linkedList
    > class is useless here. My problem is the while loop. I know that the
    > scanner usually blocks for whatever reason. My question is, does
    > anybody have a suggestion for me? If the scanner stalls waiting for
    > more input, how do I make it un-stall?
    >


    By giving it more data, which does not help with the real objective of
    getting your loop to finish.

    Two possible solutions:

    1. Provide an end-of-file, so that the Scanner will reach a hasNext()
    false condition. You could do this by redirecting standard in to come
    from a file, or by entering the appropriate file ending character for
    the environment in which you are running.

    2. Don't use end-of-file at all. Pick some other end-of-data marker, a
    special data value, and make the loop continuation depend on the input
    not being the end-of-data marker.

    Patricia
     
    Patricia Shanahan, Sep 17, 2007
    #2
    1. Advertising

  3. mmoski

    mmoski Guest

    On Sep 16, 11:35 pm, Patricia Shanahan <> wrote:
    > mmoski wrote:
    > > First off, the list has to be of my own design, so the linkedList
    > > class is useless here. My problem is the while loop. I know that the
    > > scanner usually blocks for whatever reason. My question is, does
    > > anybody have a suggestion for me? If the scanner stalls waiting for
    > > more input, how do I make it un-stall?

    >
    > By giving it more data, which does not help with the real objective of
    > getting your loop to finish.
    >
    > Two possible solutions:
    >
    > 1. Provide an end-of-file, so that the Scanner will reach a hasNext()
    > false condition. You could do this by redirecting standard in to come
    > from a file, or by entering the appropriate file ending character for
    > the environment in which you are running.
    >
    > 2. Don't use end-of-file at all. Pick some other end-of-data marker, a
    > special data value, and make the loop continuation depend on the input
    > not being the end-of-data marker.
    >
    > Patricia


    Perhaps if I were to use a read line to wrap the whole while and it
    could reach it's EOF when it detects a blank line ie: by hitting enter
    twice while in the console. This is my next step but I fear that I'll
    still stall because I don't get how the program will make it to the
    next line because it has to break the nested while loop first.

    Basically I want the user to type in input such as:

    input one this is something
    input B this is something else
    hello world

    I want it to read in a line and then using another while loop inside
    the first I want it to then read each token in the line into a list.
    In the end it should put the head node of each list into an array to
    make an array of lists, which will then be processed in a certain
    way. I had this EXACT problem last year and never got a solution. I
    know that sc.next() will never return null, and that it blocks while
    waiting for input.

    I know what doesn't work.

    What does?
     
    mmoski, Sep 17, 2007
    #3
  4. mmoski

    Guest

    In article <>,
    mmoski <> wrote:
    > I've refined my code to make it nice and basic.
    >
    > import java.util.Scanner;
    >
    > public class Parse {
    >
    > public static void main (String[] args) {
    >
    > Scanner sc = new Scanner(System.in);
    >
    > Node head = null;
    > Node prev = null;
    > String read = sc.next();
    > Node a = new Node();
    >
    > while(sc.hasNext()){ // <-- PROBLEM AREA.


    Yes, it is a problem, and there's one more reason (for its being
    a problem) that I'm not sure anyone has pointed out yet:

    It doesn't make sense to check what hasNext() returns *after*
    making the call to next(); normal usage is to call next() only
    if hasNext() returns true. If you run this program and provide
    it a single string as input, followed by end-of-file, the loop
    will execute zero times. As I think someone suggested in the
    other thread, wouldn't it be simpler and less error-prone to write

    while(sc.hasNext()) {
    String read = sc.next();
    // do stuff with read
    }

    rather than having two calls to next() at different points in
    the program?

    >
    > a.data = read;
    >
    > if(head == null){
    > head = a;
    > }else{
    > prev.next = a;
    > }
    > prev = a;
    > read = sc.next();
    > }
    >
    > for(Node pointer = head; pointer != null; pointer = pointer.next)
    > {
    > System.out.println(pointer.data);
    > }
    >
    > }
    > }
    >
    > class Node{
    > public Node next;
    > public String data;
    > }
    >
    > First off, the list has to be of my own design, so the linkedList
    > class is useless here. My problem is the while loop. I know that the
    > scanner usually blocks for whatever reason. My question is, does
    > anybody have a suggestion for me? If the scanner stalls waiting for
    > more input, how do I make it un-stall?
    >


    --
    B. L. Massingill
    ObDisclaimer: I don't speak for my employers; they return the favor.
     
    , Sep 17, 2007
    #4
  5. mmoski

    Guest

    In article <>,
    mmoski <> wrote:
    > On Sep 16, 11:35 pm, Patricia Shanahan <> wrote:
    > > mmoski wrote:


    [ snip ]

    > Perhaps if I were to use a read line to wrap the whole while and it
    > could reach it's EOF when it detects a blank line ie: by hitting enter
    > twice while in the console. This is my next step but I fear that I'll
    > still stall because I don't get how the program will make it to the
    > next line because it has to break the nested while loop first.
    >
    > Basically I want the user to type in input such as:
    >
    > input one this is something
    > input B this is something else
    > hello world
    >
    > I want it to read in a line and then using another while loop inside
    > the first I want it to then read each token in the line into a list.
    > In the end it should put the head node of each list into an array to
    > make an array of lists, which will then be processed in a certain
    > way. I had this EXACT problem last year and never got a solution. I
    > know that sc.next() will never return null, and that it blocks while
    > waiting for input.
    >
    > I know what doesn't work.
    >
    > What does?
    >


    If you want to read input a line at a time, how about using a
    BufferedReader? Here's a quickly-hacked-together example of using
    one to read input a line at a time, until a blank line is detected.
    It compiles and runs for me, but no claims about all details being
    best-practice.

    import java.io.BufferedReader;
    import java.io.InputStreamReader;
    import java.io.IOException;

    public class EchoUntilBlank {

    public static void main (String[] args) throws IOException {
    // probably should deal with the IOException in the code
    // rather than just throwing it, but -- quick hack for now

    BufferedReader br =
    new BufferedReader( new InputStreamReader(System.in));

    String line = null;

    while(((line = br.readLine()) != null) && (!line.equals(""))) {
    System.out.println(line); // replace with your processing
    }
    }
    }

    --
    B. L. Massingill
    ObDisclaimer: I don't speak for my employers; they return the favor.
     
    , Sep 17, 2007
    #5
  6. mmoski

    Guest

    On Sep 17, 4:31 am, <> wrote:
    > In article <>,
    >
    > mmoski <> wrote:
    > > On Sep 16, 11:35 pm, Patricia Shanahan <> wrote:
    > > > mmoski wrote:

    >
    > [ snip ]
    >
    >
    >
    > > Perhaps if I were to use a read line to wrap the whole while and it
    > > could reach it's EOF when it detects a blank line ie: by hitting enter
    > > twice while in the console. This is my next step but I fear that I'll
    > > still stall because I don't get how the program will make it to the
    > > next line because it has to break the nested while loop first.

    >
    > > Basically I want the user to type in input such as:

    >
    > > input one this is something
    > > input B this is something else
    > > hello world

    >
    > > I want it to read in a line and then using another while loop inside
    > > the first I want it to then read each token in the line into a list.
    > > In the end it should put the head node of each list into an array to
    > > make an array of lists, which will then be processed in a certain
    > > way. I had this EXACT problem last year and never got a solution. I
    > > know that sc.next() will never return null, and that it blocks while
    > > waiting for input.

    >
    > > I know what doesn't work.

    >
    > > What does?

    >
    > If you want to read input a line at a time, how about using a
    > BufferedReader? Here's a quickly-hacked-together example of using
    > one to read input a line at a time, until a blank line is detected.
    > It compiles and runs for me, but no claims about all details being
    > best-practice.
    >
    > import java.io.BufferedReader;
    > import java.io.InputStreamReader;
    > import java.io.IOException;
    >
    > public class EchoUntilBlank {
    >
    > public static void main (String[] args) throws IOException {
    > // probably should deal with the IOException in the code
    > // rather than just throwing it, but -- quick hack for now
    >
    > BufferedReader br =
    > new BufferedReader( new InputStreamReader(System.in));
    >
    > String line = null;
    >
    > while(((line = br.readLine()) != null) && (!line.equals(""))) {
    > System.out.println(line); // replace with your processing
    > }
    > }
    >
    > }
    >
    > --
    > B. L. Massingill
    > ObDisclaimer: I don't speak for my employers; they return the favor.


    I vote for BufferedReader (or any Reader implementation for that
    matter). If the lines are all text and you really want to process
    input an entire line at a time, this is really the most java-esque way
    of doing it IMHO.
     
    , Sep 18, 2007
    #6
  7. mmoski

    Lew Guest

    Besides all the advice on how to get a line in to your program, you have a
    separate problem of how to do the loop, and how to stop it.

    It is good to focus on one problem at a time. The fact that you can gives you
    the design principle to separate each problem into separate methods or
    separate classes.

    Many here have spoken of the way to get in a line to parse into your Node
    list. That makes it one problem, and it deserves its own method. Let's call
    that method retrieveLine().

    public class NodeWorker
    {
    public String retrieveLine()
    {
    String result;
    // put one of the suggested implementations here
    result = ...;
    return result;
    }
    }

    Actually, once you fill in that ellipsis, you've got a complete, but so far
    useless class.

    Get that part to compile and then add another method to do something useful,
    say, create a Node from a String.

    Wait! What's a Node? Well, it's something you add to a NodeList that holds a
    String.

    class Node
    {
    private String data;
    private Node next;

    public String getData()
    {
    return data;
    }
    public void setData( String v )
    {
    this.data = v;
    }

    public Node getNext()
    {
    return next;
    }
    public void setNext( Node v )
    {
    this.next = v;
    }
    }

    What I'm showing here is to use standard get/set accessor methods for private
    variables.

    (If the class were generic it would be a Node<T> and you'd substitute T for
    String in the class definition.)

    Now you need to have an add( Node n ) method in NodeWorker. This is where you
    use that one part of your original program where you manipulate head and prev.

    You really need to think about whether prev does any good yet. Start with
    just having head.

    Where does head go? In NodeWorker?

    Unlike the other variables, head does not get accessor methods.
    Just add( Node n ).

    // within NodeWorker
    private Node head; // don't presume to initialize it yet

    public void add( Node n )
    {
    if ( n == null )
    {
    String msg = "Let's avoid null for now, shall we?";
    throw new IllegalArgumentException( msg );
    }
    n.setNext( head );
    head = n;
    }

    Notice that this handles just one eensy-weensy piece of the action. No
    worries about what the Node has for data, just a little play with the structure.

    At this point you should write the main() for NodeWorker and try to get just
    these methods to do something useful, perhaps watching in a debugger to see if
    it does what you want.

    Or anything at all.

    Then add the logic to, say, parse the next token from a line and create a node
    for it. Test.

    Add a loop to main() to check for a next token, then do something with it
    inside the loop using the methods you've developed by that point.

    Make sure to follow blmblm's advice:
    > It doesn't make sense to check what hasNext() returns *after*
    > making the call to next(); normal usage is to call next() only
    > if hasNext() returns true.


    Build it one step at time, and it'll come.

    --
    Lew
     
    Lew, Sep 18, 2007
    #7
  8. mmoski

    Lew Guest

    Lew wrote:
    > Unlike the other variables, head does not get accessor methods.


    Actually, you might want a getter for it eventually. I didn't see a need for
    it at first, but perhaps later.

    --
    Lew
     
    Lew, Sep 18, 2007
    #8
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Jeff
    Replies:
    1
    Views:
    313
    Chris Smith
    Dec 27, 2004
  2. Replies:
    3
    Views:
    401
    Daniel T.
    Oct 12, 2006
  3. mmoski

    While loop hell.

    mmoski, Sep 16, 2007, in forum: Java
    Replies:
    3
    Views:
    333
    Eric Jablow
    Sep 16, 2007
  4. DZantow
    Replies:
    0
    Views:
    205
    DZantow
    Dec 20, 2011
  5. Isaac Won
    Replies:
    9
    Views:
    407
    Ulrich Eckhardt
    Mar 4, 2013
Loading...

Share This Page