Replacing a specific Char from a String between two positions - java

Consider the following String:
String str = "XFB_PART~\XFB_IDF~\XFB_MODE~0\XFB_LOCALITEM~\XFB_REMOTEITEM~\XFB_MSG~tool\ soundgarden~\ASYNCHRONOUS~0\BROADCAST~0\XFB_LOCALAGT~"
What I would like to do is replace all the backslashes between XFB_MSG and ASYNCHRONOUS with commas (so every time you see a backslash, replace it with a comma).
Here's what I did:
stringBuffer = new StringBuffer(str);
for (int i = stringBuffer.indexOf("XFB_MSG"); i<stringBuffer.indexOf("ASYNCHRONOUS"); i++){
if(stringBuffer.charAt(i)=='\\'){
stringBuffer = stringBuffer.replace(i, i, ",");
}
}
Problem is, once the condition if (stringBuffer.charAt(i)=='\\') is met, the compiler keeps on entering and replacing the char even when i changes value and as a result I'm getting an infinite loop with commas being constantly inserted:
XFB_PART~\XFB_IDF~\XFB_MODE~0\XFB_LOCALITEM~\XFB_REMOTEITEM~\XFB_MSG~tool,,,,,,,,\ soundgarden~\ASYNCHRONOUS~0\BROADCAST~0\XFB_LOCALAGT~
Once again, the objective is to only replace all the backslashes between XFB_MSG and ASYNCHRONOUS and leave the rest of the string intact. The positions can change, and so can the value between those two parameters. So I have to search for them like that and try to find a way to replace the backslashes between them with commas.
Any idea why am I having an infinite loop, and if you happen to have a better way to do this, please do not hesitate to let me know.
Thank you.

I changed:
stringBuffer = stringBuffer.replace(i, i, ",");
to:
stringBuffer = stringBuffer.replace(i, i+1, ",");
and now it's working.
But I still don't understand why it's working now and why earlier I had an infinite loop.

Related

I cannot print value of converted string

I want to reverse a string. I know there are some other methods to do it but I wanted to do in a different way. There is no error but no output when I run my code. I dont understand why "String.valueOf(word.charAt(i)" doesnt return a value? Am I missing something?
String word = "myword";
for (int i = word.length(); i <= 0; i--) {
System.out.print(String.valueOf(word.charAt(i)));
}
The first value of i is out of index. And I also fixed your code. Check below:
String word = "myword";
for(int i=word.length()-1;i>=0;i--){
System.out.print(String.valueOf(word.charAt(i)));}
Just for providing another slightly different solution:
You can use a StringBuilder to reverse a String using its method reverse().
If you have a String, you can use it to initialize the StringBuilder with it and directly reverse it.
This example additionally uses an enhanced for-loop, which always goes through all of the elements. Using that, you can get rid of checking the length of a String and you won't have to use an int i for iterating.
For your requirements, this is a suitable option because you want to reverse the whole String.
String word = "myword";
for (char c : new StringBuilder(word).reverse().toString().toCharArray()) {
System.out.println(c);
}
Note that you can use the reverse() method for printing the reversed word in one line just doing
System.out.println(new StringBuilder(word).reverse().toString());
Your code has 2 issues.
i should be initialized with word.length()-1. Other wise you will get StringIndexOutOfBoundsException
for loop condition should be >= 0.
Below is the corrected code.
String word = "myword";
for(int i=word.length()-1;i>=0;i--) {
System.out.print(word.charAt(i));
}

Getting error "String index out of range: 0" on using String Builder

So this is my code in Java (for returning two halves of a string - one is the odd half, starting with the index 0, or the first character, and the second half, starting with the index 1, or the second character):
public class StringTest{
public String halfOfString(String message, int start){
int length = message.length();
StringBuilder output = new StringBuilder(length);
char ch;
int i;
if((start==0)||(start==1)){
for(i=start; i<message.length(); i=i+2){
ch = message.charAt(i);
output.setCharAt(i,ch); // error occurs here
}
}
return output.toString();
}
public void testFunction(){
String s = "My name is Sid";
String first = halfOfString(s, 0);
String second = halfOfString(s, 1);
System.out.println("First half is " + first + " and second half is " + second);
}
}
So my problem is - whenever I attempt to run this program on BlueJ IDE, it doesn't, and returns the error in the title, on the line mentioned in the comment.
I have poured over this site for a similar question which may help me with my error, but all I found was a question which suggested a change I have already implemented (in the StringBuilder setCharAt method, the person had reversed the i and ch parameters).
Is it anything to do with the fact that the "output" is declared empty at first, and the setCharAt method can only replace the characters which already exist?
Any help would be greatly appreciated.
Is it anything to do with the fact that the "output" is declared empty at first, and the setCharAt method can only replace the characters which already exist?
Yes, that is exactly why you get this error.
Note that creating a StringBuilder with a specified length, as you are doing:
StringBuilder output = new StringBuilder(length);
does not create a StringBuilder which already has that many characters - it just creates a StringBuilder with that internal buffer size. The StringBuilder itself still contains no characters, so trying to set the first character will result in the exception that you get.
Call append on the StringBuilder to add characters instead of setCharAt.
Is it anything to do with the fact that the "output" is declared empty
at first, and the setCharAt method can only replace the characters
which already exist?
Yes, that's the reason.
The Javadoc of setCharAt is clear on this:
The index argument must be greater than or equal to 0, and less than
the length of this sequence.
Why don't you just use the append method in StringBuilder? It looks to me like, if your code would work, it would leave holes in the StringBuilder since you're only setting every other character and not the ones in between. Using append ensures that there are no holes.

