StringIndexOutOfBoundsException - java

This program I'm making isn't compiling right, I keep getting the error:
Exception in thread "main" java.lang.StringIndexOutOfBoundsException: String index out of range: -9
at java.lang.String.charAt(String.java:687)
at pro1.main(pro1.java:161)
Here's my code:
import java.io.*;
import java.util.*;
public class pro1 {
static String str="";
static String str1="";
static int range=250;
static int length;
static String key="";
static String ep="";
static String pt="";
static char temp;
static int t,p,h;
static int r,x,y,z,w;
static Random generator = new Random();
static public String getContents(File aFile)
{
StringBuilder contents = new StringBuilder();
try {
BufferedReader input = new BufferedReader(new FileReader(aFile));
try {
String line = null;
while (( line = input.readLine()) != null){
contents.append(line);
contents.append(System.getProperty("line.separator"));
}
}
finally {
input.close();
}
}
catch (IOException ex){
ex.printStackTrace();
}
str1=contents.toString();
return str1;
}
public static void main (String args[]) throws IOException {
File testFile = new File("/home/amritha/Desktop/sam.txt");
System.out.println("Original file contents: " + getContents(testFile));
System.out.println("message:"+str1);
String sbox="abcdefghijklmnopqrstuvwxyz";
length=str1.length()-1;
for(int i=0;i<length;i++)
{
t=(int)str1.charAt(i);
if(t==32)
{
int t1=32;
temp=(char)t;
}
else
{
range=generator.nextInt(26)+1;
temp=sbox.charAt(range);
}
key+=""+temp;
}
System.out.println("Key:"+key);
for(int i=0;i<length;i++)
{
t=(int)str1.charAt(i);
{
if(t==32)
{
t=32;
temp=(char)t;
}
else
{
t-=97;
}
}
p=(int)key.charAt(i);
{
if(p==32)
{
p=32;
temp=(char)p;
}
else
{
p-=97;
}
}
if((t==32)&&(p==32))
{
int v=32;
temp=(char)v;
}
else
{
r=(t+p)%26;
temp=sbox.charAt(r);
}
ep+=""+temp;
}
System.out.println("Encrypted Text:"+ep);
for(int i=0;i<length;i++)
{
y=(int)ep.charAt(i);
{
if(y==32)
{
y=32;
temp=(char)y;
}
else
{
y-=97;
}
}
x=(int)key.charAt(i);
{
if(x==32)
{
x=32;
temp=(char)x;
}
else
{
x-=97;
}
}
if((x==32)&&(y==32))
{
int w=32;
temp=(char)w;
}
else
{
z=(y-x)%26;
temp=sbox.charAt(z);
}
pt+=""+temp;
}
System.out.println("deccrypted Text:"+pt);
}
}

Your code looks fishy in every way, and I cannot imagine anyone wanting to read 170 lines of this code.
Look at the exception: It tells you exactly what's going wrong: You pass -9 to charAt() as an index, which is - obviously - out of range, as you should only pass 0 ... (length-1) in there.
And it gives you the line number, too... so go to line number 161 and look what's in there and how it got there.

My guess would be it has something to do with this line:
z=(y-x)%26;
If x is larger than y the result of the % operation may be negative (or 0). And charAt (which is what z is given as parameter to) expects a positive value.
You should try:
z=Math.abs(y-x)%26;
Edit: As a side note, this shouldn't be to hard to figure out on your own, by looking at the exception as was pointed out by others, or in the worst case using a debugger and seeing exactly what values the different variables have and why when the exception occurs.

Related

use a method to read numbers from a text file and return the prime numbers

