2010-08-30 3 views
1

Мне нужна функция, которая примет строку и целое число, которое указывает позицию неотрицательного двойного или целого числа и возвращает Number или null. Если «+» возвращает null.parse неотрицательные удвоения

Примеры

2.1  , 0 -> 2.1 
+2.1  , 0 -> null 
-1  , 0 -> null 
-1.2  , 1 -> 1.2 
qwa56sdf , 3 -> 56 

Самый элегантный способ сделать это? Спасибо.

обн Мне нужен код, как это, но лучше)

Number parse(String str, int pos){ 
     Matcher m = Pattern.compile("^(\\d+(?:\\.\\d+)?)").matcher(str); 
     m.region(pos, str.length()); 
     if(m.find()){ 
      return Double.parseDouble(m.group()); 
     } else { 
      return null; 
     } 
    } 
+0

Почему ваш третий пример возвращает null? – jjnguy

+1

Потому что он должен быть неотрицательным. –

+0

Тогда почему четвертый не является нулевым? –

ответ

1
public static Double parseDouble(String input, int fromIndex) { 
    Matcher matcher = Pattern.compile("\\d*\\.?\\d+") 
     .matcher(input.substring(fromIndex)); 
    return matcher.lookingAt() ? Double.parseDouble(matcher.group()) : null; 
} 
+0

Спасибо. Это хорошее решение, но есть много программистов, которые этого не понимают. –

3

Вы можете попробовать:

public static void main(String[] args) { 
    System.out.println(parse("2.1", 0)); 
    System.out.println(parse("+2.1", 0)); 
    System.out.println(parse("-1", 0)); 
    System.out.println(parse("-1.2", 1)); 
    System.out.println(parse("qwa56sdf", 3)); 
} 

private static Double parse(String string, int index) { 
    if (string.charAt(index) == '-' || string.charAt(index) == '+') { 
    return null; 
    } 
    try { 
    return Double.parseDouble(string.substring(index).replaceAll("[^\\d.]", "")); 
    } 
    catch (NumberFormatException e) { 
    return null; 
    } 
} 

мне пришлось раздеться замыкающего нецифровые символы с заменой всего потому, что они вызвало NumberFormatException и возвратит значение null для входных данных, подобных тому, которое было в вашем последнем примере.

Edit: Другой вариант для работы в тех случаях, как в комментарии может быть, чтобы проверить каждый знак

private static Double parse(String string, int index) { 
    String finalString = ""; 
    boolean foundSeparator = false; 
    for (char c : string.substring(index).toCharArray()) { 
     if (c == '.') { 
      if (foundSeparator) { 
       break; 
      } 
      else { 
       foundSeparator = true; 
      } 
     } 
     else if (!Character.isDigit(c)) { 
      break; 
     } 
     finalString += c; 
    } 
    if (finalString == "") { 
     return null; 
    } 
    return Double.parseDouble(finalString); 
} 
+0

Спасибо, но есть проблемы с входами, такими как parse («qwe5a6asf», 3) –

+0

Я предполагаю, что в этом входе вы хотите только совместить «5», что является первым допустимым числом в этой строке. Думаю, обновленная версия должна работать и на этот случай. –

+0

Да, мне нужно что-то вроде второго варианта. Но я полагаю, что должно быть лучшее решение с NumberFormat или что-то вроде этого. –

2

Вам нужно использовать комбинацию метода String.substring() начать в указанный позицию в строке и класс NumberFormat для анализа номера.

+0

Спасибо.На самом деле, NumberFormat имеет метод parse with indexPosition, но есть проблема с символами типа «+» и «-». –

1

Если это функционально правильно, оно выглядит достаточно элегантно для меня. Вы можете захотеть сделать шаблон последним членом класса, так как вам нужно только его компилировать один раз. И регион, вероятно, не требуется:

Matcher m = pattern.matcher(str.substring(pos)); 

Другой вариант, чтобы начать с 1-символ длины подстроки и вырастить его до тех пор, пока не разобрать больше:

if (str.charAt(pos) == '+' || str.charAt(pos) == '-') { 
    //special cases 
    return null; 
} 
Double val = null; 
for (int i = pos+1; i <= str.length(); i++) { 
    try { 
     val = Double.parseDouble(str.substring(pos, i)) { 
    } catch (NumberFormatException e) { 
     break; 
    } 
} 
return val; 

Это немного проще, но также наивную производительность. Менее читаемое, но более совершенное решение заключалось бы в том, чтобы найти конец двойника перед тем, как перейти к разбору, просто взглянув на персонажей по одному.

+0

Спасибо, это будет работа, но я думаю, что должно быть лучшее решение. –

1

Существует также класс Scanner. Что конкретно имеет методы для чтения в примитивах, например scanner.hasNextDouble() и scanner.nextDouble(). Вам все равно придется делать чек на + или -, потому что это все равно пройдет проверку.

+0

Спасибо, но для сканера я должен указать разделитель, но я не могу. –

+0

Уверен, вы можете, ничего, что не цифра или точка. "[^ 0-9.]" –

+0

Да, я могу использовать разделитель, но мне нужен синтаксис из текста, например, "1.2.3" результат "1.2", а не нуль. –

1

Я думаю, что следующая реализация будет более изящной для вашего набора требований. Я использую класс java.text.NumberFormat для синтаксического анализа.

private static Number parse(String text, int position){ 
     Number value=null; 
     NumberFormat nf = NumberFormat.getInstance(); 
     try { 
      value = nf.parse(text,new ParsePosition(position)); 
      if (value.intValue() < 0) 
       value = null; 
     } catch (Exception e) { 
      value = null; 
     } 
     return value; 
    } 
+0

Это хорошо работает для всех ваших входных данных. – Drona

+0

Спасибо. Но на самом деле мне не нравятся исключения в исключительных потоках. –

+0

Метод parse() генерирует только ParseException, если он не может разобрать входное выражение, например «+21». Это совершенно правильно, и его следует поймать и обработать. В моем коде выше, я по ошибке использовал генерическое исключение вместо ParseException. – Drona

Смежные вопросы