2

I want split a string for example: 5121321 in 5 121 321, every 3 is a ' '. I have that code:

private void compor()
{
    String dinheiro="5121321";

    char aux[]= new char[dinheiro.length()];

    for(int i=0;i<dinheiro.length();i++)
    {
       aux[i]=dinheiro.charAt(i);
    }

    int flag=0;

    String total="";
    for(int i=0;i<dinheiro.length();i++)
    {
        if(flag==3)
        {
            total+=' ';
            flag=0;
        }

        total += String.valueOf(aux[i]);
        flag++;
    }
    TextView txt = (TextView) findViewById(R.id.textView3);
    txt.setText(String.valueOf(total));
}

The problem is the output of this is: 512 132 1 and i want 5 121 321. Sorry my english. Somebody can help me?Thanks.

  • 1
    A quick fix would be initializing `int flag` with 2 instead of 0, but you should also consider the other tips in the answers. – Tom Aug 11 '14 at 22:09

5 Answers5

4

It looks like you're just trying to do general numeric formatting. A simple solution using framework utilities is:

public static String splitNumericString(String numeric) throws NumberFormatException {
    // Create a new DecimalFormatSymbols instance and set the
    // grouping separator to a space character
    DecimalFormatSymbols symbols = new DecimalFormatSymbols();
    symbols.setGroupingSeparator(' ');

    // Construct a new NumberFormat defining a 3 digit grouping
    // pattern
    NumberFormat format = new DecimalFormat("#,###", symbols);

    // Converts the string into an actual numeric value
    long number = Long.parseLong(numeric);

    // Return the formatted string
    return format.format(number);
}

EDIT: Given @Squonk's info, this becomes a one-liner:

return NumberFormat.getInstance(Locale.FRANCE).format(Long.parseLong(numeric));

Although you should catch the NumberParseException in case of an improperly formatted input string.

Kevin Coppock
  • 133,643
  • 45
  • 263
  • 274
  • 1
    This is quite a bit of a hack, relying on the US locale to use `,` as grouping separator and then replacing those commas with spaces... Perhaps it'd be better to use the right locale to begin with, or pass in a custom pattern and `DecimalFormatSymbols` to the `DecimalFormat` constructor? – Mattias Buelens Aug 11 '14 at 22:20
  • Yeah, it's unclear what his end result really needed to be, but using ' ' as a separator didn't seem like a standard locale result. But yes, you could use a custom DecimalFormat instance -- I'll update to that. – Kevin Coppock Aug 11 '14 at 22:21
  • 2
    @kcoppock : WRT a locale that uses that format - the French (possibly not the only country) use a space for a separator and a comma instead of a decimal point. Example, "1,234.5" would be "1 234,5". Just thought you'd like to know for reference. – Squonk Aug 11 '14 at 22:40
2

(1) Just loop backwards through the string. And use pretty much the same idea you used. This will split it the way you want. (2) Alternatively, you can calculate where the first full triple starts by using the % (modulo) operator (I mean string length % 3).

Sample code for approach (2):

public class Test007 {

    public static void main(String[] args) {

        String dinheiro="5121322";

        int i = dinheiro.length() % 3;

        String s1 = "";

        s1 = dinheiro.substring(0, i);

        String s2 = "";

        for (int k=i; k<dinheiro.length(); k+=3){
            if (k!=i || i>0){
                s2 += " ";
            }
            s2 += dinheiro.substring(k, k+3);
        }

        System.out.println(s1 + s2);

    }

}
peter.petrov
  • 38,363
  • 16
  • 94
  • 159
  • Well, this work 100% but i dont understand mo mutch that code:( – you are been banned Aug 11 '14 at 22:17
  • 1
    I just find where the first full triple starts - at position i. Then I loop skipping 3 chars each time. It's simple. I append " " in between only if i is not zero (i.e. i>0) OR if that's not the first iteration of the loop (i.e. if k!=i). That's exactly when I need to append " " in between. – peter.petrov Aug 11 '14 at 22:23
  • That `if` check can only ever become `false` in one loop iteration, right? You should be able to move it out of the loop. Also, it'd probably help to use meaningful variable names and add some comments where appropriate to help the OP and others in understanding your code. :-) – Mattias Buelens Aug 11 '14 at 22:27
1

Instead of catenating in a loop, use a stringbuilder:

String input = /*...*/;
StringBuilder sb = new StringBuilder();
int i = 2;
for (char c : input.toCharArray()) {
    sb.append(c);
    i++;
    if (i == 3) {
        sb.append(' ');
        i = 0;
    }
}
String result = sb.toString();
Rogue
  • 11,105
  • 5
  • 45
  • 71
  • for that is `String result = sb.toString();`? – you are been banned Aug 11 '14 at 22:11
  • 1
    That 'magical number' `i = 2` will only work for the sample input. For example, `12345` should become `12 345` but your snippet would output `1 234 5`. Sure, a `StringBuilder` is more efficient than repeated concatenation, but make the code *work* before you try to make it fast. – Mattias Buelens Aug 11 '14 at 22:11
  • @MattiasBuelens I understand it's a magic number, my understanding from reading the question was it should always start with a single number. – Rogue Aug 11 '14 at 23:02
  • 1
    @Rogue No, it seems the OP is trying to do simple [digit grouping](http://en.wikipedia.org/wiki/Decimal_mark#Digit_grouping) using a space as thousands separator (which is commonly used in European countries). I have to admit, just *one* sample input and output without much context does leave a lot to be guessed. :-P – Mattias Buelens Aug 11 '14 at 23:06
0

Here's a variant to Peter Petrov's solution:

public static String group(String in) {
    // Get the length of the first group
    int i = (in.length() - 1) % 3 + 1;

    // Add the first group
    String out = in.substring(0, i);

    // Add the other groups, each prefixed with a space
    for (int k = i; k < in.length(); k += 3){
        out += " " + in.substring(k, k + 3);
    }

    return out;
}

We get the length of the first group, we initialize the output with that first group and then we go over the remainder of the input to append one group of 3 digits at a time. That's really all there is to it.

The tricky bit is in the first line. Just using in.length() % 3 doesn't work correctly, since that prevents the first group from ever having 3 digits. For example, an input of "123456" would lead to i == 0 and an output of " 123 456" (note the unwanted space at the start). Peter uses an if check to deal with this case, but it turns out you can also handle it by changing i a bit.

We want the relation between in.length() and i to be like this:

in.length() |   i | (in.length() - 1) % 3
------------------------------------------
         0  |   0 |                    -1
         1  |   1 |                     0
         2  |   2 |                     1
         3  |   3 |                     2
         4  |   1 |                     0
         5  |   2 |                     1
       ...  | ... |                   ...

Subtracting one before the modulo and adding it back afterwards gives us this relation (the partial result after the modulo is in the third column). It even handles the special case where in is the empty string! :-P

Mattias Buelens
  • 19,609
  • 4
  • 45
  • 51
0

The solution is easier to write with simple arithmetic than with string manipulation:

public static String groupDigits(int amount) {  
    String total = "";

    while (amount > 0) {
        Integer digits = amount % 1000;
        amount = amount / 1000;
        total = digits.toString() + " " + total;
    }

    return total;
}
x-code
  • 2,940
  • 1
  • 18
  • 19