the question says: Create a class named HW09. In this class implement a method named primeCounter
with the following signature, that takes a file name as string (for example “numbers.txt”) and returns the number of prime numbers in the text file. Assume the text file only contains integer numbers.
I tried to build the code for the program But I keep getting these error messages and I'm not sure how to fix them and get the program running again. My knowledge of the file access concept is very weak and my professor is horrible. I hope someone can help me understand what went wrong
import java.io.*;
import java.util.Scanner;
class HW09 {
public static int primeCounter(String fileName) throws IOException {
int count= 0;
int number;
String x= null;
File filename= new File("C:/Users/black/Desktop/file.txt");
Scanner s = new Scanner(filename);
BufferedReader data= null;
data= new BufferedReader (new FileReader(filename));
while (s.hasNextInt()) {
number= Integer.parseInt(x);
int see=0;
for (int i =1; i<=number; i++) {
if (number%i==0) {
see = see+1;
}
if (see>2) {
break;
}
}
if (see==2) {
count = count+1;
}
}
return count;
}
public static void main (String args []) {
try {
String file= ("C:/Users/black/Desktop/file.txt");
System.out.println(HW09.primeCounter(file));
}
catch (IOException e) {
System.out.println("Couldn't find file! ");
}
}
}
I see a number of issues with your current code, first and foremost is the lack of separation of concerns. I would start with a simple method to determine if a single number is prime. I wrote such a method here, and that looks like
private static boolean isPrime(int n) {
if (n == 2) {
return true;
} else if (n == 1 || n % 2 == 0) {
return false;
}
for (int i = 3; i * i <= n; i += 2) {
if (n % i == 0) {
return false;
}
}
return true;
}
Then you want to read numbers with your Scanner. And check if they are prime. And don't forget to close the Scanner when you're done. Using a try-with-resources takes care of that. Like,
public static int primeCounter(String fileName) throws IOException {
int count = 0;
try (Scanner s = new Scanner(new File(fileName))) {
while (s.hasNextInt()) {
int v = s.nextInt();
if (isPrime(v)) {
count++;
}
}
}
return count;
}
Finally, when constructing a path, it's better to use the system properties to get the home folder. That way, it can work on other people's machines more easily,
public static void main(String args[]) {
try {
String file = new File(
System.getProperty("user.home"), "Desktop/file.txt").getPath();
System.out.println(primeCounter(file));
} catch (IOException e) {
System.out.println("Couldn't find file! ");
}
}
And I created a file to test against,
$ cat ~/Desktop/file.txt
13
11
7
5
3
2
4
After running the program I get, as expected,
6

How to find an index of given String in array of strings?

Surely the solution to this is the following:
public long myFunc(String name) throws Exception {
for(int i=0;i<amount;i++){
if(this.otherString[i].equals(name))
return longArray[i];
}
throw new Exception("Not found");
}
However, this does not seem to be the case.
You can use Guava, then your code can looks like this
String[] stringArray = {"s1", "s2", "s3"};
int index = Iterators.indexOf(Iterators.forArray(stringArray), new Predicate<String>() {
#Override
public boolean apply(String input) {
return input.equals("s2");
}
});
or simpler
int index = Arrays.asList(stringArray).indexOf("s2");
Your code can also look like this
public class Finder {
private String[] stringArray = {"s1", "s2", "s3"};
public int findIndex(String name) {
for (int i = 0; i < stringArray.length; i++) {
if (stringArray[i].equals(name))
return i;
}
throw new RuntimeException("Not found");
}
public static void main(String... s) {
int index = new Finder().findIndex("s1");
System.out.println(index);
}
}
You can either run your code through a debugger and find out why it doesn't work, or add some println traces to your original code and you'll see what the problem is:
public long myFunc(String name) throws Exception {
System.out.println("Looking for: " + name);
for (int i = 0; i < amount; i++){
if(this.otherString[i].equals(name))
return longArray[i];
System.out.printf("%4d: \"%s\": No match.%n", i, this.otherString[i]);
}
for (int i = amount; i < this.otherString.length; i++)
System.out.printf("%4d: \"%s\": Not checked.%n", i, this.otherString[i]);
throw new Exception("Not found");
}
By the way, make sure you are correctly interpreting the method's behaviour. Could it be that it's finding it but throwing an ArrayIndexOutOfBoundsException because i is greater than longArray.length, and you misinterpret that as the exception you are explicitly throwing?
Turns out '\u0000' was at the end of the string that was meant to be equal. This does not show in printing. Next time I will be more ruthless in the inspection of the debugging. Thank you for all the suggestions though, and sorry for wasting your time.
This might be completely wrong, but isn't the problem just missing curly brackets in the if statement? I am new to the java language and the example is probably messy, but it uses the same structure from your question and works just fine:
public class random_class {
public static void main(String[] args) {
// TODO Auto-generated method stub
String[] a = new String[] {"hi!", "hello world!", "ho ho ho world!"};
int b = getHWIndex(a);
System.out.println(b);
}
public static int getHWIndex(String[] stringArray){
int i;
Boolean test = false;
for(i=0;i<stringArray.length;i++){
if(stringArray[i].equals("hello world!")){
test = true;
break;
}
}
if(test == true){
return i;}else{
return i = 0; // this is not a good answer...
//but as you return an int I could not think on a quick way to fix the return when there is no match.
}
}
}

Getting wrong answer from Uva judge for the 3n+1problem

