-3

I've been experimenting with a calculator application for my AP CSP class and have hit a roadblock in development. I've been trying to format all numbers in a string to add commas though is it proving to be rather difficult.

Here is an example of the input and output I'm trying to achieve:

Input: "1081+34-3954"
Output: "1,081+34-3,954"

I've tried messing with String#split but that didn't really do the trick as it became very large and repetitive.

Mark Rotteveel
  • 100,966
  • 191
  • 140
  • 197
Lightcaster5
  • 81
  • 10
  • 1
    "I've tried messing with String#split but that didn't really do the trick as it became very large and repetitive." -- it'd be great to see this code as a [mcve] showing the problem. – ggorlen Jan 10 '21 at 01:06
  • [This thread](https://stackoverflow.com/questions/3672731/how-can-i-format-a-string-number-to-have-commas-and-round) might help, but you'll still need to parse out the numbers, probably using a regex like `\\d+` and `replaceAll` or similar. – ggorlen Jan 10 '21 at 01:16
  • You could split on "\\b" which splits on the boundaries between words. – NomadMaker Jan 10 '21 at 03:06
  • If s is your first example, then ``s.split("\\b")`` splits into "1081", "+", "34", "-", "3954" – NomadMaker Jan 10 '21 at 03:09

3 Answers3

2

You can do it like this using regular expressions.

  • (\\d+) - capture block one for integer.
  • ([+-]|$) - capture block two for the operator or end of line
String s = "1081+34-3954";

Pattern p = Pattern.compile("(\\d+)([/*+-]|$)");
Matcher m = p.matcher(s);

StringBuilder sb = new StringBuilder();

while (m.find()) {
    sb.append(String.format("%,d%s", Integer.valueOf(m.group(1)), m.group(2)));
}
String result = sb.toString();

System.out.println(result);

Prints

1,081+34-3,954
  • String.format() takes same arguments as System.out.printf()
  • %,d formats an integer with commas for the thousands grouping separator
  • %s is for a string to obtain the operator.

However, if this is just an example and your pattern is more complicated you will have to adjust it. Check out the following for more information.

WJS
  • 36,363
  • 4
  • 24
  • 39
  • It worked at first but after further testing, if the string contains a '*' or '/', it breaks. Thanks so far! – Lightcaster5 Jan 10 '21 at 01:42
  • *Warning:* Result is locale-dependent, e.g. in France, the result is `1 081+34-3 954`. – Andreas Jan 10 '21 at 01:43
  • @Lightcaster5 I did say in my answer that if the String was more complicated you would have to adjust. So add `/` and `*` between the `[]` of the character class as I did for you. And you can change the group separator by specifying `Locale` in the String.format method which I also provided a link too. – WJS Jan 10 '21 at 02:09
  • @WJS, sorry I must've read over that part. Everything is functioning as expected! I greatly appreciate your help, your solution is very smart! – Lightcaster5 Jan 10 '21 at 02:15
0

You can use regex replacement, by searching for the numbers, then parsing and reformatting them.

In Java 9+, do it like this:

String input = "1081+34-3954";

DecimalFormat fmt = new DecimalFormat("#,##0", DecimalFormatSymbols.getInstance(Locale.US));
String result = Pattern.compile("\\d+{4,}").matcher(input)
                       .replaceAll(n -> fmt.format(Long.parseLong(n.group())));
System.out.println(result); // prints: 1,081+34-3,954

Any text that is not a 4+ digit number is left untouched.

In older Java versions, use a replacement loop:

String input = "1081+34-3954";

DecimalFormat fmt = new DecimalFormat("#,##0", DecimalFormatSymbols.getInstance(Locale.US));
StringBuffer buf = new StringBuffer();
Matcher m = Pattern.compile("\\d+{4,}").matcher(input);
while (m.find())
    m.appendReplacement(buf, fmt.format(Long.parseLong(m.group())));
String result = m.appendTail(buf).toString();
System.out.println(result); // prints: 1,081+34-3,954
Andreas
  • 154,647
  • 11
  • 152
  • 247
0

You can just use simple String and StringBuilder methods:

public class Test {
  public static String splitStr(String input) {
    StringBuilder str = new StringBuilder();
    boolean change = false;
    if (input.charAt(input.length() - 1) != '+' || input.charAt(input.length() - 1) != '-') {
      input = new StringBuilder(input).append('+').toString();
      change = true;
    }
    int lastIdx = 0;
    for(int i = 0; i < input.length(); i++){
      StringBuilder subStr = new StringBuilder();
      if (input.charAt(i) == '-' || input.charAt(i) == '+') {
       subStr.append(input.substring(lastIdx,i));
       for(int j = subStr.length() - 3; j >= 0; j-=3) {
        subStr.insert(j, ',');
       } 
       lastIdx = i + 1;
      str.append(subStr);
      str.append(input.charAt(i));
      }
    } 
    if (change) {
      str.delete(str.length() - 1, str.length());
    }
    return str.toString();
  }
  public static void main (String[] args) {
    String str = "1081+34-3954";
    String newStr = splitStr(str);
    System.out.println(newStr);
  }
}
Nam V. Do
  • 630
  • 6
  • 27