Getting java.lang.ArrayIndexOutOfBoundsException, looked, cannot find an example thats the same - java

I am writing a "tweet checker" code for my AP Computer Science Class. The code is supposed to check that the length of the tweet is within the 140 character limit and, if so, prints the amount of hashtags, #, and links used. I am using the .split method to put all the characters into an array, and then I am accessing the array with for loops to find the specific characters.
I keep encountering a java.lang.ArrayIndexOutOfBoundsException, which I know means that I am trying to access a nonexistent element in my string, such as element 46 for an array of 46 characters, but I do not know what the exact problem is here. I got harped on last time for not "looking hard enough" but I have searched for over 2 hours on only this subject, and I am simply a high school student.
I appreciate all the help.
import java.util.Scanner;
import java.lang.Math;
class Main{
public static void main(String[] args)
{
Scanner scan = new Scanner (System.in);
System.out.println("Please enter a tweet:");
String tweet = scan.nextLine();
int length = tweet.length ();
String[] tweetArray = tweet.split ("");
int c = 0;
int d = 0;
int e = 0;
int i = 0;
if (length > 140)
System.out.println("Excess Characters: " + (length - 140));
else
{
System.out.println("Length Correct");
for (i = 0; i < length; i++)
{
if (tweetArray[i].equals("#"))
{
if(!tweetArray[i+1].equals(" "))
{
c++;
}
}
}
System.out.println("Number of Hastags: " + c);
for (i = 0; i < length; i++)
{
if (tweetArray[i].equals("#"))
{
if(!tweetArray[i+1].equals(" "))
{
d++;
}
}
}
System.out.println("Number of Attributions: " + d);
for (i = 0; i < length; i++)
{
if((tweetArray[i].equals("h")) || (tweetArray[i].equals("H")))
{
if(tweetArray[i+1].equals("t") || tweetArray[i+1].equals("T"))
{
if(tweetArray[i+2].equals("t") || tweetArray[i+2].equals("T"))
{
if(tweetArray[i+3].equals("p") || tweetArray[i+3].equals("P"))
{
if(tweetArray[i+4].equals(":"))
{
if(tweetArray[i+5].equals("/"))
{
if(tweetArray[i+6].equals("/"))
{
if(!tweetArray[i+7].equals(" "))
{
e++;
}
}
}
}
}
}
}
}
}
System.out.println("Number of Links: " + e);
}
}
}

In your for loop, i correctly iterates from 0 to the maximum length. However you have code such as:
tweetArray[i+1]
...
tweetArray[i+7]
that will fail once i reaches (or gets close to) its maximum. That is, you are referencing past the end of the array.
In general, if you need to check something about the next character, you need to check that it exists first (as you only know that the current character exists).
You may wish to review your whole approach though. There does not appear to be any need to split your string into characters. You could instead use string based functions to count the number of # characters or check for the presence of a string (eg. http://). Check out the API.

Related

Trying to find the numbers in a line of user input, and then save them to an array stack

For this problem, I am working on finding numbers within a formula (ex. 60 / 30) and save them to a stack. I am currently using the .isDigit method to determine whether a character is a digit or not, and then am checking each character after it to see if it is a multi-digit number or not (ex. 600 or 34). I use a substring method to cut each number from the formula and then a push method obviously to save it into the arraystack. I'm getting index out of bounds errors and don't know where I went wrong. here is the code:
public static void main (String[]args) {
System.out.println("input your formula ");
Scanner scan = new Scanner (System.in);
String input;
input = scan.nextLine();
scan.close();
System.out.println("input: " + input);
ArrayStack st = new ArrayStack();
for(int j = 0; j < input.length(); j++) {
if (Character.isDigit(input.charAt(j))) {
int cur = 0;
while (input.charAt(j + cur) != ' ') {
cur += 1;
String number = input.substring(j,cur);
st.push(number);
break;
}
}
}
while (!st.isEmpty())
{
System.out.println(st.peek());
st.pop();
}
}
}
I tried and expected to get the numbers out of the formula and put them into a stack, then print them out.

Assigning Partners (From CCC competition)

