-1

In my AP Computer Science class, we have an assignment where I need to input a string (which in this case is always a tweet) and then check to see if it meets the charlimit, see if it is a retweet, and then count the Hashtags and Mentions. I have figured all of this out, but for a Hashtag or mention to be counted, it has to not have a space or a return following it. My current solution is this:

for(int i=0; i < tweetLength; i++) {
  if((tweet.charAt(i) == '@')&&((tweet.charAt(i+1) != 0)||(tweet.charAt(i+1) != 32)||(tweet.charAt(i+1) != 13)) ) {
      countMentions++;

  } if((tweet.charAt(i) == '#')&&((tweet.charAt(i+1) != 0)||(tweet.charAt(i+1) != 32)||(tweet.charAt(i+1) != 13)) ) {
      countHashtags++;

  } if(((tweet.charAt(i) == 'R')||(tweet.charAt(i) == 'r'))&&((tweet.charAt(i + 1) == 'T')||(tweet.charAt(i + 1) == 't'))&&(tweet.charAt(i + 2) == ':')) {
      retweet = true;
  }
}

Note, 32, 13, and 0 are ascii values for the Space, Return, and Null (I think, lol) -- I used the numerical values in hopes that it would miraculously solve my problems, but alas, it has not.

It all works fine, but when there is an Ampersand or a Hash sign at the very end of the string, then it returns with this error:

java.lang.StringIndexOutOfBoundsException: String index out of range: 1
        at java.lang.String.charAt(String.java:686)
        at Main.main(Main.java:21)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:597)
        at edu.rice.cs.drjava.model.compiler.JavacCompiler.runCommand(JavacCompiler.java:272)

I know that this is caused because it is trying to read null, but I can't really find a solution and my teacher is the "Teach via. videos" kind, so not much help.

Hytyotwo
  • 3
  • 2
  • `tweet.charAt(i + 1)` -- this will break when you're at the end of the String. – Hovercraft Full Of Eels Oct 21 '16 at 19:54
  • Personally I'd use Regular Expressions to solve something like this (but I guess that's forbidden as it is a school/university assignment?). Here you have to check first if `i + 1` is still within bounds of your string – UnholySheep Oct 21 '16 at 19:56

1 Answers1

1

You need to be careful not to go outside of the bound when iterating over the characters in the string. You can achieve this by ensuring charAt(i) will not fail:

for(int i=0; i < tweetLength; i++)
    {
        if (i + 1 == tweetLength)
        {
            // avoid going out of bounds
            // when i == last char of the string
            break;
        }

        if (tweet.charAt(i) == '@')
            countMentions++;

        if (tweet.charAt(i) == '#')
            countHashtags++;

        if (i + 2 < tweetLength)
        {
            // search for i+2 only when
            // i+2 is not outside of the string
            if (((tweet.charAt(i) == 'R') || (tweet.charAt(i) == 'r')) && 
                    ((tweet.charAt(i + 1) == 'T') || (tweet.charAt(i + 1) == 't')) && 
                    (tweet.charAt(i + 2) == ':'))
            {
                retweet = true;
            }
        }
    }

As you can see I've added a break statement to exit the loop when we are positioned on the last character. We are also not going to check for ":" when we are on the last but one character from the end.

I hope you get the idea, but just FYI you're code doesn't "work all fine". You have some more corner cases for which you are not testing (e.g: "a b # c") it's not a valid hashtag so you also need to ensure that a valid letter comes after the hashtag sign. There maybe others like "#@abc" but you're somehow on the right track so I'll let you do your assignment and not do it for you.

If you want to better understand why the exception was thrown look at the code that throws it:

public char charAt(int index) {
    if ((index < 0) || (index >= value.length)) {
        throw new StringIndexOutOfBoundsException(index);
    }
    return value[index];
}

Now that I hope you've understand the logic, think about modifying your for like this:

for(int i=0; i < tweetLength - 1; i++)

and removing the first if. We are doing that anyway but just in a more complicated way, right? :)

AlinG
  • 451
  • 3
  • 12