2010-03-09 67 views
2

我从用户那里得到一个字符串,然后进行一些检查以确保它是有效的,这里是我一直使用的代码;可能会损失精度;从字符串中提取字符

char digit= userInput.charAt(0) - '0'; 

这一直工作正常,直到我做了另一种方法的一些工作,我去编译,并已接收从那时起一个错误“可能的精度损失”。

我在做什么错?

+0

您的减法,即使它正确转换,也会将char值0,1,2 ... 9减少为二进制0,1,2 ... 9。任何低于'0'的值都将变为负值,但char是无符号值。你试图做的是无效的,没有意义。使用cletus的建议。看到我的答案,如果你真的想这样做。 – 2010-03-09 05:01:25

回答

0

在执行减法操作之前,Java可能会将userInput.charAt(0)'0'转换为其他数据类型,然后再转换回来。

尽量明确铸造结果char将其存储到数字之前:

char digit = (char)(userInput.charAt(0) - '0'); 
+0

这解决了这个问题,但现在数字根本没有赋值... – Troy 2010-03-09 03:16:19

+0

@Troy:'数字'必须被赋值,它是一个原始类型。值是二进制0吗?如果charAt(0)是'0',这将是有意义的。 – 2010-03-09 04:58:20

6

一件事,你应该使用Character方法实现此目的,而不是一个家庭长大的解决方案,即Character.isDigit()检查的有效性和Character.digit()为得到一个值:

char c = ... 
if (Character.isDigit(c)) { 
    // it's a digit 
} 
int value = Character.digit(c, 10); 

为什么你得到这个警告是5.6.2 Binary Numeric Promotion从解释3210:

当操作者施加二进制 数值提升到一对 操作数,其中的每一个必须表示一个数字型的 值,以下 规则适用,为了使用加宽 转换(§5.1.2)至 操作数转换为必要的:

  • 如果操作数是double型的,另一种是转换为 double
  • 否则,如果任一操作数的类型为float,则另一个操作数转换为 为float
  • 否则,如果任一操作数的类型为long,则另一个转换为 long
  • 否则,两个操作数都转换为int类型。

那么,有什么情况是,当你做减法两个参数被晋升为int秒。结果是int。当您尝试将int分配给char时,可能会丢失精度(32位有符号16位无符号)。

另一种验证方法是简单地使用正则表达式:

if (s.matches("\\d\\d-\\d\\d")) { 
    // it's ##-## 
} 

,或者,如果你需要获取组:

Pattern p = Pattern.compile("(\\d\\d)-(\\d\\d)"); 
Matcher m = p.matcher(s); 
if (m.matches()) { 
    System.out.println(m.group(1)); // first group 
    System.out.println(m.group(1)); // second group 
} 
+0

问题是我正在检查以确保用户输入格式为digitdigit-digitdigit的字符串,如果它不匹配,或者数字超出了范围,我正在检查然后我想返回一个错误。 – Troy 2010-03-09 03:19:57

+1

@Troy为什么不使用'\ d \ d- \ d \ d'的正则表达式并测试用户输入?如果没有,使用'Character.isDigit()'可以做你想要的验证。 – cletus 2010-03-09 03:28:28

+0

+1:给我看的方式。 – 2010-03-09 05:56:41

0

这与做如何的Java隐含蒙上操作数与算术运算符一起使用时。

两个userInput.charAt(0)'0'char类型,但是它们被隐式转换为整数的操作(减法),因此当整数结果被分配给一个char,Java将给出错误。

0

你真的应该使用cletus的答案,我给他+1。但是,如果您真的想在代码中使用该减法,则不应将结果存储在char之内,因为结果可能为负值(例如,如果用户输入“”(空格))。

int digit = userInput.charAt(0) - '0'; 
if (digit < 0 || digit > 9) 
    throw new IllegalArgumentException("Bad input at 0, must be between 0 and 9."); 

当然,这不应该有一个硬编码的索引或者,除非你真的只是想 检查字符串的第一个位置。