Comment insérer un caractère dans une chaîne à une certaine position?

155

J'entre dans un intavec une valeur à 6 chiffres. Je veux l'afficher sous la forme Stringd' un avec un point décimal (.) À 2 chiffres à partir de la fin de int. Je voulais utiliser un floatmais il a été suggéré de l'utiliser Stringpour une meilleure sortie d'affichage (au lieu de 1234.5l'être 1234.50). Par conséquent, j'ai besoin d'une fonction qui prendra un intcomme paramètre et retournera le correctement formaté Stringavec un point décimal à 2 chiffres de la fin.

Dire:

int j= 123456 
Integer.toString(j); 

//processing...

//output : 1234.56
daverocks
la source
1
String str = Integer.toString(j); //integer or string with white spaces<br/> str = new StringBuffer(str.trim()).insert(str.length()-2, ".").toString();
user881703

Réponses:

195
int j = 123456;
String x = Integer.toString(j);
x = x.substring(0, 4) + "." + x.substring(4, x.length());
Mike Thomsen
la source
6
Les chaînes sont immuables. Bien que cela fonctionne, utiliser quelque chose comme StringBuilder est moralement correct, sans oublier que votre code sera plus rapide.
wheresmycookie
7
Oubliez StringBuilder. Avec un formatage comme celui-ci, String.format est la meilleure option disponible.
NobleUplift
33
Il n'y a pas de boucle, c'est un cas de concaténation simple et le compilateur devrait l'optimiser à l'aide d'un générateur de chaîne, pour la lisibilité je préfère utiliser l'opérateur +, il n'est pas nécessaire dans ce cas d'utiliser StringBuilder explicitement. Utiliser la solution "StringBuilder" parce qu'elle est plus rapide ne respecte pas les règles d'optimisation. Code de lisibilité. Optimisez après le profilage et uniquement là où cela est nécessaire. en.wikipedia.org/wiki/Program_optimization#Quotes
Remi Morin
17
Vous n'avez pas besoin de x.length () lors du deuxième appel de sous-chaîne.
crazyGuy
1
Cette solution échouera lorsque le nombre est un nombre différent de chiffres. Pour 12345, il affichera 1234,5 et pour 1234567, il sera 1234,567. Si vous voulez toujours que les 2 derniers chiffres soient après la virgule décimale, assurez-vous que le nombre comporte au moins 3 chiffres, puis faitesx = x.substring(0, x.length()-2) + "." + x.substring(x.length()-2);
Teodor Marinescu
210

Comme mentionné dans les commentaires, un StringBuilder est probablement une implémentation plus rapide que l'utilisation d'un StringBuffer . Comme mentionné dans la documentation Java:

Cette classe fournit une API compatible avec StringBuffer, mais sans aucune garantie de synchronisation. Cette classe est conçue pour être utilisée en remplacement de StringBuffer dans les endroits où le tampon de chaîne était utilisé par un seul thread (comme c'est généralement le cas). Lorsque cela est possible, il est recommandé d'utiliser cette classe de préférence à StringBuffer car elle sera plus rapide dans la plupart des implémentations.

Utilisation:

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

Ou si vous avez besoin d'une synchronisation, utilisez le StringBuffer avec une utilisation similaire:

String str = Integer.toString(j);
str = new StringBuffer(str).insert(str.length()-2, ".").toString();
blo0p3r
la source
1
Cette solution fonctionne pour toute chaîne> = 4 caractères: la chaîne "111" m'a donné ".111", et rien de moins que cela entraîne un java.lang.StringIndexOutOfBoundsException(tentative d'accès à une référence qui n'existe pas).
sotrh
17
int yourInteger = 123450;
String s = String.format("%6.2f", yourInteger / 100.0);
System.out.println(s);
Itay Maman
la source
Je suggérerais d'utiliser java.math.BigDecimalcar l'utilisation doublepeut provoquer une erreur d'arrondi . Si la vitesse est plus précieuse que la précision, doublec'est mieux.
sotrh
5

Dans la plupart des cas d'utilisation, utiliser un StringBuilder(comme déjà répondu) est un bon moyen de le faire. Cependant, si la performance compte, cela peut être une bonne 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);
}
rmuller
la source
4

