Jak wstawić znak do ciągu w określonej pozycji?


155

Otrzymuję int6-cyfrową wartość. Chcę go wyświetlić jako Stringz kropką dziesiętną (.) Na 2 cyfry od końca int. Chciałem użyć, floatale zasugerowano użycie Stringdla lepszego wyświetlania (zamiast 1234.5będzie 1234.50). Dlatego potrzebuję funkcji, która przyjmie intparametr as i zwróci odpowiednio sformatowany Stringz przecinkiem dziesiętnym 2 cyfry od końca.

Mówić:

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();
user881703

Odpowiedzi:


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

6
Ciągi znaków są niezmienne. Chociaż to działa, użycie czegoś takiego jak StringBuilder jest moralnie poprawne, nie wspominając o tym, że twój kod będzie szybszy.
wheresmycookie

7
Zapomnij o StringBuilder. W przypadku takiego formatowania, String.format jest najlepszą dostępną opcją.
NobleUplift,

33
Nie ma pętli, jest to prosty przypadek konkatenacji i kompilator powinien go zoptymalizować za pomocą konstruktora ciągów, dla czytelności wolę używać operatora +, w tym przypadku nie ma potrzeby jawnego używania StringBuilder. Korzystanie z rozwiązania „StringBuilder”, ponieważ jest szybsze, nie przestrzega reguł optymalizacji. Kod czytelności. Optymalizuj po profilowaniu i tylko wtedy, gdy jest to wymagane. en.wikipedia.org/wiki/Program_optimization#Quotes
Remi Morin

17
Nie potrzebujesz x.length () w drugim wywołaniu podłańcucha.
crazyGuy

1
To rozwiązanie nie powiedzie się, jeśli liczba ma inną liczbę cyfr. Dla 12345 wyświetli 1234,5, a dla 1234567 będzie to 1234,567. Jeśli zawsze chcesz, aby ostatnie 2 cyfry były po przecinku, upewnij się, że liczba ma co najmniej 3 cyfry, a następnie zróbx = x.substring(0, x.length()-2) + "." + x.substring(x.length()-2);
Teodor Marinescu

210

Jak wspomniano w komentarzach, StringBuilder jest prawdopodobnie szybszą implementacją niż użycie StringBuffer . Jak wspomniano w dokumentacji Java:

Ta klasa zapewnia interfejs API zgodny z StringBuffer, ale bez gwarancji synchronizacji. Ta klasa została zaprojektowana do użycia jako zamiennik typu drop-in dla StringBuffer w miejscach, w których bufor ciągu był używany przez pojedynczy wątek (jak to zwykle ma miejsce). Tam, gdzie to możliwe, zaleca się używanie tej klasy zamiast StringBuffer, ponieważ będzie ona szybsza w większości implementacji.

Stosowanie :

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

Lub jeśli potrzebujesz synchronizacji, użyj StringBuffer z podobnym zastosowaniem:

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

1
To rozwiązanie działa dla dowolnego ciągu> = 4 znaków: ciąg "111" dał mi ".111", a wszystko mniejsze niż to skutkuje java.lang.StringIndexOutOfBoundsException(próbą dostępu do odniesienia, które nie istnieje).
sotrh

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

Sugerowałbym użycie, java.math.BigDecimalponieważ używanie doublemoże powodować błąd zaokrąglania . Jeśli prędkość jest bardziej wartościowa, doubleto precyzja jest lepsza.
sotrh

5

W większości przypadków użycie StringBuilder(jak już udzielono) jest dobrym sposobem na zrobienie tego. Jeśli jednak liczy się wydajność, może to być dobra alternatywa.

