javastringacm-java-libraries

Exception in thread "main" java.lang.StringIndexOutOfBoundsException


Exception in thread "main" java.lang.StringIndexOutOfBoundsException: String index out of range: 7
    at java.lang.String.charAt(Unknown Source)
    at DNAmatch.findFirstMatchingPosition(DNAmatch.java:100)
    at DNAmatch.run(DNAmatch.java:82)
    at acm.program.Program.runHook(Program.java:1568)
    at acm.program.Program.startRun(Program.java:1557)
    at acm.program.Program.start(Program.java:808)
    at acm.program.Program.start(Program.java:1279)
    at acm.program.Program.main(Program.java:1360)

I got this weird error and I don't know what is causing it. I googled for a solution to my problem but nothing helped me solve it. If you try as inputs for chain1 atcg and for chain2 tagaagtc, it works fine but for inputs chain1 atcg and chain2 tagaagct then i got this error. If anyone could help i'd appreciate it.

=================================================

import acm.program.*;

public class DNAmatch extends Program
{
public void run()
{
    //The chains must only contain the characters A,T,C or G so we check the string for any irregularities.
    String current, chain2; Boolean flag=true; int errorCount;
    String chain1 = readLine("Please type in the first chain of DNA code: ");
    for (int i=0; i<chain1.length(); i++)
    {
        current = chain1.charAt(i) +"";
        if (!((current.equalsIgnoreCase("a"))||(current.equalsIgnoreCase("t"))||
                (current.equalsIgnoreCase("c"))||(current.equalsIgnoreCase("g"))))
        {
            flag=false; break;
        }
    }
    while (flag==false)
    {
        errorCount=0;
        println("The DNA code you insert must only contain the characters A, T, C and G");
        chain1 = readLine("Please type again in the first chain of DNA code: ");

        for (int i=0; i<chain1.length(); i++)
        {
            current=chain1.charAt(i) +"";
            if (!((current.equalsIgnoreCase("a"))||(current.equalsIgnoreCase("t"))||
                (current.equalsIgnoreCase("c"))||(current.equalsIgnoreCase("g"))))
            {
                errorCount =1; break;
            }
        }
        if (errorCount==0)
        {
            flag=true; break;
        }

    }
    chain2 = readLine("Please type in the second chain of DNA code: ");
    flag=true;
    for (int i=0; i<chain2.length(); i++)
    {
        current = chain2.charAt(i) +"";
        if (!((current.equalsIgnoreCase("a"))||(current.equalsIgnoreCase("t"))||
                (current.equalsIgnoreCase("c"))||(current.equalsIgnoreCase("g")))&&(chain1.length()>chain2.length()))
        {
            flag= false; break;
        }
    }

    while ((flag==false)&&(chain1.length()>chain2.length()))
    {
        errorCount=0;
        if (chain1.length()>chain2.length())
            println("The second DNA chain must be longer or equal to the first one at the most!");
        else
            println("The DNA code you insert must only contain the characters A, T, C and G");
        chain2 = readLine("Please type again the second chain of DNA code: ");
        for (int i=0; i<chain2.length(); i++)
        {
            current = chain2.charAt(i) +"";
            if (!((current.equalsIgnoreCase("a"))||(current.equalsIgnoreCase("t"))||
                    (current.equalsIgnoreCase("c"))||(current.equalsIgnoreCase("g")))&&(chain1.length()>chain2.length()))
            {
                errorCount =1; break;
            }
        }
        if (errorCount==0)
        {
            flag=true;
        }
    }

    int match=findFirstMatchingPosition(chain1,chain2);
    if (match==-1)
        println("Not match found! "+ match);
    else
        println("Match has been found at point "+ match+ "!");

}
public int findFirstMatchingPosition(String shortDNA, String longDNA)
{
    String currentCharShort=""; String currentCharLong="";
    int match=0; int ans=-1; int a;
    for (int i=0; i < longDNA.length(); i++)
    {
        a = i;
        match = 0;

        for (int j=0; j < shortDNA.length(); j++)
        {
            currentCharLong=longDNA.charAt(a)+ "";
            currentCharShort=shortDNA.charAt(j)+ ""; 

            if ( (currentCharShort.equalsIgnoreCase("a") && currentCharLong.equalsIgnoreCase("t"))||
                (currentCharShort.equalsIgnoreCase("t") && currentCharLong.equalsIgnoreCase("a"))||
                (currentCharShort.equalsIgnoreCase("c") && currentCharLong.equalsIgnoreCase("g"))||
                (currentCharShort.equalsIgnoreCase("g") && currentCharLong.equalsIgnoreCase("c")) )
            {
                match +=1;
                a +=1;
            }
            else break;
        }
        if (match == shortDNA.length())
        {
            ans=i;
            break;
        }

    }
    return ans;
}

}


Solution

  • When you enter this for loop

    for (int j=0; j < shortDNA.length(); j++)
        {
            currentCharLong=longDNA.charAt(a)+ "";
            currentCharShort=shortDNA.charAt(j)+ ""; 
    
            if ( (currentCharShort.equalsIgnoreCase("a") && currentCharLong.equalsIgnoreCase("t"))||
                (currentCharShort.equalsIgnoreCase("t") && currentCharLong.equalsIgnoreCase("a"))||
                (currentCharShort.equalsIgnoreCase("c") && currentCharLong.equalsIgnoreCase("g"))||
                (currentCharShort.equalsIgnoreCase("g") && currentCharLong.equalsIgnoreCase("c")) )
            {
                match +=1;
                a +=1;
            }
            else break;
        }
    

    with "a" that is the index of your last character in longDNA (say 5 if longDNA has six characters), when you enter the if branch and put a+=1 you now have an index that is greater than longDNA size. So when you iterate again and search for charAt(a) the exception will be thrown. This could also happen with lesser "a" if you execute the a+=1 statement different times in the internal for loop.