Question

I'm very close to being done, but can't quite figure out how to tie everything together. I have the separate methods responsible for their particular task, but i feel like my cohesion is really bad. not real sure how they tie together and what needs to be called in main. The goal here is to read a text file from the command line and list the words in the story lexicographically.

% java Ten < story.txt
Word      Occurs
====      ======
a          21
animal      3
 .
 .
 .
zebra       1
%

Here's my code thus far:

import java.util.Scanner;

public class Ten2
{
    public static void main(String [] arg)
    {
        Scanner input = new Scanner(System.in);

        String word;
        List sortedList = new List();
        word = nextWord(input);

        while (word!=null) {
            sortedList.insert(word);
            word = nextWord(input);
        }

        sortedList.printWords();        
    }

    private static String nextWord(Scanner input)
    {   
        // return null if there are no more words
        if (input.hasNext() == false )
            return null;
        // take next element, convert to lowercase, store in s
        else { 
            String s = input.next().toLowerCase() ;
            // empty string
            String token = "";
            // loop through s and concatonate chars onto token
            for (int i =0; i < s.length(); i++) {
                if (Character.isLetter(s.charAt(i)) == true)
                    token = token + s.charAt(i);
                else if (s.charAt(i) == '\'' )
                    token = token + s.charAt(i);
                else if (s.charAt(i) == '-')
                    token = token + s.charAt(i);
            }
            return token; 
        }      
    }   
}

class List
{
    /*
     * Internally, the list of strings is represented by a linked chain 
     * of nodes belonging to the class ListNode. The strings are stored
     * in lexicographical order.
     */
    private static class ListNode
    {
        // instance variables for ListNode objects
        public String word;
        public ListNode next;
        public int count;

        // Listnode constructor               
        public ListNode(String w, ListNode nxt)
        {  
            word = w; // token from nextWord()?
            next = nxt; // link to next ListNode
            count = 1; // number of word occurences
        }
    }

    // instance variables for List object
    private ListNode first;
    private int numWords;

    // constructor postcondition: creates new Listnode storing object
    public List()
    { 
        first = null; // pointer to ListNode?
        numWords = 0; // counter for nodes in list
    }


    //  Insert a specified word into the list, keeping the list 
    //  in lexicographical order.
    public void insert(String word)
    {    
        // check if first is null
        if (first == null) {
            ListNode newNode;
            newNode = addNode(word, null);
            first = newNode;          
        }   

        // else if (first is not null) check if word matches first word in List
        else if (word.equals(first.word)) {
            // increase count
            first.count++;
            }

        // else (first is not null && doesn't match first word) 
        else {  
            ListNode newNode;
            ListNode current;
            current = first;
            ListNode previous;
            previous = null;
            int cmp =  word.compareTo(current.word);

            /*
             * Fist two cases of empty list and word already existing
             * handled in above if and else statements, now by using compareTo() 
             * method between the words, the insertion postion can be determined.
             * Links between ListNode variables current and previous need to be
             * modified in order to maintain the list
             */


            // loop as long as value comparing to is positive
            // when compareTo() returns positive this means the "word" parameter is greater than the word in the list 
            while ((cmp >0) && (current.next != null)) {
                previous = current;    
                current = current.next;
                cmp =  word.compareTo(current.word);
            }

            // insert after current at end of list
            if ((cmp >0 && current.next == null)) {
                newNode = addNode(word, null);
                current.next = newNode;
            }

            // increments count when word already exists
            else if (cmp==0) {
                current.count++;
            }

            // else (cmp < 0) we insert BEFORE current
            else { 
                newNode = addNode(word, current);

                // first node in list comes after new word
                if (previous == null) {
                    first = newNode;       
                }         

                else {
                    // inserting new word in middle of list
                    previous.next = newNode;
                }
            }       
        }
    }

    // method to add new ListNode and increase counter
    private ListNode addNode(String word, ListNode next)
    {
        ListNode newNode = new ListNode(word, next);
        numWords++;
        return newNode;
    }


    // Returns a string array that contains all the words in the list.  
    public String[] getWords() 
    {
        String[] Words = new String[numWords];
        ListNode current = first;
        int i =0;

        while (current != null) {     
            Words[i] = current.word;
            current = current.next;
            i++;
        }
        return Words;
    }   


