2010-03-09 6 views
2

Je reçois une chaîne de l'utilisateur, puis je vérifie pour s'assurer qu'elle est valide, voici le code que j'ai utilisé;Perte de précision possible; extraction de char à partir de la chaîne

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

Cela avait fonctionné très bien jusqu'à ce que j'ai travaillé sur une autre méthode, je suis allé à compiler et ont reçu une erreur « possible perte de précision » depuis.

Qu'est-ce que je fais mal?

+0

Votre soustraction, même lorsqu'elle est lancée correctement, réduira les valeurs char 0, 1, 2 ... 9 à binaire 0, 1, 2 ... 9. Toute valeur inférieure à '0' deviendra réellement négative, mais char est une valeur non signée. Ce que vous essayez de faire n'est pas valide et n'a pas de sens. Utilisez ce que suggère Cletus. Voyez ma réponse si vous voulez vraiment faire cela. –

Répondre

0

Il est possible que Java convertisse userInput.charAt(0) et '0' en un type de données différent avant de procéder à la soustraction, puis de les convertir par la suite.

Essayez de caster explicitement le résultat à char avant de le ranger dans chiffres:

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

Cela a résolu le problème, mais maintenant aucune valeur n'est affectée au chiffre ... – Troy

+0

@Troy: une valeur doit être affectée à digit, il s'agit d'un type primitif. La valeur est-elle binaire 0? Cela aurait du sens si le charAt (0) était un '0'. –

6

Pour une chose que vous devez utiliser les Character méthodes pour ce faire plutôt qu'une solution de Home Grown, à savoir Character.isDigit() pour vérifier la validité et Character.digit() pour obtenir une valeur:

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

Pourquoi vous obtenez cet avertissement est expliqué par 5.6.2 Binary Numeric Promotion de la Java Language Specification:

Lorsqu'un opérateur applique binaire promotion numérique à une paire de opérandes, dont chacun doit dénoter une valeur d'un type numérique, les règles suivantes appliquent, dans l'ordre, en utilisant l'élargissement conversion (§5.1.2) pour convertir opérandes nécessaire:

  • Si l'un des opérandes est de type double, l'autre est converti en double.
  • Sinon, si l'un des opérandes est de type float, l'autre est converti en float.
  • Sinon, si l'un des opérandes est de type long, l'autre est converti en long.
  • Sinon, les deux opérandes sont convertis en type int.

Alors ce qui se passe est que lorsque vous faites la soustraction des deux arguments sont promus à int s. Le résultat est un int. Lorsque vous essayez et attribuez que int à char il y a une perte de précision possible (32 bits signé à 16 bits non signé).

Une technique de validation alternative est simplement d'utiliser une expression régulière:

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

ou, si vous devez saisir les groupes:

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

Le problème est que je vérifie que l'utilisateur entre une chaîne au format digitdigit-digitdigit, si elle ne correspond pas, ou si les chiffres sont en dehors de la plage que je vérifie, alors je veux retourner une erreur. – Troy

+1

@Troy pourquoi ne pas utiliser une regex de dire '\ d \ d- \ d \ d' et tester l'entrée de l'utilisateur pour cela? Sinon, utiliser 'Character.isDigit()' peut effectuer la vérification que vous voulez. – cletus

+0

+1: Façon de me montrer. –

0

Cela a à voir avec la façon dont Java lance implicitement opérandes lorsqu'il est utilisé avec des opérateurs arithmétiques.

Les deux userInput.charAt(0) et '0' sont de type char mais ils sont convertis implicitement en entiers pour l'opération (soustraction) et donc lorsque le résultat entier est affecté à un char, Java donné une erreur.

0

Vous devriez vraiment utiliser la réponse de Cletus et je lui ai donné +1. Cependant, si vous voulez vraiment utiliser cette soustraction dans votre code, vous ne devriez pas stocker le résultat dans un char, car le résultat peut être négatif (si l'utilisateur entre "" (espace) par exemple).

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

Bien sûr, cela ne devrait pas avoir un index codé en dur, soit à moins que vous voulez vraiment juste vérifier la première position de cette chaîne.

Questions connexes