Java String.substring returning empty string - java

I'm trying to run the following code
int[] sbox = new int[256];
String inputString = "Thisisanexample";
String sTemp;
char cTmp;
int intLength = inputString.length();
for (a = 0; a <= 255; a++)
{
sTemp = inputString.substring(a % intLength, 1);
ctmp = sTemp.toCharArray()[0];
sbox[a] = (int)ctmp;
}
Every time i run the code I get a java.lang.ArrayIndexOutOfBoundsException when the counter variable = 1. Checking the code in the debugger, it appears the substring is returning an empty string when it should be returning the second character in the inputString.
Can anyone advise why this would be the case?

String.substring() expects a start and a end index, not the length. So you need to add the length to the start index:
for (a = 0; a <= 255; a++)
{
int index = a % intLength;
sTemp = inputString.substring( index, index + 1 );
ctmp = sTemp.toCharArray()[0];
sbox[a] = (int)ctmp;
}
You can also avoid the creation of sub strings in this case. This would give you the same results:
for (a = 0; a <= 255; a++)
{
ctmp = inputString.charAt(a % intLength);
sbox[a] = ctmp;
}

If in doubt check the javadoc this shows you that substring() does not do what you think it does...

When you use the debugger, you can see that the first time round the loop, you get one character and the second time you get no characters.
That is because String.substring(int start, int end) takes the end, not the length.
BTW: You can just write
int[] sbox = new int[256];
String inputString = "Thisisanexample";
for(int i = 0; i < sbox.length; i++)
sbox[i] = inputString.charAt(i % inputString.length());

String.substring(begining, endIndexExclusive)
when a=1, beginIndex=1, endIndexExclusive=1 =>
sTemp == "" =>
toCharArray() returns empty array =>
[0] indexOutOfBounds

Related

Storing Reverse String in 2D Array

I am trying to get the contents of a string, and store it in the last row of my 2D array here is what I have so far:
char[][] square = new char[5][5];
String number = new String("three");
for(int k = number.length() - 1; k >= 0; k--)
{
square[4][k] = number.charAt(k);
}
The output the code is giving me is the string in non reversed order.
Isn't this the logic for reversing a string? All I am doing here is setting the fourth column, and all rows starting at the end of the string to it's value. What am I missing?
Thanks
just walk through the loop by hand.
The first time through, k is 4.
So, square[4][4] is set to the character returned by .charAt(4), which is an 'e'.
then square[4][3] becomes 'e', ... and square[4][0] becomes 't'.
square[4] now reads t,h,r,e,e.
You've basically reversed both ends. Try this:
for (int k = 0; k < number.length(); k++) {
square[4][k] = number.charAt(number.length() - k - 1);
}
Yes, because you're not reversing it. You're setting the same character back again at the same position. If you need it reversed then the logic should be
square[4][number.length() - (k + 1)] = number.charAt(k);
You need a different index beyond square[4][k] when you are also copying the value from number.charAt(k) - that is, you are copying the characters backwards (but into the array also backward). There is no need to call new String(String). You could do
char[][] square = new char[5][5];
String number = "three";
for (int i = 0; i < number.length(); i++) {
int k = number.length() - i - 1;
square[4][k] = number.charAt(i);
}
But I would prefer a StringBuilder and StringBuilder.reverse() myself. Like,
char[][] square = new char[5][5];
String number = "three";
square[4] = new StringBuilder(number).reverse().toString().toCharArray();

How to define number sequence in string?