The CEMC is organizing a workshop with an activity involving pairs of students. They decided to assign
partners ahead of time. You need to determine if they did this consistently. That is, whenever A is a partner
of B, then B is also a partner of A, and no one is a partner of themselves.
Input
The input consists of three lines. The first line consists of an integer N (1 < N ≤ 30), which is the number of
students in the class. The second line contains the first names of the N students separated by single
spaces. (Names contain only uppercase or lowercase letters, and no two students have the same first
name). The third line contains the same N names in some order, separated by single spaces.
The positions of the names in the last two lines indicate the assignment of partners: the i-th name on the
second line is the assigned partner of the i-th name on the third line.
Output
The output will be good if the two lists of names are arranged consistently, and bad if the arrangement of
partners is not consistent.
Sample Input 1
4
Ada Alan Grace John
John Grace Alan Ada
Sample Output 1
good
Explanation for Sample 1
Ada and John are partners, and Alan and Grace are partners. This arrangement is consistent.
Sample Input 2
7
Rich Graeme Michelle Sandy Vlado Ron Jacob
Ron Vlado Sandy Michelle Rich Graeme Jacob
Sample Output 2
bad
Explanation for Sample 1
Graeme is partnered with Vlado, but Vlado is partnered with Rich. This is not consistent. It is also
inconsistent because Jacob is partnered with himself.
Here is my work, I wonder why it doesn't work???
import java.util.Scanner;
public class CCCHW4 {
public static void main(String[] args) {
Scanner reader = new Scanner(System.in);
int n = reader.nextInt(); //how many names
String [][] combo = new String [2][n];
double value = 0;
combo [0] [0] = reader.nextLine();
for (int i = 0; i < n; i++) { //input the names
combo [0] [i] = reader.nextLine();
}
combo [1] [0] = reader.nextLine();
for (int j = 0; j < 4; ++j) { //input the names
combo [1] [j] = reader.nextLine();
}
for (int i = 0; i < n++; ++i) {
if ((combo [0][i]).equals(combo [1][i])) { //check if partner with himself/herself
System.out.println(" same " + combo [0][i] + combo [1][i]);
System.exit(0);
}
}
for (int i = 0; i < n; ++i) { //each combo
for (int j = 0; j < n; ++j) { // each column
int determineValue = 0; //determine if any guy partnered with more than one person
if ((combo [0] [i]+combo [1] [i]).equals(combo [0] [j]+combo [1] [j]) || //check, if partner with two person
(combo [0] [i]+combo [1] [i]).equals(combo [1] [j]+combo [0] [j])) {
determineValue += 1;
}
if (determineValue != 2) { //same combo one time, reversed combo one time, so two.
value += 1;
System.out.println("yes2");
}
}
}
if (value == 0) {
System.out.print("good");
} else {
System.out.print("bad");}
}
}
Below is my solution to your homework exercise.
I first ran a few tests by hand and realized that the program output can never be GOOD if there are an odd number of students, so I added a condition that the entered number of students must be an even number.
My algorithm is to use two, separate, one dimensional arrays rather a single, two dimensional array. I loop through the second array (partners in the below code) and for each "partner", I search the first array (students in the code below) for that "partner". If I find the "partner" in the students array then I check whether the pairs are the same. As soon as I fail to find a matching pair, I exit the loop and the program prints BAD.
Note that I only need to search half of the partners array since if I find matches for all the students in the first half of the array, then the second half must all have matches also.
Also note that I added a lot of checks for valid input, including ensuring that the entered number of students is a positive integer, i.e. not a number with a decimal point or a minus sign. I also check that the correct number of names are entered and that each list of names contains only unique names, i.e. the same name cannot appear more than once in a list. The user is asked to re-enter invalid data, repeatedly, until [s]he enters valid data, i.e. a correct number of students and correct lists of names.
Lastly note that I check the validity of the parameters in methods getNames() and getNumberOfStudents(). I feel it is important since I always remind myself that the Ariane 5 rocket failed because the software did not check the validity of method parameters.
import java.util.HashSet;
import java.util.Objects;
import java.util.Scanner;
import java.util.Set;
public class Pairings {
public static void main(String[] args) {
Scanner stdin = new Scanner(System.in);
int numberOfStudents = getNumberOfStudents(stdin);
String[] students = getNames(stdin, numberOfStudents);
String[] partners = getNames(stdin, numberOfStudents);
int limit = numberOfStudents / 2;
boolean bad = false;
for (int i = 0; i < limit; i++) {
boolean found = false;
for (int j = 0; j < numberOfStudents; j++) {
if (i != j) {
if (students[j].equals(partners[i])) {
if (partners[j].equals(students[i])) {
found = true;
break;
}
}
}
}
if (!found) {
bad = true;
break;
}
}
if (bad) {
System.out.println("BAD");
}
else {
System.out.println("GOOD");
}
}
private static String[] getNames(Scanner stdin, int number) {
if (number <= 0) {
throw new IllegalArgumentException("Not positive: " + number);
}
Objects.requireNonNull(stdin, "Null scanner.");
String[] names = new String[0];
int count = 0;
do {
System.out.printf("Enter %d unique names (separated by single space)%n", number);
String str = stdin.nextLine();
names = str.split("\\s+");
count = names.length;
if (count != number) {
System.out.printf("You entered %d names and not %d%n", count, number);
}
else {
Set<String> nameSet = new HashSet<String>(number);
for (String name : names) {
if (nameSet.contains(name)) {
System.out.printf("%s appears more than once%n", name);
count = 0;
break;
}
else {
nameSet.add(name);
}
}
}
} while (count != number);
return names;
}
private static int getNumberOfStudents(Scanner stdin) {
Objects.requireNonNull(stdin, "Null scanner.");
String str;
int numberOfStudents;
do {
System.out.print("Enter number of students (even number between 2 & 30): ");
str = stdin.nextLine();
try {
numberOfStudents = Integer.parseInt(str);
if (numberOfStudents < 0) {
System.out.printf("%d is a negative number%n", numberOfStudents);
}
else if (numberOfStudents % 2 == 1) {
System.out.printf("%d is not an event number%n", numberOfStudents);
}
}
catch (NumberFormatException xNumFmt) {
System.out.printf("%s is not a whole number%n", str);
numberOfStudents = 1;
}
} while (numberOfStudents % 2 == 1);
return numberOfStudents;
}
}