    // Returns an int array that contains the number of times 
    // each word occurs in the list.  
    public int[] getNumbers()
    {
        int[] Numbers = new int[numWords];
        ListNode current = first;
        int i =0;

        while (current != null) {
            Numbers[i] = current.count;
            current = current.next;
            i++;
        }
        return Numbers;
    }


    // Outputs the string array and int array containing all the   
    // words in the list and the number of times each occurs.
    public void printWords()
    {
        int[] Numbers = getNumbers();
        String[] Words = getWords();

        System.out.println("Word   \t    \t    Occurs");
        System.out.println("====   \t    \t    ======");

        for (int i =0; i < numWords; i++) { 
            System.out.println(Words[i] + " \t " + Numbers[i]);   
        }
    }      
}   
Was it helpful?

Solution

Well, I would start by defining what you want your program to do, which you've already done:

The goal here is to read a text file from the command line and list the words in the story lexicographically.

You're main function does this almost. Basically, what you need is a loop to tie it together:

public static void main(String [] arg)
{
    // print out your initial information first (i.e. your column headers)
    // ...

    List sortedList = new List();
    String word = nextWord();

    // now, the question is... what is the end condition of the loop?
    // probably that there aren't any more words, so word in this case
    // will be null
    while (word != null)
    {
      sortedList.insert(word);
      word = nextWord();
    }

    // now, your list takes care of the sorting, so let's just print the list
    sortedList.printWords();
}

I think that's all there is to it. Normally, I don't like to post solutions to homework questions, but in this case, since you already had all of the code and you just needed a little nudge to drive you in the right direction, I think it's fine.

There are a few things I noticed that are incorrect with your

Your list constructor has a 'void' return type - there should be no return type on constructors:

public List() //make an empty list
{ 
    first = null;
    numWords = 0;
}

The 'else' statement in this method is unneeded:

    public static String nextWord()
    {   
        if ( keyboard.hasNext() == false )
            return null;
        else {   
            String start =  keyboard.next().toLowerCase() ;
            String organized = "";
            for (int i =0; i < start.length(); i++) {
                if (Character.isLetter(start.charAt(i)) == true)
                    organized = organized + start.charAt(i);

                else if (start.charAt(i) == '\'' )
                    organized = organized + start.charAt(i);

                else if (start.charAt(i) == '-')
                    organized = organized + start.charAt(i);
            }
            return organized;       
        }   
    }

So, this should be:

public static String nextWord()
{   
    if ( keyboard.hasNext() == false )
        return null;
    String start =  keyboard.next().toLowerCase() ;
    String organized = "";
    for (int i =0; i < start.length(); i++) {
        if (Character.isLetter(start.charAt(i)) == true)
            organized = organized + start.charAt(i);

        else if (start.charAt(i) == '\'' )
            organized = organized + start.charAt(i);

        else if (start.charAt(i) == '-')
            organized = organized + start.charAt(i);
    }
    return organized;   
}

If you want to use a BufferedReader, it's pretty easy. Just set it up in your main method:

  if (arg.length > 0)
  {
    // open our file and read everything into a string buffer
    BufferedReader bRead = null;
    try {
      bRead = new BufferedReader(new FileReader(arg[0]));
    } catch(FileNotFoundException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
      System.exit(0);
    }
    setupScanner(bRead);
  }

Then, create a new method that sets up the scanner object:

public static void setupScanner(BufferedReader rdr)
{
  keyboard = new Scanner(rdr);
}

And then just pass it in on the command line (i.e. java ten2 [filename])

OTHER TIPS

    import java.util.Scanner;

public class Ten2
{
    public static void main(String [] arg)
    {
        Scanner input = new Scanner(System.in);

        String word;
        List sortedList = new List();
        word = nextWord(input);

        while (word!=null) {
            sortedList.insert(word);
            word = nextWord(input);
        }

        sortedList.printWords();        
    }