En utilisant ApacheCommons3 StringUtils, vous pouvez également faire

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

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

c'est essentiellement une concaténation de sous-chaînes mais plus courte si cela ne vous dérange pas d'utiliser des bibliothèques, ou déjà en fonction de StringUtils

cornichon
la source
2

Vous pourriez utiliser

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

Selon les commentaires, 12345 / 100.0 serait mieux, tout comme l'utilisation de double au lieu de float.

Joseph Ottinger
la source
2
doublepourrait être un meilleur choix. float n'est précis qu'à 6 chiffres.
Peter Lawrey
1
Oui, un autre exemple auquel quelqu'un a répondu était d'utiliser 12345 / 100.0, ce qui est plus intelligent (bien que cela aboutisse au même résultat.)
Joseph Ottinger
Nitpicking: Je pense que cela ne donnera pas le bon résultat, car 12345/100 = 123 en entier et n'est ensuite converti qu'en 123,00. ((float) 12345/100) fonctionnerait.
rurouni
Hé, bon point - je ne tenais pas compte de la priorité, principalement parce que la toute première fois qu'il l'a exécuté, cela lui donnerait le résultat tronqué. Corrige le message (qui disait 12345/100, puis lance le résultat, au lieu d'élargir d'abord la valeur.)
Joseph Ottinger
0

Si vous utilisez un système où le flottant coûte cher (par exemple pas de FPU) ou n'est pas autorisé (par exemple en comptabilité), vous pouvez utiliser quelque chose comme ceci:

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

Sinon, le DecimalFormat est la meilleure solution. (la variante StringBuilder ci-dessus ne fonctionnera pas avec de petits nombres (<100)

rurouni
la source
2
Dans le cas de la comptabilité, vous seriez mieux avec BigDecimal.
Joseph Ottinger
@Joseph: Vous avez raison. Je ne suis pas en comptabilité et j'utilise principalement ints comme représentation en virgule fixe pour des raisons de performances (en java embarqué), donc BigDecimal n'est pas mon choix ;-)
rurouni
0

Je pense qu'une solution plus simple et plus élégante pour insérer une chaîne dans une certaine position serait ce one-liner:

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

Par exemple, pour insérer un manquant :dans une chaîne de temps:

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

Il fait correspondre les positioncaractères du début de la chaîne, les groupes et remplace le groupe par lui-même ( $1) suivi de la insertchaîne. Faites attention à replaceAll, même s'il y a toujours une occurrence, car le premier paramètre doit être une expression régulière.

Bien sûr, elle n'a pas les mêmes performances que la solution StringBuilder, mais je pense que la concision et l'élégance en tant que one-liner simple et plus facile à lire (par rapport à une énorme méthode) sont suffisantes pour en faire la solution préférée dans la plupart des non-performances. -cas d'utilisation critiques.

Remarque Je résous le problème générique dans le titre pour des raisons de documentation, bien sûr, si vous avez affaire à des nombres décimaux, vous devez utiliser les solutions spécifiques au domaine déjà proposées.

Luan Nico
la source
0

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

kkurian
la source
À quiconque a critiqué ceci: Relisez ce que le PO a décrit en détail. Cela fournit une réponse exacte au problème: pas de calcul en virgule flottante. Place le point décimal au bon endroit. À savoir, stackoverflow.com/a/5884413/972128 fournit une réponse similaire mais utilise la virgule flottante (non souhaitée) et compte 17 votes positifs pour le moment.
kkurian le
0

Pour les mecs Kotlin;) de la réponse acceptée (@ 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")
theapache64
la source
-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;
}
Miya
la source
-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());
Nagendra Mishra
la source
2
Bienvenue dans Stack Overflow! En général, les réponses sont beaucoup plus utiles si elles incluent une explication de ce que le code est censé faire et pourquoi cela résout le problème sans en présenter d'autres. Merci d'améliorer la valeur de référence de la réponse et de la rendre plus compréhensible!
Tim Diekmann
Veuillez ne pas utiliser StringBuffer car il a été remplacé par StringBuilder en 2004.
Peter Lawrey
-2

Essaye ça :

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;
    }
Pattanai Pornpibul
la source