I have a task to create a string with a non-defined length (input digits from the keyboard until the user presses "Enter"), then I have to define how many of digits are in sequence. Unfortunately I can't handle this. I think I'm almost there but I'm not. I've created the string which I hoped to copy character by character to an array and then compare each digit with the next one, but I have trouble with copying characters into an array.
Here's my code:
int sum = 0;
String someSymbols = sc.nextLine();
int array [] = new int[someSymbols.length()];
for(int i=0; i<someSymbols.length(); i++){
for (int j=0; j<=array.length; j++){
array[j] = someSymbols.charAt(i);
}
sum++;
}
Not sure of what you want to achieve but here are 2 examples for inspiration:
Taking digits until reaching a different digit. Ignoring non digits
String s = "22u223r5";
String digitsOnly = s.replaceAll("[^\\d.]", "");
int firstDifferentDigit = -1;
for(int i = 1; i < digitsOnly.length(); i++) {
if(digitsOnly.charAt(i) != digitsOnly.charAt(i-1)) {
firstDifferentDigit = i;
break;
}
}
System.out.println("firstDifferentDigit:"+firstDifferentDigit);
System.out.println(digitsOnly.substring(0,firstDifferentDigit));
Outputs
firstDifferentDigit:4
2222
Taking digits until first non digit
String s = "124g35h6j3lk4kj56";
int firstNonDigitCharacter = -1;
for(int i = 0; i < s.length(); i++) {
if(s.charAt(i) < '0' || s.charAt(i) > '9') {
firstNonDigitCharacter = i;
break;
}
}
System.out.println("firstNonDigitCharacter:"+firstNonDigitCharacter);
System.out.println(s.substring(0,firstNonDigitCharacter));
Outputs
firstNonDigitCharacter:3
124
EDIT
This works for how you described the exercise:
String someSymbols = "72745123";
List<String> sequences = new ArrayList<>();
boolean inSequence = false; // will flag if we are currently within a sequence
StringBuilder currentSequence = new StringBuilder(); // this will store the numbers of the sequence
for(int i = 0; i < someSymbols.length(); i++) {
char currentChar = someSymbols.charAt(i);
char nextChar = 0;
if(i < someSymbols.length()-1)
nextChar = someSymbols.charAt(i+1);
// if next number is 1 more than the current one, we are in a sequence
if(currentChar == nextChar-1) {
inSequence = true;
currentSequence.append(String.valueOf(currentChar));
// if next number is NOT 1 more than the current one and we are in a sequence, it is the last of the sequence
} else if(inSequence) {
currentSequence.append(String.valueOf(currentChar));
sequences.add(currentSequence.toString());
currentSequence = new StringBuilder();
inSequence = false;
}
}
System.out.println(sequences);
Outputs
[45, 123]
Thanks a lot! I made it with your help! It turns out that the task was to count how many numbers occur in the string of any symbols. As simple as that. My bad! But I'm grateful to be part of this forum :)
Here's the code:
String f = sc.nextLine();
int count = 0;
for(int i=0; i<f.length(); i++){
if((f.charAt(i)>='0') && (f.charAt(i)<='9')){
count++;
}
}
System.out.println("The numbers in the row are : " + count);
I deleted my first answer, because I got the question wrong, thought it's about a character sequence, of which some happen to be digits.
Trying to wrap my head around the new functional style in Java8, but conversion is complicated and full of pitfalls. Surely, this isn't canonical. I guess a collector could be appropriate here, but I broke out and made half of the work in an recursive method.
import java.util.*;
import java.util.stream.*;
String s = "123534567321468"
List<Integer> li = IntStream.range (0, s.length()-2).filter (i -> (s.charAt(i+1) != s.charAt(i)+1)).collect (ArrayList::new, List::add, List::addAll);
li.add (s.length()-1);
int maxDiff (int last, List<Integer> li , int maxdiff) {
if (li.isEmpty ())
return maxdiff;
return maxDiff (li.get(0), li.subList (1, li.size () - 1), Math.max (li.get(0) - last, maxdiff));
}
int result = maxDiff (0, li, 0);
It starts elegantly.
IntStream.range (0, s.length()-2).filter (i -> (s.charAt(i+1) != s.charAt(i)+1))
| Expression value is: java.util.stream.IntPipeline$9#5ce81285
| assigned to temporary variable $20 of type IntStream
-> $20.forEach (i -> System.out.println (i));
2
3
8
9
10
11
12
That's the List of indexes, where chains of numbers are broken.
String s = "123534567321468"
123 is from 0 to 2, 5 is just 3, 34567, the later winner from 4 to 8, ...
Note that we needn't transform the String into Numbers, since the characters are chained in ASCII or UTF-X one by one, like numbers.
To convert it into a List, the complicated collect method is used, because Array of primitive int doesn't work well with List .
For the last interval, li.add (s.length()-1) has to be added - adding elements wouldn't work with array.
maxDiff protocolls the max so far, the last element and repeatedly takes the head from the list, to compare it with the last element to build the current difference.
The Code was testet in the jshell of Java9, which is an amazing tool and needs no embedding class, nor 'main' for snippets. :)
Just for comparison, this is my solution in scala:
val s = "123534567321468"
val cuts = (0 to s.length-2).filter (i => {s.charAt(i+1) != s.charAt(i)+1}).toList ::: s.length-1 :: Nil
(0 :: cuts).sliding (2, 1).map {p => p(1) - p(0)}.max
Sliding(a,b) defines a window of width a=2 which moves forward by b=1.

