Làm thế nào để chèn một ký tự trong một chuỗi ở một vị trí nhất định?


155

Tôi đang nhận được intvới một giá trị 6 chữ số. Tôi muốn hiển thị nó dưới dạng Stringdấu thập phân (.) Ở 2 chữ số từ cuối int. Tôi muốn sử dụng một floatnhưng được đề xuất sử dụng Stringcho đầu ra hiển thị tốt hơn (thay vì 1234.5sẽ được 1234.50). Do đó, tôi cần một hàm sẽ lấy inttham số làm và trả về định dạng đúng Stringvới dấu thập phân 2 chữ số từ cuối.

Nói:

int j= 123456 
Integer.toString(j); 

//processing...

//output : 1234.56

1
String str = Integer.toString(j); //integer or string with white spaces<br/> str = new StringBuffer(str.trim()).insert(str.length()-2, ".").toString();
dùng881703

Câu trả lời:


195
int j = 123456;
String x = Integer.toString(j);
x = x.substring(0, 4) + "." + x.substring(4, x.length());

6
Dây là bất biến. Trong khi điều này hoạt động, sử dụng một cái gì đó như StringBuilder là chính xác về mặt đạo đức, không đề cập đến sẽ làm cho mã của bạn nhanh hơn.
whereesmycookie 20/07/13

7
Quên StringBuilder. Với định dạng như thế này, String.format là tùy chọn tốt nhất hiện có.
NobleUplift

33
Không có vòng lặp, đó là trường hợp nối đơn giản và trình biên dịch nên tối ưu hóa nó bằng trình tạo chuỗi, để dễ đọc tôi thích sử dụng toán tử +, trong trường hợp này không cần sử dụng StringBuilder một cách rõ ràng. Sử dụng giải pháp "StringBuilder" vì nó nhanh hơn không tôn trọng các quy tắc tối ưu hóa. Mã cho dễ đọc. Tối ưu hóa sau khi định hình và chỉ khi cần thiết. vi.wikipedia.org/wiki/Program_optimization#Quotes
Remi Morin

17
Bạn không cần x.length () trong cuộc gọi chuỗi con thứ hai.
crazyGuy

1
Giải pháp này sẽ thất bại khi số là một số chữ số khác nhau. Đối với 12345, nó sẽ xuất ra 1234,5 và đối với 1234567, nó sẽ là 1234,567. Nếu bạn luôn muốn 2 chữ số cuối cùng nằm sau dấu thập phân, hãy đảm bảo rằng số đó có ít nhất 3 chữ số và sau đó thực hiệnx = x.substring(0, x.length()-2) + "." + x.substring(x.length()-2);
Teodor Marinescu

210

Như đã đề cập trong các bình luận, StringBuilder có thể là một triển khai nhanh hơn so với sử dụng StringBuffer . Như đã đề cập trong các tài liệu Java:

Lớp này cung cấp API tương thích với StringBuffer, nhưng không đảm bảo đồng bộ hóa. Lớp này được thiết kế để sử dụng như là một thay thế thả xuống cho StringBuffer ở những nơi mà bộ đệm chuỗi đang được sử dụng bởi một luồng duy nhất (như thường là trường hợp). Nếu có thể, lớp này được khuyến nghị sử dụng theo ưu tiên cho StringBuffer vì nó sẽ nhanh hơn trong hầu hết các triển khai.

Sử dụng :

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

Hoặc nếu bạn cần đồng bộ hóa, hãy sử dụng StringBuffer với cách sử dụng tương tự:

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

1
Giải pháp này hoạt động với mọi chuỗi> = 4 ký tự: chuỗi "111" đã cho tôi ".111" và bất cứ điều gì ít hơn kết quả đó java.lang.StringIndexOutOfBoundsException(cố gắng truy cập một tham chiếu không tồn tại).
sotrh

17
int yourInteger = 123450;
String s = String.format("%6.2f", yourInteger / 100.0);
System.out.println(s);

Tôi sẽ đề nghị sử dụng java.math.BigDecimalnhư sử dụng doublecó thể gây ra lỗi làm tròn . Nếu tốc độ có giá trị hơn độ chính xác doublethì tốt hơn.
sotrh

5

Trong hầu hết các trường hợp sử dụng, sử dụng một StringBuilder(như đã trả lời) là một cách tốt để làm điều này. Tuy nhiên, nếu hiệu suất có vấn đề, đây có thể là một lựa chọn tốt.