/**
 * 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

Używając ApacheCommons3 StringUtils, możesz również to zrobić

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

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

jest to w zasadzie konkatenacja podciągów, ale krótsza, jeśli nie masz nic przeciwko używaniu bibliotek lub już w zależności od StringUtils


2

Możesz użyć

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

Zgodnie z komentarzami, 12345 / 100.0 byłoby lepsze, podobnie jak użycie double zamiast float.


2
doublemoże być lepszym wyborem. liczba zmiennoprzecinkowa jest dokładna tylko do 6 cyfr.
Peter Lawrey

1
Tak, innym przykładem, którym ktoś odpowiedział, było użycie 12345 / 100.0, co jest mądrzejsze (chociaż kończy się z tym samym wynikiem).
Joseph Ottinger

Nitpicking: Myślę, że to nie da właściwego wyniku, ponieważ 12345/100 = 123 w liczbie całkowitej i jest następnie rzutowane tylko na 123,00. ((float) 12345/100) zadziała.
rurouni

Heh, słuszna uwaga - nie brałem pod uwagę pierwszeństwa, głównie dlatego, że przy pierwszym uruchomieniu dałoby mu to skrócony wynik. Naprawi post (który kiedyś mówił 12345/100, a następnie rzutował wynik, zamiast najpierw poszerzać wartość).
Joseph Ottinger

0

Jeśli używasz systemu, w którym zmiennoprzecinkowy jest drogi (np. Nie ma FPU) lub niedozwolony (np. W księgowości), możesz użyć czegoś takiego:

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

W przeciwnym razie DecimalFormat jest lepszym rozwiązaniem. (powyższy wariant StringBuilder nie będzie działał z małymi liczbami (<100)


2
W przypadku księgowości lepiej byłoby z BigDecimal.
Joseph Ottinger

@Joseph: Masz rację. Nie zajmuję się księgowością i głównie używam ints jako reprezentacji stałej wartości ze względu na wydajność (we wbudowanej Javie), więc BigDecimal nie jest moim wyborem ;-)
rurouni

0

Myślę, że prostszym i bardziej eleganckim rozwiązaniem, aby wstawić String w określonej pozycji, byłoby to jednowierszowe:

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

Na przykład, aby wstawić brakujący :ciąg znaków czasu:

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

To, co robi, polega na dopasowywaniu positionznaków z początku ciągu, grupowaniu tych znaków i zastępowaniu grupy samą sobą ( $1), po której następuje insertciąg. Uważaj na replaceAll, nawet jeśli zawsze występuje jedno wystąpienie, ponieważ pierwszy parametr musi być wyrażeniem regularnym.

Oczywiście nie ma takiej samej wydajności, jak rozwiązanie StringBuilder, ale uważam, że zwięzłość i elegancja jako prosta i łatwiejsza do odczytania jedna linijka (w porównaniu do ogromnej metody) jest wystarczająca, aby uczynić ją preferowanym rozwiązaniem w większości przypadków braku wydajności -krytyczne przypadki użycia.

Uwaga Rozwiązuję ogólny problem w tytule ze względów dokumentacyjnych, oczywiście jeśli masz do czynienia z liczbami dziesiętnymi, powinieneś użyć proponowanych już rozwiązań specyficznych dla domeny.


0

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


Do każdego, kto przegłosował to: przeczytaj ponownie, co szczegółowo opisał PO. To zapewnia dokładną odpowiedź na problem: brak matematyki zmiennoprzecinkowej. Umieszcza kropkę dziesiętną we właściwym miejscu. Na przykład stackoverflow.com/a/5884413/972128 zapewnia podobną odpowiedź, ale używa liczby zmiennoprzecinkowej (niepożądane) i ma w tej chwili 17 głosów za.
kkurian

0

Dla Kotlin dudes;) z zaakceptowanej odpowiedzi (@ MikeThomsen's)

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

Test ✅

"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
Witamy w Stack Overflow! Ogólnie odpowiedzi są znacznie bardziej pomocne, jeśli zawierają wyjaśnienie, do czego służy kod i dlaczego to rozwiązuje problem bez wprowadzania innych. Dziękujemy za poprawienie wartości referencyjnej odpowiedzi i uczynienie jej bardziej zrozumiałą!
Tim Diekmann

Proszę nie używać StringBuffer, ponieważ został on zastąpiony przez StringBuilder w 2004 roku.
Peter Lawrey

-2

Spróbuj tego :

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;
    }
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.