String index out of range - Why is this occurring?

(Please keep in mind I have only been studying java for under a month on my own)
I am trying to make a program that simply tells you the last char of the name you give the program. Here is my code:
import java.util.Scanner;
public class LastCharacter {
public static void main(String[] args) {
Scanner reader = new Scanner(System.in);
System.out.println("hey");
String name = reader.nextLine();
lastChar(name);
}
public static char lastChar(String text) {
char lastChar = '\0';;
int i = 0;
for (i = 0; i <= text.length(); i++) {
lastChar = text.charAt(i);
}
System.out.println(lastChar);
return lastChar;
}
}
Error:
Exception in thread "main" java.lang.StringIndexOutOfBoundsException: String index out of range: 4
at java.lang.String.charAt(String.java:658)
at LastCharacter.lastChar(LastCharacter.java:19)
at LastCharacter.main(LastCharacter.java:11)
Java Result: 1
I also know this can be made by subtracting the length of the string by 1, however I would like to know why this method isn't working. I don't really know how to word this but do strings and chars not get along? (pls dont make fun of me)
Thanks!
Java strings start at a base index of 0. Therefore, this line: for (i = 0; i <= text.length(); i++) { is trying to access an index that doesn't exist. The string main only goes from 0 to 3. So, when you try to access index 4, you get the out of bounds error.
Replace this line:
for (i = 0; i <= text.length(); i++) {
With this:
for (i = 0; i < text.length(); i++) { to fix the problem.
The problem is because Java uses a 0 index array for the string. This means that your for loop i <= text.length() is going to the last character +1. In a name like "Joe"
J = 0,
o = 1,
e = 2
The length of "Joe" is 3 and therefor the loop goes to index(3) which is out of the bounds of the character array.
Two things to take note here:
1.) The length() method in Java String class returns the number of characters of a string
2.) Java arrays uses zero-base index
So, to accomplish your task of getting the last character of the name string :
public static char lastChar(String text) {
int textLength = text.length();
char lastChar = text.charAt(textLength - 1); //first char starts from index 0
return lastChar;
}
Hope it helps.
You are out of bounds! The condition should be:
i < text.length()
for (i = 0; i < text.length(); i++) {
lastChar = text.charAt(i);
}
Strings are 0 based, meaning the first index is 0. So for the string "mom", the 0th index is "m", the 1st index is "o" and the 2nd index is "m". That means this string doesn't have a third index, even though its length is 3! Based on that, your loop should be:
for (i = 0; i < text.length(); i++) {
lastChar = text.charAt(i);
}
However, there is an even better way to do it with no loops at all. We can simply get the character at the last index of the string without looping over each character. It is less complicated and more efficent:
lastChar = text.charAt(text.length() - 1);

int array to int number in Java

I'm new on this site and, if I'm here it's because I haven't found the answer anywhere on the web and believe me: I've been googling for quite a time but all I could find was how to convert a number to an array not the other way arround.
I'm looking for a simple way or function to convert an int array to an int number. Let me explain for example I have this :
int[] ar = {1, 2, 3};
And I want to have this:
int nbr = 123;
In my head it would look like this (even if I know it's not the right way):
int nbr = ar.toInt(); // I know it's funny
If you have any idea of how I could do that, that'd be awesome.
Start with a result of 0. Loop through all elements of your int array. Multiply the result by 10, then add in the current number from the array. At the end of the loop, you have your result.
Result: 0
Loop 1: Result * 10 => 0, Result + 1 => 1
Loop 2: Result * 10 => 10, Result + 2 => 12
Loop 3: Result * 10 >= 120, Result + 3 => 123
This can be generalized for any base by changing the base from 10 (here) to something else, such as 16 for hexadecimal.
You have to cycle in the array and add the right value.
The right value is the current element in the array multiplied by 10^position.
So: ar[0]*1 + ar[1]*10 + ar[2] *100 + .....
int res=0;
for(int i=0;i<ar.length;i++) {
res=res*10+ar[i];
}
Or
for(int i=0,exp=ar.length-1;i<ar.length;i++,exp--)
res+=ar[i]*Math.pow(10, exp);
First you'll have to convert every number to a string, then concatenate the strings and parse it back into an integer. Here's one implementation:
int arrayToInt(int[] arr)
{
//using a Stringbuilder is much more efficient than just using += on a String.
//if this confuses you, just use a String and write += instead of append.
StringBuilder s = new StringBuilder();
for (int i : arr)
{
s.append(i); //add all the ints to a string
}
return Integer.parseInt(s.toString()); //parse integer out of the string
}
Note that this produce an error if any of the values past the first one in your array as negative, as the minus signs will interfere with the parsing.
This method should work for all positive integers, but if you know that all of the values in the array will only be one digit long (as they are in your example), you can avoid string operations altogether and just use basic math:
int arrayToInt(int[] arr)
{
int result = 0;
//iterate backwards through the array so we start with least significant digits
for (int n = arr.length - 1, i = 1; n >= 0; n --, i *= 10)
{
result += Math.abs(arr[n]) * i;
}
if (arr[0] < 0) //if there's a negative sign in the beginning, flip the sign
{
result = - result;
}
return result;
}
This version won't produce an error if any of the values past the first are negative, but it will produce strange results.
There is no builtin function to do this because the values of an array typically represent distinct numbers, rather than digits in a number.
EDIT:
In response to your comments, try this version to deal with longs:
long arrayToLong(int[] arr)
{
StringBuilder s = new StringBuilder();
for (int i : arr)
{
s.append(i);
}
return Long.parseLong(s.toString());
}
Edit 2:
In response to your second comment:
int[] longToIntArray(long l)
{
String s = String.valueOf(l); //expand number into a string
String token;
int[] result = new int[s.length() / 2];
for (int n = 0; n < s.length()/2; n ++) //loop through and split the string
{
token = s.substring(n*2, (n+2)*2);
result[n] = Integer.parseInt(token); //fill the array with the numbers we parse from the sections
}
return result;
}
yeah you can write the function yourself
int toInt(int[] array) {
int result = 0;
int offset = 1;
for(int i = array.length - 1; i >= 0; i--) {
result += array[i]*offset;
offset *= 10;
}
return result;
}
I think the logic behind it is pretty straight forward. You just run through the array (last element first), and multiply the number with the right power of 10 "to put the number at the right spot". At the end you get the number returned.
int nbr = 0;
for(int i = 0; i < ar.length;i++)
nbr = nbr*10+ar[i];
In the end, you end up with the nbr you want.
For the new array you gave us, try this one. I don't see a way around using some form of String and you are going to have to use a long, not an int.
int [] ar = {2, 15, 14, 10, 15, 21, 18};
long nbr = 0;
double multiplier = 1;
for(int i = ar.length-1; i >=0 ;i--) {
nbr += ar[i] * multiplier;
multiplier = Math.pow(10, String.valueOf(nbr).length());
}
If you really really wanted to avoid String (don't know why), I guess you could use
multiplier = Math.pow(10,(int)(Math.log10(nbr)+1));
which works as long as the last element in the array is not 0.
Use this method, using a long as your input is to large for an int.
long r = 0;
for(int i = 0; i < arr.length; i++)
{
int offset = 10;
if(arr[i] >= 10)
offset = 100;
r = r*offset;
r += arr[i];
}
This checks if the current int is larger than 10 to reset the offset to 100 to get the extra places required. If you include values > 100 you will also need to add extra offset.
Putting this at end of my post due to all the downvotes of Strings...which is a perfectly legitimate answer...OP never asked for the most efficient way to do it just wannted an answer
Loop your array appending to a String each int in the array and then parse the string back to an int
String s = "";
for(int i = 0; i < arr.length; i++)
s += "" + arr[i];
int result = Integer.parseInt(s);
From your comment the number you have is too long for an int, you need to use a long
String s = "";
for(int i = 0; i < arr.length; i++)
s += "" + arr[i];
long result = Long.parseLong(s);
If you can use Java 1.8, stream API makes it very simple:
#Test
public void arrayToNumber() {
int[] array = new int[]{1,2,3,4,5,6};
StringBuilder sb = new StringBuilder();
Arrays.stream(array).forEach(element -> sb.append(element));
assertThat(sb.toString()).isEqualTo("123456");
}
you can do it that way
public static int[] plusOne(int[] digits) {
StringBuilder num= new StringBuilder();
PrimitiveIterator.OfInt primitiveIterator = Arrays.stream(digits)
.iterator();
while (primitiveIterator.hasNext()) {
num.append(primitiveIterator.nextInt());
}
int plusOne=Integer.parseInt(String.valueOf(num))+1;
return Integer.toString(plusOne).chars().map(c -> c-'0').toArray();
}
BE SIMPLE!!!
public static int convertToInteger(int... arr) {
return Integer.parseInt(Arrays.stream(arr)
.mapToObj(String::valueOf)
.collect(Collectors.joining()));
}
this also possible to convert an Integer array to an int array
int[] result = new int[arr.length];
for (int i = 0; i < arr.length; i++) {
result[i] = arr[i].intValue();
}

Counting occurrences of characters in a word list

I'm trying to make an AI for a hangman game, part of which requires counting all occurrences of each possible character in the word list. I'm planning on culling the word list before this counting to make things run faster (by first culling out all words that are not the same length as the guessable phrase, and then by culling out words that do not match the guessed characters).
The problem I am having is in the code below. Somehow, it always returns a list of e's that are the correct length (matching the number of possible characters). I'm not sure exactly what I'm doing wrong here, but the problem is definitely somewhere in countCharacters.
MethodicComputer(){
guessable = parseGuessable();
wordList = parseText();
priorities = countCharacters(guessable);
}
public char guessCharacter(String hint){
char guess = 0;
System.out.println(guessable);
System.out.println(priorities);
guess = priorities.charAt(0);
priorities = priorities.replaceAll("" + guess, "");
return guess;
}
private String countCharacters(String possibleChars){
charCount = new Hashtable();
String orderedPriorities = "";
char temp = 0;
char adding = 0;
int count = 0;
int max = 0;
int length = possibleChars.length();
for (int i = 0; i<length; i++){
temp = possibleChars.charAt(i);
count = wordList.length() - wordList.replaceAll("" + temp, "").length();
charCount.put(temp, count);
}
while (orderedPriorities.length() < length){
for (int i = 0; i < possibleChars.length(); i++){
temp = possibleChars.charAt(i);
if (max < (int) charCount.get(temp)){
max = (int) charCount.get(temp);
adding = temp;
}
}
orderedPriorities += adding;
possibleChars = possibleChars.replaceAll("" + adding, "");
}
return orderedPriorities;
}
The problem is that I did not update the max variable, so it never entered the if statement and updated the adding variable. A simple addition of
max = 0;
to the end of the while loop fixed it.

Categories

Resources