/**
 * 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);
}

4

Sử dụng ApacheUommons3 StringUtils, bạn cũng có thể làm

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

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

về cơ bản, đó là nối chuỗi con nhưng ngắn hơn nếu bạn không sử dụng các thư viện hoặc đã phụ thuộc vào StringUtils


2

Bạn đã có thể sử dụng

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

Theo nhận xét, 12345 / 100.0 sẽ tốt hơn, cũng như việc sử dụng gấp đôi thay vì thả nổi.


2
doublecó thể là một lựa chọn tốt hơn float chỉ chính xác đến 6 chữ số.
Peter Lawrey

1
Vâng, một ví dụ khác mà ai đó đã phản hồi là sử dụng 12345 / 100.0, thông minh hơn (mặc dù kết quả tương tự.)
Joseph Ottinger

Nitpicking: Tôi nghĩ rằng điều này sẽ không cho kết quả đúng, bởi vì 12345/100 = 123 trong số nguyên và chỉ được chuyển thành 123.00 sau đó. ((float) 12345/100) sẽ hoạt động.
rurouni

Heh, điểm tốt - tôi đã không được ưu tiên, chủ yếu là vì lần đầu tiên anh ta chạy nó sẽ cho anh ta kết quả bị cắt cụt. Sẽ sửa bài (trước đây là 12345/100, sau đó bỏ kết quả, thay vì mở rộng giá trị trước.)
Joseph Ottinger

0

Nếu bạn đang sử dụng một hệ thống mà float là đắt tiền (ví dụ: không có FPU) hoặc không được phép (ví dụ như trong kế toán), bạn có thể sử dụng một cái gì đó như thế này:

    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));
    }

Nếu không, DecimalFormat là giải pháp tốt hơn. (biến thể StringBuilder ở trên sẽ không hoạt động với số lượng nhỏ (<100)


2
Trong trường hợp kế toán, bạn sẽ tốt hơn với BigDecimal.
Joseph Ottinger

@Joseph: Bạn nói đúng. Tôi không làm kế toán và tôi chủ yếu sử dụng ints làm đại diện cho điểm cố định vì lý do hiệu suất (trong java nhúng), vì vậy BigDecimal không phải là lựa chọn của tôi ;-)
rurouni

0

Tôi nghĩ rằng một giải pháp đơn giản và thanh lịch hơn để chèn Chuỗi vào một vị trí nhất định sẽ là một lớp lót này:

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

Ví dụ: để chèn thiếu :vào Chuỗi thời gian:

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

Những gì nó làm là, khớp các positionký tự từ đầu chuỗi, các nhóm và thay thế nhóm bằng chính nó ( $1) theo sau làinsert chuỗi. Hãy nhớ thay thế, mặc dù luôn có một lần xuất hiện, bởi vì tham số đầu tiên phải là biểu thức chính quy.

Tất nhiên nó không có hiệu năng như giải pháp StringBuilder, nhưng tôi tin rằng sự gọn gàng và thanh lịch là một cách đơn giản và dễ đọc hơn (so với một phương pháp khổng lồ) là đủ để biến nó thành giải pháp ưa thích trong hầu hết các hoạt động không hiệu quả trường hợp sử dụng -critical.

Lưu ý Tôi đang giải quyết vấn đề chung trong tiêu đề vì lý do tài liệu, tất nhiên nếu bạn đang xử lý số thập phân, bạn nên sử dụng các giải pháp dành riêng cho tên miền đã được đề xuất.


0

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


Cho bất cứ ai hạ thấp điều này: Đọc lại những gì OP mô tả chi tiết. Điều này cung cấp một câu trả lời chính xác cho vấn đề: Không có toán học dấu phẩy động. Đặt dấu thập phân ở đúng nơi. Để dí dỏm, stackoverflow.com/a/5884413/972128 cung cấp một câu trả lời tương tự nhưng sử dụng dấu phẩy động (không mong muốn) và có 17 upvote tại thời điểm này.
kkurian

0

Dành cho các anh chàng Kotlin;) từ câu trả lời được chấp nhận (@ MikeThomsen)

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

Kiểm tra

"ThisTest".insert(4, "Is").should.equal("ThisIsTest")

-2
  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;
}

-2
// 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());

2
Chào mừng bạn đến với Stack Overflow! Nói chung, câu trả lời sẽ hữu ích hơn nhiều nếu chúng bao gồm một lời giải thích về những gì mã được dự định làm và tại sao điều đó giải quyết vấn đề mà không giới thiệu người khác. Cảm ơn vì đã cải thiện giá trị tham khảo của câu trả lời và làm cho nó dễ hiểu hơn!
Tim Diekmann

Vui lòng không sử dụng StringBuffer vì nó đã được thay thế bởi StringBuilder vào năm 2004.
Peter Lawrey

-2

Thử cái này :

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;
    }
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.