How to insert a character in a string at a certain position?
Asked Answered
M

14

185

I'm getting in an int with a 6 digit value. I want to display it as a String with a decimal point (.) at 2 digits from the end of int. I wanted to use a float but was suggested to use String for a better display output (instead of 1234.5 will be 1234.50). Therefore, I need a function that will take an int as parameter and return the properly formatted String with a decimal point 2 digits from the end.

Say:

int j= 123456 
Integer.toString(j); 

//processing...

//output : 1234.56
Manganous answered 4/5, 2011 at 13:42 Comment(1)
String str = Integer.toString(j); //integer or string with white spaces<br/> str = new StringBuffer(str.trim()).insert(str.length()-2, ".").toString();Distraint
J
223
int j = 123456;
String x = Integer.toString(j);
x = x.substring(0, 4) + "." + x.substring(4, x.length());
Judiejudith answered 4/5, 2011 at 13:45 Comment(5)
Strings are immutable. While this works, using something like StringBuilder is morally correct, not to mention will make your code faster.Ictinus
Forget StringBuilder. With formatting such as this, String.format is the best option available.Calk
There is no loop, it's a simple concatenation case and compiler should optimize it using a string builder, for readability I prefer to use the + operator, there is no need in this case to use StringBuilder explicitly. Using "StringBuilder" solution because it's faster don't respect optimization rules. Code for readability. Optimize after profiling and only where it is require. en.wikipedia.org/wiki/Program_optimization#QuotesMelanous
You do not need x.length() on the second substring call.Subauricular
This solution will fail when the number is a different number of digits. For 12345 it will output 1234.5 and for 1234567 it will be 1234.567. If you always want the last 2 digits to be after the decimal point, the make sure the number has at least 3 digits and then do x = x.substring(0, x.length()-2) + "." + x.substring(x.length()-2);Haematoid
D
245

As mentioned in comments, a StringBuilder is probably a faster implementation than using a StringBuffer. As mentioned in the Java docs:

This class provides an API compatible with StringBuffer, but with no guarantee of synchronization. This class is designed for use as a drop-in replacement for StringBuffer in places where the string buffer was being used by a single thread (as is generally the case). Where possible, it is recommended that this class be used in preference to StringBuffer as it will be faster under most implementations.

Usage :

String str = Integer.toString(j);
str = new StringBuilder(str).insert(str.length()-2, ".").toString();

Or if you need synchronization use the StringBuffer with similar usage :