    private static String nextWord(Scanner input)
    {   
        // return null if there are no more words
        if (input.hasNext() == false )
            return null;
        // take next element, convert to lowercase, store in s
        else { 
            String s = input.next().toLowerCase() ;
            // empty string
            String token = "";
            // loop through s and concatonate chars onto token
            for (int i =0; i < s.length(); i++) {
                if (Character.isLetter(s.charAt(i)) == true)
                    token = token + s.charAt(i);
                else if (s.charAt(i) == '\'' )
                    token = token + s.charAt(i);
                else if (s.charAt(i) == '-')
                    token = token + s.charAt(i);
            }
            return token; 
        }      
    }   
}

class List
{
    /*
     * Internally, the list of strings is represented by a linked chain 
     * of nodes belonging to the class ListNode. The strings are stored
     * in lexicographical order.
     */
    private static class ListNode
    {
        // instance variables for ListNode objects
        public String word;
        public ListNode next;
        public int count;

        // Listnode constructor               
        public ListNode(String w, ListNode nxt)
        {  
            word = w; // token from nextWord()?
            next = nxt; // link to next ListNode
            count = 1; // number of word occurences
        }
    }

    // instance variables for List object
    private ListNode first;
    private int numWords;

    // constructor postcondition: creates new Listnode storing object
    public List()
    { 
        first = null; // pointer to ListNode?
        numWords = 0; // counter for nodes in list
    }


    //  Insert a specified word into the list, keeping the list 
    //  in lexicographical order.
    public void insert(String word)
    {    
        // check if first is null
        if (first == null) {
            ListNode newNode;
            newNode = addNode(word, null);
            first = newNode;          
        }   

        // else if (first is not null) check if word matches first word in List
        else if (word.equals(first.word)) {
            // increase count
            first.count++;
            }

        // else (first is not null && doesn't match first word) 
        else {  
            ListNode newNode;
            ListNode current;
            current = first;
            ListNode previous;
            previous = null;
            int cmp =  word.compareTo(current.word);

            /*
             * Fist two cases of empty list and word already existing
             * handled in above if and else statements, now by using compareTo() 
             * method between the words, the insertion postion can be determined.
             * Links between ListNode variables current and previous need to be
             * modified in order to maintain the list
             */


            // loop as long as value comparing to is positive
            // when compareTo() returns positive this means the "word" parameter is greater than the word in the list 
            while ((cmp >0) && (current.next != null)) {
                previous = current;    
                current = current.next;
                cmp =  word.compareTo(current.word);
            }

            // insert after current at end of list
            if ((cmp >0 && current.next == null)) {
                newNode = addNode(word, null);
                current.next = newNode;
            }

            // increments count when word already exists
            else if (cmp==0) {
                current.count++;
            }

            // else (cmp < 0) we insert BEFORE current
            else { 
                newNode = addNode(word, current);

                // first node in list comes after new word
                if (previous == null) {
                    first = newNode;       
                }         

                else {
                    // inserting new word in middle of list
                    previous.next = newNode;
                }
            }       
        }
    }

    // method to add new ListNode and increase counter
    private ListNode addNode(String word, ListNode next)
    {
        ListNode newNode = new ListNode(word, next);
        numWords++;
        return newNode;
    }


    // Returns a string array that contains all the words in the list.  
    public String[] getWords() 
    {
        String[] Words = new String[numWords];
        ListNode current = first;
        int i =0;

        while (current != null) {     
            Words[i] = current.word;
            current = current.next;
            i++;
        }
        return Words;
    }   


    // Returns an int array that contains the number of times 
    // each word occurs in the list.  
    public int[] getNumbers()
    {
        int[] Numbers = new int[numWords];
        ListNode current = first;
        int i =0;

        while (current != null) {
            Numbers[i] = current.count;
            current = current.next;
            i++;
        }
        return Numbers;
    }


    // Outputs the string array and int array containing all the   
    // words in the list and the number of times each occurs.
    public void printWords()
    {
        int[] Numbers = getNumbers();
        String[] Words = getWords();

        System.out.println("Word   \t    \t    Occurs");
        System.out.println("====   \t    \t    ======");

        for (int i =0; i < numWords; i++) { 
            System.out.println(Words[i] + " \t " + Numbers[i]);   
        }
    }      
}  
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top