I have to make a tweet tester in java, but can't figure out how to count the amount of times a character shows up in the tweet

Alright, so for a class I am taking I have to make a program that tests tweets. It asks you to input a tweet, then tells you if the tweet is valid (less than 140 characters), tells you the amount of mentions (indicated by the character #) and the number of hashtags (indicated by a #), and tells you whether or not it is a retweet (if it contains "RT:" it is considered a retweet).
I can tell whether it is a valid tweet and can tell if it is a retweet (I coded it so that if the index of "RT:" is greater than or equal to 0, it says it is a retweet), but can't figure out how to count the number of # and # in the string the user enters. I know how to find the index, but am having trouble finding out where to go from there. I don't know what to do as a next course of action. Is there a way to count the amount of a certain character in a string?
I know what the code is currently doing, outputting the index of the first time the character shows up, but I am lost on what else I could do. I thought that maybe I could truncate every letter before and including the # and use a loop to count the amount of times that I get an index for #, then do the same for the #, but I don't know how to truncate every letter before and including a certain character. Or is there a better option? Any help is appreciated
import java.util.Scanner;
import java.lang.Math;
public class Main {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
System.out.println("Please enter a tweet:");
String s = scan.nextLine();
int length = s.length();
if(length > 140)
System.out.println("Excess Characters: " + ( length - 140));
else{
System.out.println("Length Correct");
int at = s.indexOf('#');
System.out.println("Number of Mentions: " + (at));
int hash = s.indexOf('#');
System.out.println("Number of Hashtags: " + (hash));
if (s.indexOf("RT:") >=0)
System.out.println("The input was a retweet.");
else
System.out.println("The input was not a retweet.");
}}}
.indexOf will return the index of that character in your String.
That might not be the best approach to resolve your problem.
You could do something like this :
for(int i=0; i<s.length(); i++) {
if(s.charAt(i) == '#') {
count++; //or whatever mechanism you want to keep track of those chars.
}
}
Improving slightly on Caleb's answer:
Since you know which two characters you need to count, '#' and '#,' you can have a counter for each and just iterate over the tweet once. Then you just check if a character is one you're looking for, and if it is, the counter is incremented!
int mentions = 0;
int hashtags = 0;
for(int i = 0; i < s.length; i++) {
if(s.charAt(i) == '#') {
mentions++;
} else if(s.charAt(i) == '#') {
hashtags++;
}
}
Now mentions and hashtags should have the countes of #'s and #'s respectively.
You can solve this problem by implementing a simple counting method:
public int charCount(char c, String tweet) {
int count = 0;
for(int i = 0; i < tweet.length()) {
if(tweet.charAt(i) == c) count++;
}
return count;
}
With this, you can count the number of times a character appears in a tweet.
System.out.println("Length Correct");
int at = charCount('#', s);
System.out.println("Number of Mentions: " + at);
int hash = charCount('#', s);
System.out.println("Number of Hashtags: " + hash);
if (s.indexOf("RT:") >= 0)
System.out.println("The input was a retweet.");
else
System.out.println("The input was not a retweet.");

How do I sort an array ignoring capitalization?