Android String.split("") returning extra element

I am trying to split a word into its individual letters.
I tried both String.split("") and String.split("|") however when I split a word it is creating a extra empty element.
Example:
word = "word";
int n = word.length();
Log.i("20",Integer.toString(n));
String[] letters = word.split("|");
Log.i("25",Integer.toString(letters.length));
The output in the Android Monitor is:
07-21 15:50:23.084 5711-5711/com.strizhevskiy.movetester I/20: 4
07-21 15:50:23.085 5711-5711/com.strizhevskiy.movetester I/25: 5
I put the individual letters into TextView blocks and I can actually see an extra empty TextView.
When I test these methods in my regular Java it outputs the expected answer: 4.
I am almost tempted to think this is an actual bug in Android's implementation of the method.
I am thinking you want to do this:
public Character[] toCharacterArray( String s ) {
if ( s == null ) {
return null;
}
int len = s.length();
Character[] array = new Character[len];
for (int i = 0; i < len ; i++) {
array[i] = new Character(s.charAt(i));
}
return array;
}
Instead of splitting a word without delimiters?
I hope this helps!
It's hard to say if it's bug or expected behavior, because what are you doing doesn't make sense. You are trying to split string with logical OR (split is waiting for Regular expression, not just a string), so as result it could be different result in Android comparing with normal java, and I don't see there any issue.
Anyway, there is many ways to achieve what you want in a normal way, e.g. just iterating over word by each char in a cycle or just use toCharArray String's method.
Thank you for the suggestions. My current work-around is to use a mock array and copying over into a fresh array using System.arraycopy().
String[] mockLetters = word.split("");
int n = word.length();
String[] letters = new String[n];
System.arraycopy(mockLetters,1,letters,0,n);
I appreciate the suggestions to use toCharArray(). However, these letters then get put into TextViews and TextView doesnt seem to accept char. I could, of coarse, make it work but I've decided to stick with what I currently have.
Tom, in a comment to my question, answered my underlying issue:
Why String.split() worked differently in Android than it does in Java?
Apparently the rules for String.split() changed with Java 8.
Try passing a 0 as the limit per the documentation below so that the trailing spaces are discarded.
String[] split (String regex,
int limit)
If n is zero then the pattern will be applied as many times as possible, the array can have any length, and trailing empty strings will be discarded.

Java IF Statement necessary?

I have:
String str = "Hello, how, are, you";
I want to create a helper method that removes the commas from any string. Which of the following is more accurate?
private static String removeComma(String str){
if(str.contains(",")){
str = str.replaceAll(",","");
}
return str;
}
OR
private static String removeComma(String str){
str = str.replaceAll(",","");
return str;
}
Seems like I don't need the IF statement but there might be a case where I do.
If there is a better way let me know.
Both are functionally equivalent but the former is more verbose and will probably be slower because it runs an extra operation.
Also note that you don't need replaceAll (which accepts a regular expression): replace will do.
So I would go for:
private static String removeComma(String str){
return str.replace(",", "");
}
The IF statement is unnecessary, unless you're handling "large" strings (we're talking megabytes or more).
If you're using the IF statement, your code will first search for the first occurance of a comma, and then execute the replacement. This could be costly if the comma is near the end of the string and your string is large, since it will have to be traversed twice.
Without the IF statement, commas will be replaced if they exist. If the answer is negative, your string will be untouched.
Bottom rule: use the version without the IF statement.
Both are correct, but the second one is cleaner since the IF statement of the first alternative is not needed.
It's a matter of what is the probability to have strings with comma in your universe of strings.
If you have a high probability, call the method replaceAll without checking first.
BUT If you are not using extremely huge strings, I guess you will see no difference in perfomance at all.
Just another solution with time complexity O(n), space complexity O(n):
public static String removeComma(String str){
int length = str.length();
StringBuffer sb = new StringBuffer();
for (int i = 0; i < length; i++) {
char c = str.charAt(i);
if (c != ',') {
sb.append(c);
}
}
return sb.toString();
}

How do I print content of reference in JAVA?

Newbie question comming up. Trying to get my head around JAVA.
How do I print out the content of the reference and not just their postition ? My program is ment to get some text in from the user, and print it out in a reverse order.
Here is my program (so far):
package myProgram;
import javax.swing.JOptionPane;
public class someRandomClass {
public static void main(String[] args) {
String word = JOptionPane.showInputDialog("Write som text here");
StringBuilder outPut = new StringBuilder();
for (int i = word.length()-1; i>=0; i--){
outPut.append(i);
}
System.out.println(outPut.toString());
}
}
I am greatfull for any help and tips! :)
In the line
outPut.append(i);
you are appending the value of your loop counter. You surely mean
outPut.append(word.charAt(i));
You seem to appending the integers instead of the appropriate characters. Try this instead:
outPut.append(word.substring(i, i + 1))
This way, the individual characters of word are appended to your StringBuilder. Note that the append method could also take a char as an argument, so you are also able to use word.charAt(i).
So, you want to emit the character at the position? Try using String.charAt.
outPut.append(word.charAt(i));
I'd probably avoid that and just index the char[] from String.toCharArray, though.
To be honest, I'd avoid doing the reversal loop manually to begin with... try something as follows:
final String word = JOptionPane.showInputDialog("Enter text below");
System.out.println(new StringBuilder(word).reverse());
StringBuilder.reverse should do the work for you (likely in a more efficient way, too). You also don't need to call toString manually, as println will do that for you.

Categories