0

So I am pretty sure I am using next and hasNext incorrectly... I am attempting to input a string of ACGT characters and then count the individual resulting letters. Thanks in advance.

import java.util.Scanner;

public class A1Novice {
    public static void main(String[] args){
        String input = "";
        Scanner s = new Scanner(System.in);
        Scanner j = new Scanner(input);
        System.out.println("Enter nucleobases (enter end when done)");
        while(true){
            input = s.next() + input;
            if(s.next().contains("end")){
                break;
            }
        }
        process(j, input);  
    }

    public static void process(Scanner j, String input){
        int a = 0, c = 0, g = 0, t = 0;
        while(j.hasNext()){
            if (j.next()=="A"){
                a++;
            }
            else if(j.next()=="C"){
                c++;
            }
            else if(j.next()=="G"){
                g++;
            }
            else if(j.next()=="T"){
                t++;
            }
            else{
                System.out.println("A count: " + a);
                System.out.println("C count: " + c);
                System.out.println("G count: " + g);
                System.out.println("T count: " + t);
                break;
                }
         }

    }
}
Jonas
  • 121,568
  • 97
  • 310
  • 388
user3212766
  • 5
  • 1
  • 3
  • possible duplicate of [How do I compare strings in Java?](http://stackoverflow.com/questions/513832/how-do-i-compare-strings-in-java) – Dennis Meng Jan 19 '14 at 18:21
  • Yeah you want to use the .equals method – ZekeDroid Jan 19 '14 at 18:22
  • 2
    Cache the result of `j.next()` in some variable, then check for its value instead. – raina77ow Jan 19 '14 at 18:22
  • @DennisMeng Not a duplicate, but useful link. – Darkhogg Jan 19 '14 at 18:23
  • also, yes, j.next() will remove an element so here you're removing 4 elements per loop just to see if they are equal – ZekeDroid Jan 19 '14 at 18:23
  • There is no need to use next() in the if check – Sashi Kant Jan 19 '14 at 18:23
  • How about `String tmp = j.next()`, then compare `tmp`. –  Jan 19 '14 at 18:23
  • @Darkhogg Ah yeah, I see the other issue here now. Granted, the problem he's going to hit *after* that *is* a dupe. – Dennis Meng Jan 19 '14 at 18:25
  • Thanks guys! So I am using the if/else solution with j.next() assigned to a variable and using the .equals method instead of ==. After I enter input the program still crashes, I ran debugging and there seems to be a problem with `String val = j.next();`... any ideas? – user3212766 Jan 19 '14 at 22:06
  • @DennisMeng What is the other issue you mentioned earlier? – user3212766 Jan 19 '14 at 22:32
  • I was referring to the string comparison, but it looks like you've got that part already. As for the crashing that you're getting now, `Scanner j = new Scanner(input)` is *definitely* not what you want. Go back over your `main`, there's still at least two issues I see. – Dennis Meng Jan 20 '14 at 03:13
  • Oh okay, I think I understand. Would System.In work better? – user3212766 Jan 20 '14 at 18:05

4 Answers4

2

Put it in a local variable.

 String next = j.next();

and use that in your if statements. Otherwise you will advance the iterator in every check.

Here is what it should look like:

public static void process(Scanner j, String input){
    int a = 0, c = 0, g = 0, t = 0;

    while(j.hasNext()){
        String n = j.next();
        if (n.equals("A")){
            a++;
        }
        else if(n.equals("C")){
            c++;
        }
        else if(n.equals("G")){
            g++;
        }
        else if(n.equals("T")){
            t++;
        }
        else{
            ...
        }
     }

}

Plus, do not use == to compare Strings. The == operator will check if it is the same object instance, but not whether the content is equal. Use the equals method instead.

kmera
  • 1,725
  • 10
  • 22
2

As already written you have to put your next element in a local variable.

This is not enough however: please never use == to compare strings. Use String's method equalsinstead or even equalsIgnoreCase.

You should use something like :

String val = j.next();
if(val.equals("A")){ // you could use val.equalsIgnoreCase("A") to be case insensitive
    ...
} else if (val.equals("B")){
    ...

As suggested in aljipa's answer, you you to use a switch. If you want your test to be case insensitive can can also write something like:

String val = j.next();
switch (val.toUpperCase()) {
    case "A":
        a++;
        break;
    case "B":
        ...
C.Champagne
  • 5,381
  • 2
  • 23
  • 35
  • In Java 7, you can also use a switch statement instead. – Dennis Meng Jan 19 '14 at 18:32
  • It doesn't hurt to add it in anyway (so that your answer stands alone). Generally, what I do when I add extra info is acknowledge the person in the answer (since they *did* bring it up first). – Dennis Meng Jan 19 '14 at 18:44
1

k-mera's answer is correct, but consider using switch since it's asymptomatically more effective:

public static void process( Scanner j, String input ) {
 int a = 0, c = 0, g = 0, t = 0;
 String ch;
 while( j.hasNext() ) {
     switch( ch = j.next() ) {
         case "A":
              a++;
              break;
     case "C":
          c++;
          break;
     case "G":
          g++;
          break;
     case "T":
          t++;
          break;
         default:
              System.out.println("A count: " + a);
              System.out.println("C count: " + c);
              System.out.println("G count: " + g);
              System.out.println("T count: " + t);
              return;
         }
     }
}

Additionally I'd rather use simple ( char ) System.in.read() if you need to read char by char there's no need in polluting your heap with redundant String instances which is exactly what Scanner.next() does unless you don't tokenise the input in a custom way.

aljipa
  • 716
  • 4
  • 6
  • No, as it was written k-mera's answer was not correct but yours is ... (only in Java 7 however)! Furthermore, it is more readable. – C.Champagne Jan 19 '14 at 18:38
  • Uh, it seems he already edited and I didn't notice. I think readability is not as important as more asymptomatically faster algorithm, some would doubt that a switch with lots of breaks is more readable. As for Java 7, Scanner wasn't there until Java 5 too :) – aljipa Jan 19 '14 at 18:50
  • I had put a comment on his answer. – C.Champagne Jan 19 '14 at 18:51
0

The j.next() on an iterator will essentially go on to the next loop so you're making 4 loops on every loop.

ZekeDroid
  • 7,089
  • 5
  • 33
  • 59