I use sort() to sort my array alphabetically, but it does so from A-Z to a-z. I try to capitalize each word beforehand, but it doesn't work unless it's being printed out, which should be happening after the sorting. At the moment, with this code, it will list the pupils with capital letters, but if it was inputted as lowercase, it will be sorted as lowercase. Putting the capitalize() in the initial for loop, right after assigning the input to the array, doesn't work. Any solutions?
import java.util.Scanner;
import java.util.Arrays;
public class Pupils {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
boolean loop = true;
int names = 0;
String[] ay = new String[1000];
for(int i = 0; loop == true; i++) {
System.out.println("Enter name: ");
ay[i] = scan.nextLine();
names++;
if (ay[i].equals("0")) {
loop = false;
ay[i] = " ";
}
}
String[] aay = new String[names - 1];
for(int i = 0; i < aay.length; i++) {
aay[i] = ay[i];
}
if (names == 1) {
System.out.print("There are no people in our class.");
} else if (names == 2) {
System.out.print("The person in our class is ");
} else {
System.out.print("The people in our class are ");
}
Arrays.sort(aay);
for(int i = 0; i < names - 1; i++) {
if(i == names - 2) {
System.out.print(capitalize(aay[i]) + ".");
} else if (i == names - 3) {
System.out.print(capitalize(aay[i]) + " and ");
} else {
System.out.print(capitalize(aay[i]) + ", ");
}
}
}
public static String capitalize(String line)
{
return Character.toUpperCase(line.charAt(0)) + line.substring(1);
}
}
What about using Arrays.sort() with a Comparator? Note that there is a suitable comparator defined in String, so:
Arrays.sort(aay, String.CASE_INSENSITIVE_ORDER);
should do the job.
I suggest storing all the data in the array in lowercase. It will simplify sorting as well as search (if you search for a student in the array, and it was entered as, say "Walter" and you are looking for "walter", you won't find it. If you use lowercase both for storage and for search, it will work).
And since you capitalize the names for printing anyway, the names will still be displayed capitalized.
So instead of doing
ay[i] = scan.nextLine();
You can do:
ay[i] = scan.nextLine().toLowerCase();

out of bounds error with word count

I'm trying to write my own Java word count program. I know there may already be a method for this, but I'd like to get it work. I'm getting an out of bounds error at line 14. I'm trying to use an input word to count how many times it appears in an input string. So I'm looping up to stringlength - wordlength, but that's where the problem is.
Here is the code:
import java.util.Scanner;
public class wordcount {
public static void main(String[] args)
{
Scanner s = new Scanner(System.in);
System.out.print( "Enter word : " );
String word = s.nextLine();
Scanner t = new Scanner(System.in);
System.out.print("Enter string: ");
String string = t.nextLine();
int count = 0;
for (int i = 0; i < string.length()-word.length(); i = i+1){
String substring = string.substring(i,i+word.length());
if (match(substring, word)==true){
count += 1;
}
}
System.out.println("There are "+count+ " repetitions of the word "+word);
}
public static boolean match(String string1, String string2){
for (int i=0; i<string1.length(); i+=1){
if (string1.charAt(i)!=string2.charAt(i)){
return false;
}
}
return true;
}
}
First of all, two Scanners are not necessary, you can do many inputs with the same Scanner object.
Also, this if condition
if (match(substring, word) == true)
can be rewritten like
if (math(substring, word))
I would also recommend you to use i++ to increase the loop variable. Is not strictly necessary but is "almost" a convention. You can read more about that here.
Now, about theIndexOutOfBoundsException, I've tested the code and I don't find any input samples to get it.
Besides, there is an issue, you are missing one iteration in the for:
for (int i = 0; i < string.length() - word.length() + 1; i++) { // Add '+ 1'
String substring = string.substring(i, i + word.length());
// System.out.println(substring);
if (match(substring, word)) {
count++;
}
}
You can test it by putting a print statement inside the loop, to print each substring.
I'm not getting an out of bounds error, can you tell me what values you were using for word and string?
I have identified a bug with your program. If word is equal to string, it still returns count 0. I suggest adding one more iteration and using regionMatches instead. RegionMatches makes your match method obsolete and will return false if word.length() + i is equal or greater than string.length(), avoiding out of bounds issues.
As you can see I also moved the calculations to a seperate method, this will make your code more readable and testable.
And as Christian pointed out; you indeed do only need one Scanner object. I've adapted the code below to reflect it.
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.print("Enter word : ");
String word = sc.nextLine();
System.out.print("Enter string: ");
String string = sc.nextLine();
int count = calculateWordCount(word, string);
System.out.println("There are " + count + " repetitions of the word " + word);
}
private static int calculateWordCount(String word, String string) {
int count = 0;
for (int i = 0; i < string.length() - word.length() + 1; i++) {
if (word.regionMatches(0, string, i, word.length())) {
count++;
}
}
return count;
}

Categories

Resources