I tried to submit the 3n+1 problem several time but failed to get it accepted on the Uva judge.I wrote the program in java.Can anyone point out the mistake in my program.
Problem statement:-
https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=29&page=show_problem&problem=36
My program:-
import java.io.*;
import java.util.*;
class Main
{
static String ReadLn (int maxLg) // utility function to read from stdin
{
byte lin[] = new byte [maxLg];
int lg = 0, car = -1;
String line = "";
try
{
while (lg < maxLg)
{
car = System.in.read();
if ((car < 0) || (car == '\n')) break;
lin [lg++] += car;
}
}
catch (IOException e)
{
return (null);
}
if ((car < 0) && (lg == 0)) return (null); // eof
return (new String (lin, 0, lg));
}
public static void main (String args[]) // entry point from OS
{
Main myWork = new Main(); // create a dinamic instance
myWork.Begin(); // the true entry point
}
void Begin()
{
String input;
while((input=Main.ReadLn(255))!=null){
StringTokenizer str=new StringTokenizer(input);
int n1=Integer.parseInt(str.nextToken());
int n2=Integer.parseInt(str.nextToken());
int max=0;
for(int i=n1;i<=n2;i++)
{
int no=calculate(i,0);
if(max<no){
max=no;
}
}
System.out.println(n1+" "+n2+" "+max);
}
}
static int calculate(int a,int sum){
if(a==1)
{
return sum+1;
}
else if(a%2==0)
{
sum+=1;
return calculate(a/2,sum);
}
else
{
sum+=1;
return calculate((3*a+1),sum);
}
}
}
I am very sorry for bad indentation of my code.
I think the problem is with the input/output. The code in your question reads one line and then prints one line. The input/ouput on the UVa page specifies to use a "series" for input and use "for each" as ouput. In other words: read all the input lines, calculate, and then write all the output lines.
Here is some code to help you read all the input-lines (the ReadLn method in your question looks overly complicated):
public static List<int[]> readCycleRanges() throws Exception {
List<int[]> cycleRanges = new ArrayList<>();
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String line = br.readLine();
while (!(line == null || line.trim().length() == 0)) {
StringTokenizer st = new StringTokenizer(line, " ");
int i = Integer.valueOf(st.nextToken());
int j = Integer.valueOf(st.nextToken());
cycleRanges.add(new int[] { i, j, 0 });
line = br.readLine();
}
return cycleRanges;
}
I got it accepted by UVa judge. The problem was didn't considered that the second number can be smaller than the first number. You have to consider that case in which the second number is the starting of the series.

Array omitting lines in one part of code, but showing it in another

So I'm creating an String[] and in this section of code I miss the lines of code I'm checking for!
*Please note: I do know this is not the best approach for checking, but this is just a "proof of concept" and will be changed later on. Anyway, here is the code that gives me the problem:
private void checkMethods() {
for (int i = 0; i < array.length; i++) {
String s = array[i];
System.out.println(s);
if(array[i].contains("onEnable()")) {
System.out.println("enable");
array[i] = MethodUpdate.onEnable;
}
else if (isOnDisable(s)) {
System.out.println("disable");
array[i] = MethodUpdate.onDisable;
}
else if (isOverride(s)) {
if (checkNextLine(array[i++])) {
array[i] = "";
}
}
}
}
Now this returns the following:
public class DummyBukkitClass extends JavaPlugin {
#Override
// Some Profound code can be found here
}
#Override
// The Profound code is now ending =(
}
}
However in the following code it returns what I need it too:
public void updateFile(File file) throws IOException {
BufferedReader br = null;
pw = null;
try {
br = new BufferedReader(new FileReader("classes/DummyBukkitClass.java"));
file.getParentFile().mkdirs();
pw = new PrintWriter(file);
String line;
int index = 0;
while ((line = br.readLine()) != null) {
array[index] = line;
index++;
}
} finally {
checkMethods();
for (int i = 0; i < array.length; i++) {
System.out.println(array[i]);
pw.println(array[i]);
}
br.close();
pw.flush();
pw.close();
}
}
Now this returns:
public class DummyBukkitClass extends JavaPlugin {
#Override
public void onEnable() {
// Some Profound code can be found here
}
#Override
public void onDisable() {
// The Profound code is now ending =(
}
}
I'm just stumped as to why the 1st one is omitting 2 lines, while i call it right after they are there! They are able to be printed all throughout the adding process; and I can print them before the checkMethods() is called. Please help!
Thanks you!
EDIT:
To fix the problem I needed to change:
else if (isOverride(array[i])) {
if (checkNextLine(array[i++])) {
array[i] = "";
}
}
In checkMethods() to:
else if (isOverride(array[i])) {
if (checkNextLine(array[i+1])) { //HERE
array[i] = "";
}
}
The reason behind that is this: I was increasing the size of 'i' then using that 'i' again without resetting it. 'i+1' fixes that because you are not setting a new value to i.
Change checkNextLine(array[i++]) to checkNextLine(array[i + 1]) or it will skip lines.
You increment the counter i in the first sample without outputting the line:
else if (isOverride(s)) {
if (checkNextLine(array[i++])) {
array[i] = "";
}
}

