Decimal Format error - java

I have to convert string welcome into number format. But when I'm going to execute it throws exception
Exception in thread "main" java.text.ParseException: Unparseable number: "Welcome"
at java.text.NumberFormat.parse(Unknown Source)
at sample.Sam.main(Sam.java:13)
package sample;
import java.text.DecimalFormat;
import java.text.ParseException;
public class Sam {
public static void main(String[] args) throws ParseException {
// TODO Auto-generated method stub
String str="Welcome,#123";
DecimalFormat df = new DecimalFormat(str);
System.out.println( df.parse(str));
}
}

The code you shared does no throw the Exception you copied...
Anyway, here is a code that will extract an integer from any string:
String str="Welcome,#123";
Pattern p = Pattern.compile( "\\D*(\\d+)\\D*" );
Matcher m = p.matcher(str);
if ( m.matches() )
{
int value = Integer.parseInt( m.group(1) );
System.out.println( value );
}
else
{
System.out.println("no number found");
}

You need to declare the format first with one string that is a valid DecimalFormat pattern and then you can parse the real string:
String pattern = "'Welcome,#'0"; //0 is a placeholder, see the link for the others
DecimalFormat df = new DecimalFormat(pattern);
String input = "Welcome,#123";
System.out.println(df.parse(input)); //prints 123
As , is also a placeholder, I have had to quote the text 'Welcome,#'.

Everything is possible, but ..
In that case you have to find just a numbers from that string look look at this
String s = "...stuff...";
for (int i = 0; i < s.length(); i++){
char c = s.charAt(i);
//Process char
}
For recognize if the char is number should be possible to use that
Character.isDigit(string.charAt(0))
So something like:
String s = "..ag123";
String numStr = "";
for (int i = 0; i < s.length(); i++){
char c = s.charAt(i);
if(Character.isDigit(s.charAt(i))){
numStr += s.charAt(i);
}
}
Integer.parseInt(numStr);
For demimal you have to also recognize decimal (maybe also thousands?) separator :) But something in this way..
Btw you can still probably use decimal formatter but you need to set pattern for that (not sure if its possible like string pattern) - you cant find it in doc, Im not sure, but it will be something like [^0123456789][123456789][separators][0123456789][^0123456789] (missing nonmandatory and repeating there)

Related

Why do I get a out of bounds message when I try to run this code?