String str = Integer.toString(j);
str = new StringBuffer(str).insert(str.length()-2, ".").toString();
Decaffeinate answered 21/11, 2012 at 22:48 Comment(1)
This solution works for any string >= 4 characters: the string "111" gave me ".111", and anything less than that results in a java.lang.StringIndexOutOfBoundsException (attempting to access a reference that doesn't exist).Amadeus
J
223
int j = 123456;
String x = Integer.toString(j);
x = x.substring(0, 4) + "." + x.substring(4, x.length());
Judiejudith answered 4/5, 2011 at 13:45 Comment(5)
Strings are immutable. While this works, using something like StringBuilder is morally correct, not to mention will make your code faster.Ictinus
Forget StringBuilder. With formatting such as this, String.format is the best option available.Calk
There is no loop, it's a simple concatenation case and compiler should optimize it using a string builder, for readability I prefer to use the + operator, there is no need in this case to use StringBuilder explicitly. Using "StringBuilder" solution because it's faster don't respect optimization rules. Code for readability. Optimize after profiling and only where it is require. en.wikipedia.org/wiki/Program_optimization#QuotesMelanous
You do not need x.length() on the second substring call.Subauricular
This solution will fail when the number is a different number of digits. For 12345 it will output 1234.5 and for 1234567 it will be 1234.567. If you always want the last 2 digits to be after the decimal point, the make sure the number has at least 3 digits and then do x = x.substring(0, x.length()-2) + "." + x.substring(x.length()-2);Haematoid
G
16
int yourInteger = 123450;
String s = String.format("%6.2f", yourInteger / 100.0);
System.out.println(s);
Galluses answered 4/5, 2011 at 13:46 Comment(1)
I would suggest using java.math.BigDecimal as using double can cause rounding error. If speed is more valuable than precision double is better.Amadeus
S
10

Using ApacheCommons3 StringUtils, you could also do

int j = 123456;
String s = Integer.toString(j);
int pos = s.length()-2;

s = StringUtils.overlay(s,".", pos, pos);

it's basically substring concatenation but shorter if you don't mind using libraries, or already depending on StringUtils

Serviceberry answered 10/4, 2019 at 11:17 Comment(0)
B
7

In most use-cases, using a StringBuilder (as already answered) is a good way to do this. However, if performance matters, this may be a good alternative.

/**
 * Insert the 'insert' String at the index 'position' into the 'target' String.
 * 
 * ````
 * insertAt("AC", 0, "") -> "AC"
 * insertAt("AC", 1, "xxx") -> "AxxxC"
 * insertAt("AB", 2, "C") -> "ABC
 * ````
 */
public static String insertAt(final String target, final int position, final String insert) {
    final int targetLen = target.length();
    if (position < 0 || position > targetLen) {
        throw new IllegalArgumentException("position=" + position);
    }
    if (insert.isEmpty()) {
        return target;
    }
    if (position == 0) {
        return insert.concat(target);
    } else if (position == targetLen) {
        return target.concat(insert);
    }
    final int insertLen = insert.length();
    final char[] buffer = new char[targetLen + insertLen];
    target.getChars(0, position, buffer, 0);
    insert.getChars(0, insertLen, buffer, position);
    target.getChars(position, targetLen, buffer, position + insertLen);
    return new String(buffer);
}
Bice answered 3/9, 2017 at 10:4 Comment(0)
W
6

For Kotlin dudes ;) from the accepted answer (@MikeThomsen's)

fun String.insert(insertAt: Int, string: String): String {
    return this.substring(0, insertAt) + string + this.substring(insertAt, this.length)
}

Test ✅

"ThisTest".insert(insertAt = 4, string = "Is").should.equal("ThisIsTest")
Wizen answered 29/3, 2020 at 18:3 Comment(0)
P
3

String.format("%0d.%02d", d / 100, d % 100);

Probable answered 28/10, 2019 at 20:54 Comment(1)
To whoever downvoted this: Re-read what the OP described in detail. This provides an exact answer to the problem: No floating point math. Puts the decimal point in the right place. To wit, https://mcmap.net/q/135457/-how-to-insert-a-character-in-a-string-at-a-certain-position provides a similar answer but uses floating point (not desired), and has 17 upvotes at this time.Probable
A
2

You could use

System.out.printf("%4.2f%n", ((float)12345)/100));

As per the comments, 12345/100.0 would be better, as would the use of double instead of float.

Afternoons answered 4/5, 2011 at 13:47 Comment(4)
double might be a better choice. float is only accurate to 6 digits.Orthographize
Yeah, another example someone responded with was to use 12345/100.0, which is smarter (although it ends up with the same result.)Afternoons
Nitpicking: I think this wont't give the right result, because 12345/100 = 123 in integer and is only cast to 123.00 afterwards. ((float)12345/100) would work.Superbomb
Heh, good point - I wasn't taking the precedence into account, mostly because the very first time he ran it it'd give him the truncated result. Will fix the post (which used to say 12345/100, then cast the result, instead of widening the value first.)Afternoons
S
0

If you are using a system where float is expensive (e.g. no FPU) or not allowed (e.g. in accounting) you could use something like this:

    for (int i = 1; i < 100000; i *= 2) {
        String s = "00" + i;
        System.out.println(s.substring(Math.min(2, s.length() - 2), s.length() - 2) + "." + s.substring(s.length() - 2));
    }