Find test-case for which code does't work

I submitted one code in code chef but it's giving wrong answer even if it's correct
can anybody help me to identify that please.
I have tried so many inputs and calculated manually and they are correct so why they gave me wrong answer.
so,anybody who can find the TEST Case which give incorrect output by this code ?.
Here is Problem definition.
import java.util.Scanner;
import java.lang.Math;
class Codechef {
static int get(int n,int i,int digit)
{
int p;
p=(int)Math.pow(10,i-1);
n=n/p;
return n%10;
}
static boolean check_pal(int n)
{
int digit;
digit=(int) (Math.log10(n)+1);
int a=0,b=0,i,j,p;
int sum=0;
for(i=1,j=digit-1 ; i<=digit ; i++,j-- )
{
a=get(n,i,digit);
sum+=a*Math.pow(10,j);
}
if(sum==n)
return true;
else
return false;
}
static int reverse(int n)
{
int digit;
digit=(int) (Math.log10(n)+1);
int a=0,b=0,i,j,p;
int sum=0;
for(i=1,j=digit-1 ; i<=digit ; i++,j-- )
{
a=get(n,i,digit);
sum+=a*Math.pow(10,j);
}
return n+sum;
}
public static void main(String[] args) {
try{
Scanner sc=new Scanner(System.in);
int n=sc.nextInt();
if(n<10 || n>999){
System.out.println("NONE");
return;
}
boolean c;
for(int i=1 ; i<=100 ; i++)
{
c=check_pal(n);
if(c==true)
{
System.out.println(n);
return;
}
n=reverse(n);
}
System.out.println("NONE");
}
catch(Exception e)
{
System.out.println("NONE");
}
}
}
Here is one more output.
for 99 it gives 99 and which is correct as it's palindrome.
For 89 (or 98 for that matter), your code returns "NONE", although you reach the answer 8813200023188 after only 24 steps.
Another case is that for 177 and 276 you should get 8836886388 instead of NONE
I didn't debug your code, I just wrote a program that does the same, and compared the output my program gave to the one your program gave. Since you just requested a testcase, that should suffice :) My gutfeeling is that you overflow... an int is not large enough to hold the answer in all cases.
Happy bughunting.
Edit (on Request) with my code.
I didn't change your code, except that I extracted your logic into a getResult(integer) methode so that I could bypass the scanning of the input and simply return a string as result. It prints out all the differences between our versions. I used BigInteger as the type to hold my results.
public class Main {
public static void main(String[] args) {
Main m = new Main();
for (int i=10; i < 1000; i++) {
String myResult = null;
String hisResult = null;
try {
myResult = m.getResultAsString(i);
} catch (Exception e){
System.out.println("Your code threw an exception for " + i);
}
try{
hisResult = Codechef.getResult(i);
} catch (Exception e){
System.out.println("His code threw an exception for " + i);
}
if (myResult != null && hisResult != null && ! myResult.equals(hisResult)) {
System.out.println("For " + i + " you have " + myResult + " but he has " + hisResult);
}
}
}
public String getResultAsString(int inputNumber) {
BigInteger res = getResultAsBigInteger(new BigInteger(""+inputNumber));
if (res != null) {
return res.toString();
} else {
return "NONE";
}
}
public BigInteger getResultAsBigInteger(BigInteger inputNumber) {
int numberOfSteps = 0;
BigInteger currentValue = inputNumber;
while (numberOfSteps < 101 && ! isPalindrome(currentValue)) {
numberOfSteps++;
currentValue = currentValue.add(reverseDigits(currentValue));
}
return numberOfSteps < 101 ? currentValue : null;
}
public boolean isPalindrome(BigInteger number) {
return number.equals(reverseDigits(number));
}
public BigInteger reverseDigits(BigInteger input) {
String inputString = input.toString();
String output = "";
for (int i = inputString.length() - 1; i >= 0; i--)
{
output += inputString.charAt(i);
}
return new BigInteger(output);
}
}
There is an overflow error in your code.
for input 89 it's not working as #Yves V. said
Suggestion is to use BigInteger class of lang.Match it will be useful to eliminate this overflow error.

Categories

Resources