I am trying to match a pattern . Everything works except when I try to add a string like "1??2" with 2 "?" instead of 3 "?" I get the following error:"String index out of range: 4".
Please see my code below:
import java.util.Scanner;
import java.util.regex.*;
public class pattern {
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner in = new Scanner(System.in);
String str, result="";
int myArray = 0;
System.out.println("Enter a string: ");
str =in.next();
String REGEX = "[0-9]\\?{3}[0-9]";
Pattern pattern =Pattern.compile(REGEX);
Matcher matcher = pattern.matcher(str);
boolean matches =matcher.matches();
if (matches = true) {
result=str;
} else {
System.out.print("False");
}
int resultLen= result.length();
int sum=0;
for (int i=0; i <resultLen-1; i++) {
char newChar=result.charAt(i);
int first= result.charAt(0)-'0';
int last=result.charAt(4)-'0';
sum=first+last;
}
System.out.print(sum==10? "True": "False");
}
}
Corrected code based on the comments by Elliot Frisch:
public static void main( String... args )
{
System.out.println( "Enter a string: " );
final var in = new Scanner( System.in );
final var str = in.next();
final var regex = "[0-9]\\?{3}[0-9]";
final var pattern = Pattern.compile( regex );
final var matcher = pattern.matcher( str );
if( matcher.matches() )
{
final var first = Character.getNumericValue( str.charAt( 0 ) );
final var last = Character.getNumericValue( str.charAt( 4 ) );
final var sum = first + last;
System.out.print( sum == 10 ? "True" : "False" );
}
else
{
System.out.print("False");
}
}
In the original code there was an assignment instead of a comparison:
…
boolean matches = matcher.matches();
if( matches = true ) // WRONG!
{
…
instead of
…
boolean matches = matcher.matches();
if( matches == true )
{
…
or
…
boolean matches = matcher.matches();
if( matches )
{
…
Next, the original program proceeded even the given input string did not match the regular expression, with the result that an exception could be thrown in such case.
Finally, the loop did not have any impact on the final value of sum, and was therefor superfluous.
Also several local variables were obsolete; they did not even support readability.
And that hack with substracting '0' to get the numeric value works, but is not intuitive; it also works only for digits in the ASCII realm.

How to split a string delimited on if substring can be casted as an int

I am attempting to split a string into a list of strings delimited on the change of if a character can be casted numerically or not. To say it another way, I want to break my string up into distinct groups of numbers and letters. For added fun, I'm also trying to trim any leading 0's from each group of numbers. Consider the following example.
Say you're given "aoeu01234stnh0987" as your input. The output I want is ["aoeu", "1234", "stnh", "987"]
I made a working example below, but it is somewhat long and confusing. It seems like there must be a better, more concise way to achieve this.
private static List<String> fragmentString(String string) {
char[] charArr = string.toCharArray();
StringBuilder tempStr = new StringBuilder();
StringBuilder tempInt = new StringBuilder();
List<String> tempList = new ArrayList<>();
boolean wasPrevNum = false;
for (char c : charArr) {
boolean isNum = Character.isDigit(c);
if (isNum) {
tempInt.append(c);
if (!wasPrevNum) {
wasPrevNum = true;
tempList.add(tempStr.toString());
tempStr = new StringBuilder();
}
} else {
tempStr.append(c);
if(wasPrevNum) {
while (tempInt.charAt(0) == '0') tempInt.deleteCharAt(0);
tempList.add(tempInt.toString());
tempInt = new StringBuilder();
wasPrevNum = false;
}
}
}
if (tempInt.length() > 0) while (tempInt.charAt(0) == '0') tempInt.deleteCharAt(0);
tempList.add(wasPrevNum ? tempInt.toString() : tempStr.toString());
return tempList;
}
I saw this post about using the split() method, but that solution only works for their very specific case and doesn't apply here. The split() method was the first thing I played with to solve this, but I couldn't figure out a regex, and now I'm questioning if this is even possible using split().
A very simple solution can be using regex. The regex, \p{L}+|[0-9]+, which means sequence of letters or sequence of digits, can be used to find the substrings. Then, try to parse the found substring. If it is an integer, the leading zeros will be removed as a result of parsing and if the parsing fails, simply print the substring.
import java.util.regex.Matcher;
import java.util.regex.Pattern;
class Main {
public static void main(String[] args) {
String str = "aoeu01234stnh0987";
Matcher matcher = Pattern.compile("\\p{L}+|[0-9]+").matcher(str);
while (matcher.find()) {
String substring = matcher.group();
try {
System.out.println(Integer.parseInt(substring));
} catch (NumberFormatException e) {
System.out.println(substring);
}
}
}
}
Output:
aoeu
1234
stnh
987
This example isn't much more concise than the code the OP posted. The best I can say is that I'm not using an exception as a part of my processing.
Here are the results from one test run.
aoeu01234stnh0987
[aoeu, 1234, stnh, 987]
Here's the complete runnable example code.
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class StringSplitter {
public static void main(String[] args) {
StringSplitter ss = new StringSplitter();
String input = "aoeu01234stnh0987";
System.out.println(input);
List<String> output = ss.splitString(input);
String[] output2 = output.toArray(new String[output.size()]);
System.out.println(Arrays.toString(output2));
}
public List<String> splitString(String input) {
List<String> output = new ArrayList<>();
if (input == null || input.length() < 1) {
return output;
}
char c = input.charAt(0);
boolean isDigit = Character.isDigit(c);
StringBuilder builder = new StringBuilder();
builder.append(c);
for (int i = 1; i < input.length(); i++) {
c = input.charAt(i);
if (isDigit == Character.isDigit(c)) {
builder.append(c);
} else {
addToList(output, builder, isDigit);
builder.delete(0, builder.length());
builder.append(c);
isDigit = !isDigit;
}
}
addToList(output, builder, isDigit);
return output;
}
private void addToList(List<String> output,
StringBuilder builder, boolean isDigit) {
if (isDigit) {
output.add(Integer.toString(
Integer.valueOf(builder.toString())));
} else {
output.add(builder.toString());
}
}
}
You can add some delimiter characters to each group of symbols, and then split the string around these characters:
String str = "aoeu01234stnh0987";
String[] arr = str.replaceAll("\\d+|\\D+", "$0::::").split("::::", 0);
System.out.println(Arrays.toString(arr)); // [aoeu, 01234, stnh, 0987]
// trim leading zeros from numbers,
// i.e. parse the integer value
// and return it back to the string
IntStream.range(0, arr.length)
.filter(i -> arr[i].replaceAll("\\d+", "").length() == 0)
.forEach(i -> arr[i] = Integer.valueOf(arr[i]).toString());
System.out.println(Arrays.toString(arr)); // [aoeu, 1234, stnh, 987]
See also: How to split the string into string and integer in java?
I'm posting the code I ended up using in production, just in case it benefits anyone; I know there are already some great answers, and I used information from some answers here to come up with this.
private static List<List<String>> fragmentArr(String[] inputArr) {
List<List<String>> fragArr = new ArrayList<>();
Arrays.stream(inputArr).forEach(string -> {
List<String> listToAdd = new ArrayList<>();
Matcher matcher = Pattern.compile("[^0-9]+|[0-9]+").matcher(string);
while (matcher.find()) {
StringBuilder substring = new StringBuilder(matcher.group());
while (substring.charAt(0) == '0') substring.deleteCharAt(0);
listToAdd.add(substring.toString());
}
fragArr.add(listToAdd);
});
return fragArr;
}
I used a while loop to trim 0's instead of converting to int and converting back to a string for 2 reasons.
Time Complexity - If you convert data types for this problem, even using a Big Integer or by some other means, you're costing yourself efficiency. Refer to this post on the time complexity of converting to an int and back. Both parseInt and toString are O(n) operations where n is the entire length of the string. My while loop implementation is O(n) where n is the number of leading 0's.
Number Format Exception - If you are passed a string like "0000000000000000000001000000000000000000000", an exception would be thrown if you try to convert the value to an integer to trim the leading 0's because this value is too large for the integer data type in Java. So this is an edge case to consider.
Here's a unit test.
#Test
public void fragmentTest() {
assertEquals(
Arrays.asList(
Arrays.asList("abc", "123", "dce", "456"),
Arrays.asList("123", "abcde", "444", "a")
),
fragmentArr(new String[]{"abc123dce456", "123abcde444a"})
);
assertEquals(
Arrays.asList(
Arrays.asList("abc", "1000000000000000000000", "def", "29")
),
fragmentArr(new String[]{"abc0000000000000000000001000000000000000000000def29"})
);
}

markdown algorithm java; converter problems

public class Md2html {
public static void main(String[] args) throws IOException {
String stringToConvert = new Scanner(System.in).nextLine();
System.out.println(convert(stringToConvert));
}
public static String convert(String str) {
if (str.equals("# "))
System.out.println(" ");
Pattern pattern = Pattern.compile("(#+[^#]+)");
Matcher matcher = pattern.matcher(str);
while (matcher.find()) {
String str1 = matcher.group(1);
if(str1.replaceFirst("#+", "").length() == 0 ||
str1.replaceFirst("#+", "").matches("[\\s]+"))
continue;
int n = str1.length() - str1.replaceFirst("#+", "").length();
System.out.println("<h" + n + ">" + str1.substring(n) +
"</h" + n + ">");
double carac;
carac = str.charAt(0);
if(carac>65 & carac <=90) {
System.out.print("<p>");
System.out.println(str);
System.out.println("<p>");
}
}
return ("");
}
}
Ok, so now I have an algorithm that converts # to < h1> < h2> depending on the number of #...I'm now trying to add < p> at the beginning of a paragraph and < /p> at the end of it. For some reason,the second part of the converter, which is supposed to add < p> at the beginning and < /p> at the end of a paragraph doesnt seem to work (it's the code starting with double carac). Can someone tell me what I'm doing wrong???
You are printing two opening tags for a paragraph if the string starts with an uppercase letter and no closing tag. Replace
System.out.print("<p>");
System.out.println(str);
System.out.println("<p>");
with
System.out.print("<p>");
System.out.println(str);
System.out.println("</p>"); //<--here
Also, you should use a logical AND && instead of a bitwise AND & for boolean operations.
Also, String#charAt(int) returns a char, not a double. You are declaring carac as a double. Declare as a char instead.

How to get with JAVA a specific value for one substring from string?

I have ONE string field which is in format:
"TransactionID=30000001197169 ExecutionStatus=6
additionalCurrency=KMK
pin= 0000"
So they are not separated with some ; оr , they are not seperated even with one blank space.
I want to get value for Execution Status and put it in some field?
How to achieve this?
Thanks for help
This works. But I am not sure this is the most optimal.It just solves your problem.
String s = "TransactionID=30000001197169ExecutionStatus=6additionalCurrency=KMKpin=0000";
if(s!=null && s.contains("ExecutionStatus="))
{
String s1[] = s.split("ExecutionStatus=");
if(s1!=null && s1.length>1)
{
String line = s1[1];
String pattern = "[0-9]+";
// Create a Pattern object
Pattern r = Pattern.compile(pattern);
// Now create matcher object.
Matcher m = r.matcher(line);
if (m.find( )) {
System.out.println("Match");
System.out.println("Found value: " + m.group(0) );
} else {
System.out.println("NO MATCH");
}
}
}
In your example they are indeed seperated by blanks, but the following should be working without blanks, too. Assuming your String is stored in String arguments
String executionStatus;
String[] anArray = arguments.split("=");
for (int i; i < anArray.length; i++)
if (anArray[i].contains("ExecutionStatus")){
executionStatus = anArray[++i].replace("additionalCurrency","");
executionStatus = executionStatus.trim();
}
}
Check if it contains() ExecutionStatus=
If yes then split the string with ExecutionStatus=
Now take the Second string from array find the first occurance of non digit char and use substring()
Assuming all that white space is present in your string, this works.
String str = "\"TransactionID=30000001197169 ExecutionStatus=6\n" +
" additionalCurrency=\"KMK\"\n" +
" pin= \"0000\"\"";
int start = str.indexOf("ExecutionStatus=") + "ExecutionStatus=".length();
int status = 0;
if (start >= 0) {
String strStatus = str.substring(start, str.indexOf("additionalCurrency=") - 1);
try {
status = Integer.parseInt(strStatus.trim());
} catch (NumberFormatException e) {
}
}
At the risk of attracting "... and now you have two problems!" comments, this is probably easiest done with regexes (str is the String defined above):
Pattern p = Pattern.compile("ExecutionStatus\\s*=\\s*(\\d+)"); // Whitespace matching around equals for safety, capturing group around the digits of the status)
Matcher m = p.matcher(str);
String status = m.find() ? m.group(1) : null;

DecimalFormat pattern problem

I try to format a number using NumberFormatter in Android. I use the code bellow and it works perfectly:
NumberFormat formatter = new DecimalFormat("###,###");
String myFormattedString = formatter.format(123456);
But, when i use a pattern with space, like that: new DecimalFormat("###,# ##"); it throws an IllegalArgumentException. I've read documentation about NumberFormatter and DecimalFormatter and found nothing about spaces in patterns. Can anyone explane me why can't i use spaces or how to add them as allowed characters.
Thanks in advance!!!
You can not put spaces in the middle of a number: it is not a valid format.
If you look at the JavaDoc of DecimalFormat, you'll see this:
Prefix:
any Unicode characters except \uFFFE, \uFFFF, and special characters
Suffix:
any Unicode characters except \uFFFE, \uFFFF, and special characters
Number:
Integer Exponentopt
Integer . Fraction Exponentopt
Without copying the entire doc, none of the components of the Number pattern accept spaces, so trying to fit a space in the middle will not work. You can only use spaces in the prefix or suffix.
In a regular JDK this does not throw an exception - it just formats the number as 123,456.
It is not clear what is the space in your example. You have a couple of options for a symbol's role:
decimal separator
group separator
exponent separator
monetary decimal separator
You can set each of these with:
DecimalFormatSymbols symbols = formatter.getDecimalFormatSymbols();
symbols.setGroupingSeparator(' ');
formatter.setSymbols(symbols);
I've achieved my goal by making my own formatter using standart formatter and finding prohibited symbols using exeptions. Hope it will be useful for someone else.
public static String getFormattedNumberWithPattern(String aPattern,
float aNumber) {
String lFormattedNumber = null;
String lOriginalPattern = aPattern;
try {
Hashtable<Integer, String> lIlligalChars = new Hashtable<Integer, String>();
// analyze illegal characters
for (int i = aPattern.length() - 1; i >= 0; i--) {
char[] lAux = new char[1];
aPattern.getChars(i, i + 1, lAux, 0);
try {
// if character is illegal, it throws an exception
#SuppressWarnings("unused")
NumberFormat lNumberFormatter = new DecimalFormat("#"
+ lAux[0] + "#");
} catch (IllegalArgumentException e) {
// add illegal chars and indexes to dictionary
lIlligalChars.put(new Integer(i), String.valueOf(lAux[0]));}}
Enumeration<String> lChars = lIlligalChars.elements();
while (lChars.hasMoreElements()) {
String lIllegalChar = lChars.nextElement();
// remove illegal chars from pattern
aPattern = removeChar(aPattern, lIllegalChar.charAt(0));
}
// format number using legal pattern
NumberFormat lNumberFormatter = new DecimalFormat(aPattern);
lFormattedNumber = lNumberFormatter.format(aNumber);
int lLenghtDifference = lOriginalPattern.length()
- lFormattedNumber.length();
// add illegal chars to formatted string using their indexes
Enumeration<Integer> lKeys = lIlligalChars.keys();
while (lKeys.hasMoreElements()) {
Integer lIllegalCharIndex = lKeys.nextElement();
int lInsertIndex = lIllegalCharIndex.intValue()
- lLenghtDifference;
// insert illegal chars into formatted number
if (lInsertIndex >= 0
|| lInsertIndex < lFormattedNumber.length()) {
lFormattedNumber = new StringBuffer(lFormattedNumber)
.insert(lInsertIndex,
lIlligalChars.get(lIllegalCharIndex)
.charAt(0)).toString();
}
}
} catch (Exception e) {
// Log.d("info", "formater error:" + e + "mask: " + aPattern
// + " number:" + aNumber);
}
return lFormattedNumber;
}
public static String removeChar(String s, char c) {
StringBuffer r = new StringBuffer(s.length());
r.setLength(s.length());
int current = 0;
for (int i = 0; i < s.length(); i++) {
char cur = s.charAt(i);
if (cur != c)
r.setCharAt(current++, cur);
}
r.setLength(current);
return r.toString();
}

Categories