Question

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;
                }
         }

    }
}
Was it helpful?

Solution

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":
        ...

OTHER TIPS

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.

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.

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

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top