charAt(0) gives java.lang.StringIndexOutOfBoundsException - java

String.charAt(0) is giving java.lang.StringIndexOutOfBoundsException even though the String is not empty
public class Mainc {
public static void main(String[] args) {
int T;
Scanner inp = new Scanner(System.in);
Scanner inp2 = new Scanner(System.in);
T = inp.nextInt();
for (int i = 0; i < T; i++) {
String u = "";
String l = "";
String s = inp2.nextLine();
while (s != null) {
char ch = s.charAt(0);
if (Character.isLowerCase(ch))
l += ch;
else
u += ch;
s = s.substring(1);
}
if (u.length() > l.length())
System.out.println(u);
else
System.out.println(l);
}
}
}
It's supposed to give an all uppercase String or all lowercase String depending on which is bigger or an all uppercase String if they were both equal length but it gives runtime error java.lang.StringIndexOutOfBoundsException
even though the String is not empty and the charAt() function is at index 0. Thanks in advance.

Your while loop loops through the string s, checks each character, adds that character to u or l, and then removes it from s. But what happens when all the characters are removed? s is now empty, but the while loop still executes, because s is not null (null and the empty string are different things!) This means that you would call s.charAt(0) when s is empty, which causes the crash.
To fix this, you can change the while loop conditions to "s is not empty" instead. You don't need to check if s is null because it comes from Scanner.nextLine, which shouldn't return null.
while (!s.isEmpty()) {
char ch = s.charAt(0);
if (Character.isLowerCase(ch))
l += ch;
else u += ch;
s = s.substring(1);
}
You can improve your code further by not removing the character from s in each iteration. Instead, use a for loop with an index to loop through the string. Also, you should use a StringBuilder when concatenating strings in a loop. Both of these will avoid creating unnecessary string objects.
StringBuilder u = new StringBuilder(); // notice the change to StringBuilder here
StringBuilder l = new StringBuilder();
String s = inp2.nextLine();
for (int j = 0 ; j < s.length() ; j ++) {
char ch = s.charAt(j);
if (Character.isLowerCase(ch))
l.append(ch);
else u.append(ch);
}

even your s value is ""(blank) its still going in while loop as its not null after finish all chars so use length while(s.length() > 0) should work.
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.util.Scanner;
public class Test {
public static void main(String[] args) {
int T;
Scanner inp=new Scanner(System.in);
Scanner inp2=new Scanner(System.in);
T=inp.nextInt();
for(int i=0;i<T;i++){
String u=""; String l="";
String s=inp2.nextLine();
while(s.length() > 0){
char ch=s.charAt(0);
if(Character.isLowerCase(ch))
l+=ch;
else u+=ch;
s = s.substring(1);}
if(u.length()>l.length())
System.out.println(u);
else System.out.println(l);
}
}
}

Related

Cannot return modified String from static method