Otherwise the DecimalFormat is the better solution. (the StringBuilder variant above won't work with small numbers (<100)

Superbomb answered 4/5, 2011 at 13:59 Comment(2)
In the case of accounting, you'd be better off with BigDecimal.Afternoons
@Joseph: You are right. I'm not in accounting and I mostly use ints as a fixedpoint representation for performance reasons (in embedded java), so BigDecimal is not my choice ;-)Superbomb
F
0

I think a simpler and more elegant solution to insert a String in a certain position would be this one-liner:

target.replaceAll("^(.{" + position + "})", "$1" + insert);

For example, to insert a missing : into a time String:

"-0300".replaceAll("^(.{3})", "$1:");

What it does is, matches position characters from the beginning of the string, groups that, and replaces the group with itself ($1) followed by the insert string. Mind the replaceAll, even though there's always one occurrence, because the first parameter must be a regex.

Of course it does not have the same performance as the StringBuilder solution, but I believe the succinctness and elegance as a simple and easier to read one-liner (compared to a huge method) is sufficient for making it the preferred solution in most non performance-critical use-cases.

Note I'm solving the generic problem in the title for documentation reasons, of course if you are dealing with decimal numbers you should use the domain-specific solutions already proposed.

Fernandes answered 13/12, 2017 at 13:4 Comment(0)
M
0

There are good answers here, but with Kotlin extensions addition we can do it even more simply:

    val indexWhereInsertIsIntended = 2
    val inputString = "2408"
    val resultingString = inputString.toCharArray().toMutableList()
        .also { 
             it.add(indexWhereInsertIsIntended, '/') 
        }.joinToString("")

Result = 24/08

This example shows a card expiry date, and slash (/) is intended at 2nd Index. So the resulting index in this case will have / at 2nd index.

If you want to replace and not add:

val indexWhereInsertIsIntended = 2
        val inputString = "2408"
        val resultingString = inputString.toCharArray()
            .also { 
                 it[indexWhereInsertIsIntended] = '/' 
            }.joinToString("")

Result = 24/0

Mikkel answered 14/3, 2022 at 11:54 Comment(0)
S
-1
  public static void main(String[] args) {
    char ch='m';
    String str="Hello",k=String.valueOf(ch),b,c;

    System.out.println(str);

    int index=3;
    b=str.substring(0,index-1 );
    c=str.substring(index-1,str.length());
    str=b+k+c;
}
Spahi answered 15/1, 2017 at 18:59 Comment(0)
A
-1
// Create given String and make with size 30
String str = "Hello How Are You";

// Creating StringBuffer Object for right padding
StringBuffer stringBufferRightPad = new StringBuffer(str);
while (stringBufferRightPad.length() < 30) {
    stringBufferRightPad.insert(stringBufferRightPad.length(), "*");
}

System.out.println("after Left padding : " + stringBufferRightPad);
System.out.println("after Left padding : " + stringBufferRightPad.toString());

// Creating StringBuffer Object for right padding
StringBuffer stringBufferLeftPad = new StringBuffer(str);
while (stringBufferLeftPad.length() < 30) {
    stringBufferLeftPad.insert(0, "*");
}
System.out.println("after Left padding : " + stringBufferLeftPad);
System.out.println("after Left padding : " + stringBufferLeftPad.toString());
Adigun answered 20/6, 2018 at 14:1 Comment(2)
Welcome to Stack Overflow! Generally, answers are much more helpful if they include an explanation of what the code is intended to do, and why that solves the problem without introducing others. Thanks for improving the answer's reference value and making it more understandable!Etoile
Please don't use StringBuffer as it was replaced by StringBuilder in 2004.Orthographize
H
-2

Try this :

public String ConvertMessage(String content_sendout){

        //use unicode (004E00650077) need to change to hex (&#x004E&#x;0065&#x;0077;) first ;
        String resultcontent_sendout = "";
        int i = 4;
        int lengthwelcomemsg = content_sendout.length()/i;
        for(int nadd=0;nadd<lengthwelcomemsg;nadd++){
            if(nadd == 0){
                resultcontent_sendout = "&#x"+content_sendout.substring(nadd*i, (nadd*i)+i) + ";&#x";
            }else if(nadd == lengthwelcomemsg-1){
                resultcontent_sendout += content_sendout.substring(nadd*i, (nadd*i)+i) + ";";
            }else{
                resultcontent_sendout += content_sendout.substring(nadd*i, (nadd*i)+i) + ";&#x";
            }
        }
        return resultcontent_sendout;
    }
Hunfredo answered 10/8, 2018 at 4:1 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.