Im very new to coding and cant seem to be able to return anything. I need to convert upper case characters to lower case and vice versa. Here's my code:
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String str = sc.nextLine();
invString(str);
sc.close();
}
private static String invString(String str) {
for (int i = 0; i < str.length(); i++) {
char ch = str.charAt(i);
if (ch > 97) {
ch = Character.toUpperCase(ch);
return str;
} else {
ch = Character.toLowerCase(ch);
return str;
}
}
return null;
}
What am i doing wrong? ( in terms of returning, the code isnt complete yet)
EDIT****************
thanks for the helpful remarks, as i understood i do not have a place where my modifications are stored, so i added String res = ""; and kept adding the values into String res but in the end, when returning res, i still dont get any output...Here is the whole thing:
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String str = sc.nextLine();
String st = invString(str);
sc.close();
}
private static String invString(String str) {
String res = "";
for (int i = 0; i < str.length(); i++) {
char ch = str.charAt(i);
if (65 <= ch && ch <= 90) {
ch += 32;
res += ch;
} else if (97 <= ch && ch <= 122) {
ch -= 32;
res += ch;
}
}
return res;
}
ps. Im not using the ready methods because my task asks for it.
There are a number of flaws in your code. Firstly, you are attempting to return the original string str in every if statement. So what happens is the method invString( String ) simply returns the original string that is passed as argument. Instead, you should keep adding the characters to a new String variable (as #Massimo said). Also, you are returning null in the end. Why even do that? You would want to return the new String variable instead.
private static String invString(String str) {
String s=""; //new String variable
for (int i = 0; i < str.length(); i++) {
char ch = str.charAt(i);
if (ch > 97) {
ch = Character.toUpperCase(ch);
s+=ch; //do this instead of returning str
} else {
ch = Character.toLowerCase(ch);
s+=ch; //same here
}
}
return s; //return the new String
}
Secondly, in your main method, simply calling the method is wrong as it returns a value. You should assign the value returned by invString() to a String variable.
public static void main(String[] args){
...
String st = invString(str); //st stores the value of str with
//letters' cases changed
}
You return you str object without updating it at all.
You should generate a new string in which put the characters for which you reverse the case.
Check the last answers in
How can I invert the case of a String in Java?
If you want to use the inverted string, you need to actually use the returned value, e.g:
str = invString (str)
Strings are immutable so you can't change the characters within them. You can only replace the string variable with a new string.
Modifying the characters you are accessing doesn't affect the string. You need to build a new string (look up StringBuilder) and return it.

reverse every word of the sentence..the changes do not appear

this is a simple program to reverse each word of the string and print ... i dont know whats going wrong with this...please help
import java.util.Scanner;
public class ReverseWordCapitalizeFirstCharacter {
public static void reverse(char a[], int start, int end)
{
while(start<end)
{
char temp = a[start];
a[start] = a[end];
a[end] = temp;
start++;
end--;
}
}
public static void main(String[] args) {
System.out.println("Enter the string");
Scanner sc = new Scanner(System.in);
String str = sc.next();
char a[] = new char[str.length()];
a = str.toCharArray();
int wordStartIndex = 0;
for(int i=0; i<a.length; i++)
{
if(a[i] == ' ')
{
reverse(a,wordStartIndex,i-1);
wordStartIndex = i+1;
}
}
for(int i=0; i<a.length; i++)
{
System.out.print(a[i]);
}
}
}
i am passing the character array as parameter to the function that reverse each word..
Is it not because sc.next() returns only the next word ?
So, you never encounter a ' ' in your string, thus you never call the reverse method. Try with sc.nextLine(); maybe.
Javadoc says :
A Scanner breaks its input into tokens using a delimiter pattern, which by default matches whitespace.
As a result, if you enter "abc 123 456", sc.next() will only return "abc".
String str = sc.next();//str only contains "abc"
[...]
if(a[i] == ' ') //This condition is never met.
You can specify the delimiter like this :
Scanner sc = new Scanner(System.in);
sc.useDelimiter("\n");

love letter passes for base test cases

Loveletter code question: James found a love letter his friend Harry has written for his girlfriend. James is a prankster, so he decides to meddle with the letter. He changes all the words in the letter into palindromes.
To do this, he follows 2 rules:
(a) He can reduce the value of a letter, e.g. he can change 'd' to 'c', but he cannot change 'c' to 'd'.
(b) In order to form a palindrome, if he has to repeatedly reduce the value of a letter, he can do it until the letter becomes 'a'. Once a letter has been changed to 'a', it can no longer be changed.
Each reduction in the value of any letter is counted as a single operation. Find the minimum number of operations required to convert a given string into a palindrome.
import java.io.*;
import java.util.*;
import java.text.*;
import java.math.*;
import java.util.regex.*;
public class Solution {
static int getAscii(char letter)
{
return (int)letter;
}
static boolean checkPalindrome(String str, int strLen)
{
String revStr ="";
for(int i=strLen;i >= 0;i--)
{
revStr = revStr + str.charAt(i);
}
if(str.equals(revStr))
{
return true;
}
return false;
}
static void reduceAscii(String str)
{
StringBuilder sb = new StringBuilder(str);
str = str.toString();
int strLen = str.length()-1;
int numOfOperations=0;
char letter;
for(int j=strLen; j >= 0; j--)
{
letter = str.charAt(j);
while(getAscii(letter) > 97 && getAscii(letter) <= 122)
{
if(checkPalindrome(str, strLen))
{
break;
}
else
{
int asciiValofLetter = (char)getAscii(letter);
char charToreplace = (char)(asciiValofLetter-1);
sb.setCharAt(j, charToreplace);
str = sb.toString();
letter = charToreplace;
numOfOperations++;
}
}
}
System.out.println(numOfOperations);
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int numOfTestCases;
String str;
numOfTestCases = sc.nextInt();
for(int i=0; i < numOfTestCases; i++)
{
str = sc.next();
Solution.reduceAscii(str);
}
}
}
My code passes for abc, abcd, abcba but fails for lot of test cases. Here are some:
pue
heubsbn
feazhaxpux
hmhcy
tmp
Your solution looks overly complicated. You're asked to find the number of operations required, not the actual result.
Java's not my thing, so here's some pseudocode:
Number of letters to change = int(length of string/2) (for a seven letter string we change three letters)
Total operations = 0
for n=0 to number of letters to change
take nth letter and (string length-n)th letter
(number of operations on each letter is difference of ASCII values so...)
subtract ASCII value of first letter from ASCII value of second
add absolute value of this to your total
next letter
print total.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.InputMismatchException;
public class ConvertToPal {
public ConvertToPal() {
// TODO Auto-generated constructor stub
}
public static void main(String[] args) throws IOException{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
System.out.println("Please enter a string to be palindromized! ");
String str = br.readLine();
char[] strArr = str.toCharArray();
int size = strArr.length;
int numOfOperations = 0;
for (int i = 0; i < (size/2) ; i++){
int dif = (getAscii(strArr[i])-getAscii(strArr[size-1-i]));
if (dif > 0){
strArr[i] = strArr[size-1-i];
numOfOperations += Math.abs(dif);
}
if(dif < 0){
strArr[size-1-i] = strArr[i];
numOfOperations += Math.abs(dif);
}
}
System.out.println(new String(strArr));
System.out.println("num of ops: "+ numOfOperations);
}
static int getAscii(char letter){
return (int)letter;
}
}
Here is a method in Java to achieve this
public int palindromeCount(String s) {
int count = 0;
int i = 0, j = s.length() - 1;
while (i < j) {
int front = (int) s.charAt(i);
int back = (int) s.charAt(j);
count += (Math.abs(front - back));
i++;
j--;
}
return count;
}

Reverse characters in a sentence

Im trying to reverse characters in a sentence without using the split function. Im really close but I am missing the final letter. Can some one please point me in the right direction? Right now it prints "This is a new sentence" as "sihT si a wen cnetnes" Also I included if(start == 0) because the program would skip the initial space character, but I don't understand why?
static String reverseLetters(String sentence)
StringBuilder reversed = new StringBuilder("");
int counter = 0;
int start = 0;
String word;
for(int i = 0; i <= sentence.length()-1 ; i++ )
{
if(sentence.charAt(i)== ' '|| i == sentence.length()-1 )
{
StringBuilder sb = new StringBuilder("");
sb.append(sentence.substring(start,i));
if(start == 0)
{
start = i;
word = sb.toString();
reversed.append(reverseChar(word));
reversed.append(' ');
}
else
{
start = i;
word = sb.toString();
reversed.append(reverseChar(word));
}
}
return reversed.toString();
}
static String reverseChar (String word)
{
StringBuilder b = new StringBuilder("");
for(int idx = word.length()-1; idx >= 0; idx -- )
{
b.append(word.charAt(idx));
}
return b.toString();
}
start means wordStart. As i points to the space, the next wordStart should point after i.
Hence the last i should point after the last word char, should be length()
the if-then-else is too broad; a space has to be added in one case: i pointing at the space.
One could loop unconditionally, and on i == length() break in the middle of the loop code.
I think the error lies in the index, the for should be
for(int i = 0; i <= sentence.length() ; i++ )
Then if should be:
if (sentence.charAt(i==0?0:i-1)== ' '|| i == sentence.length() )
For me the error will be that the substring(start,i) for the last one i should be sentence.length instead of sentence.length-1, so this would solve it.
Substring is open in the last index, so if you put substring(1, 10) will be substring from 1 to 9. That might be the problem with last word.
The thing with the first space is also the problem with substring, let's say you're reading "this is..." the first time it will do a subtring with start=0 and i = 4 so you expect "this " but it really is "this". The next reading, with start=4 and i=7 will be " is".
So with the change of the index you should be able to remove the if/else with start==0 too.
Another option
private String reverse (String originalString) {
StringBuilder reverseString = new StringBuilder();
for (int i = originalString.length() - 1; i >= 0; i--) {
reverseString.append(originalString.charAt(i));
}
return reverseString.toString();
}
String reverseString = "This is a new sentence";
System.out.println(new StringBuffer(reverseString).reverse().toString());
Syso prints : ecnetnes wen a si sihT
Put
i <= sentence.length()
In your for loop and change the if to:
if(i == sentence.length() || sentence.charAt(i)== ' ')
as
substring(start,i)
Returns the string up to i, not included.
import java.util.Stack;
public class Class {
public static void main(String[] args) {
String input = "This is a sentence";
char[] charinput = input.toCharArray();
Stack<String> stack = new Stack<String>();
for (int i = input.length() - 1; i >= 0; i--) {
stack.push(String.valueOf(charinput[i]));
}
StringBuilder StackPush = new StringBuilder();
for (int i = 0; i < stack.size(); i++) {
StackPush.append(stack.get(i));
}
System.out.println(StackPush.toString());
}
}
Not a split to be seen.

Reversing characters in each word in a sentence - Stack Implementation

This code is inside the main function:
Scanner input = new Scanner(System.in);
System.out.println("Type a sentence");
String sentence = input.next();
Stack<Character> stk = new Stack<Character>();
int i = 0;
while (i < sentence.length())
{
while (sentence.charAt(i) != ' ' && i < sentence.length() - 1)
{
stk.push(sentence.charAt(i));
i++;
}
stk.empty();
i++;
}
And this is the empty() function:
public void empty()
{
while (this.first != null)
System.out.print(this.pop());
}
It doesn't work properly, as by typing example sentence I am getting this output: lpmaxe. The first letter is missing and the loop stops instead of counting past the space to the next part of the sentence.
I am trying to achieve this:
This is a sentence ---> sihT si a ecnetnes
Per modifications to the original post, where the OP is now indicating that his goal is to reverse the letter order of the words within a sentence, but to leave the words in their initial positions.
The simplest way to do this, I think, is to make use of the String split function, iterate through the words, and reverse their orders.
String[] words = sentence.split(" "); // splits on the space between words
for (int i = 0; i < words.length; i++) {
String word = words[i];
System.out.print(reverseWord(word));
if (i < words.length-1) {
System.out.print(" "); // space after all words but the last
}
}
Where the method reverseWord is defined as:
public String reverseWord(String word) {
for( int i = 0; i < word.length(); i++) {
stk.push(word.charAt(i));
}
return stk.empty();
}
And where the empty method has been changed to:
public String empty() {
String stackWord = "";
while (this.first != null)
stackWord += this.pop();
return stackWord;
}
Original response
The original question indicated that the OP wanted to completely reverse the sentence.
You've got a double-looping construct where you don't really need it.
Consider this logic:
Read each character from the input string and push that character to the stack
When the input string is empty, pop each character from the stack and print it to screen.
So:
for( int i = 0; i < sentence.length(); i++) {
stk.push(sentence.charAt(i));
}
stk.empty();
I assume that what you want your code to do is to reverse each word in turn, not the entire string. So, given the input example sentence you want it to output elpmaxe ecnetnes not ecnetnes elpmaxe.
The reason that you see lpmaxe instead of elpmaxe is because your inner while-loop doesn't process the last character of the string since you have i < sentence.length() - 1 instead of i < sentence.length(). The reason that you only see a single word is because your sentence variable consists only of the first token of the input. This is what the method Scanner.next() does; it reads the next (by default) space-delimited token.
If you want to input a whole sentence, wrap up System.in as follows:
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
and call reader.readLine().
Hope this helps.
Assuming you've already got your input in sentence and the Stack object is called stk, here's an idea:
char[] tokens = sentence.toCharArray();
for (char c : tokens) {
if (c == ' ') {
stk.empty();
System.out.print(c);
} else {
stk.add(c);
}
}
Thus, it will scan through one character at a time. If we hit a space character, we'll assume we've hit the end of a word, spit out that word in reverse, print that space character, then continue. Otherwise, we'll add the character to the stack and continue building the current word. (If you want to also allow punctuation like periods, commas, and the like, change if (c == ' ') { to something like if (c == ' ' || c == '.' || c == ',') { and so on.)
As for why you're only getting one word, darrenp already pointed it out. (Personally, I'd use a Scanner instead of a BufferedReader unless speed is an issue, but that's just my opinion.)
import java.util.StringTokenizer;
public class stringWork {
public static void main(String[] args) {
String s1 = "Hello World";
s1 = reverseSentence(s1);
System.out.println(s1);
s1 = reverseWord(s1);
System.out.println(s1);
}
private static String reverseSentence(String s1){
String s2 = "";
for(int i=s1.length()-1;i>=0;i--){
s2 += s1.charAt(i);
}
return s2;
}
private static String reverseWord(String s1){
String s2 = "";
StringTokenizer st = new StringTokenizer(s1);
while (st.hasMoreTokens()) {
s2 += reverseSentence(st.nextToken());
s2 += " ";
}
return s2;
}
}
public class ReverseofeachWordinaSentance {
/**
* #param args
*/
public static void main(String[] args) {
String source = "Welcome to the word reversing program";
for (String str : source.split(" ")) {
System.out.print(new StringBuilder(str).reverse().toString());
System.out.print(" ");
}
System.out.println("");
System.out.println("------------------------------------ ");
String original = "Welcome to the word reversing program";
wordReverse(original);
System.out.println("Orginal Sentence :::: "+original);
System.out.println("Reverse Sentence :::: "+wordReverse(original));
}
public static String wordReverse(String original){
StringTokenizer string = new StringTokenizer(original);
Stack<Character> charStack = new Stack<Character>();
while (string.hasMoreTokens()){
String temp = string.nextToken();
for (int i = 0; i < temp.length(); i ++){
charStack.push(temp.charAt(i));
}
charStack.push(' ');
}
StringBuilder result = new StringBuilder();
while(!charStack.empty()){
result.append(charStack.pop());
}
return result.toString();
}
}
public class reverseStr {
public static void main(String[] args) {
String testsa[] = { "", " ", " ", "a ", " a", " aa bd cs " };
for (String tests : testsa) {
System.out.println(tests + "|" + reverseWords2(tests) + "|");
}
}
public static String reverseWords2(String s) {
String[] sa;
String out = "";
sa = s.split(" ");
for (int i = 0; i < sa.length; i++) {
String word = sa[sa.length - 1 - i];
// exclude "" in splited array
if (!word.equals("")) {
//add space between two words
out += word + " ";
}
}
//exclude the last space and return when string is void
int n = out.length();
if (n > 0) {
return out.substring(0, out.length() - 1);
} else {
return "";
}
}
}
This can pass in leetcode

Categories

Resources