1
votes

Pourquoi est-ce que j'obtiens NumberFormatException lors de la conversion de String Array en int Array?

Je n'obtiens pas l'erreur lorsque j'exécute mon code sur IntelliJ . Cependant, lorsque j'essaie de remettre mon code pour l'affectation sur laquelle je travaille, j'obtiens NFE pour les deux cas de test. J'ai supprimé tout mon code et laissé uniquement le code ci-dessous passer par les cas de test. Quelque part ici doit être une NumberFormatException .

System.out.println(Arrays.asList(tokens).contains(""));
    System.out.println(Arrays.toString(tokens));

J'ai lu sur les doubles espaces et vérifié ceci avec: System.out.println (Arrays.asList (tokens) .contains ("")); La sortie était fausse, ce n'est donc pas une option. Comme vous pouvez le voir, j'utilise déjà trim () . J'apprécierais votre aide. Louis

Eddit: D'accord, quelque chose est louche ici. J'ai ajouté

public class Search {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        sc.nextLine();
        int[] list = new int[n];
        String [] tokens = sc.nextLine().trim().split(" ");

        for (int i=0; i<tokens.length;i++){
            list[i]=Integer.parseInt(tokens[i]);
        }
    }
}

À mon code et l'ai remis aux cas de test. Alors qu'IntelliJ fournirait false suivi d'un tableau d'entiers, le scénario de test génère: vrai [] . Par conséquent, vous avez tous raison et j'ai juste supposé à tort que l'entrée dans mes cas de test serait similaire à l'exemple d'entrée que j'ai reçu dans la mission.

Edit2:

D'accord! Je l'ai compris. L'entrée des cas de test n'était tout simplement pas le même format que celui de mon entrée de test qui ressemblait un peu à ceci:

10
8 8 9 12 1101111117186298321
2
8 13

Je suppose que le sc.nextLine () que j'ai inclus a ignoré les entiers dont j'avais besoin pour faire ma liste. Donc, le problème réel n'était pas que des espaces supplémentaires ou quoi que ce soit, c'était simplement que j'avais dépassé l'entrée que je voulais en utilisant sc.nextLine (). La réponse qui m'a donné l'indication dont j'avais besoin, même si je ne pense pas que c'était prévu, venait d'Andronicus. Merci à tout le monde en tout cas.


5 commentaires

essayez de consigner les jetons [i] avant de les analyser. vous saurez ce qui cause l’ENF.


Oui, vous avez un non-Integer en jetons, ce qui provoque l'ENF. Il y a probablement une sorte de cas de test en cours d'exécution sur votre code qui passe sans nombres.


Utilisez ce split ("\\ s +") au lieu de split ("") .


C'est aussi l'explication que j'ai trouvée. Mais s'il vous plaît, jetez un oeil à l'entrée Im donnée: 10 8 8 9 12 110 111 117 186 298 321 Ce sont les deux premières lignes de mon entrée. Pour moi, cela semble exempt de jetons non entiers. J'ai également essayé d'imprimer mon tokens-array. Le résultat ressemble à ceci: [8, 8, 9, 12, 110, 111, 117, 186, 298, 321] Également exempt de membres non entiers


L'entrée ci-dessus fonctionne bien avec le code que vous avez publié. Cela signifie que ce n'est pas tout le code (donc le problème est ailleurs) ou ce n'est pas l'entrée que vous passez.


4 Réponses :


2
votes

Si vous savez qu'il y aura un entier comme entrée et que vous ne vous inquiétez pas de l'analyse, pourquoi ne pas l'utiliser à la place?

Arrays.stream(sc.nextLine().trim().split(" ")).filter(s -> !s.matches("\\s")).toArray(String[]::new);
\\ or simplier
sc.nextLine().trim().split("\\s+")

Dans votre solution, vous auriez à faire:

int input = sc.nextInt();


4 commentaires

C'est un bon point. Je pourrais même faire cela mais j'aimerais quand même comprendre pourquoi ma version ne fonctionnera pas.


C'est à cause de ces espaces blancs dont vous devez vous débarrasser


@Louis j'ai ajouté quelques explications


Comme mentionné dans ma modification, le problème était un InputFormat différent de celui attendu. Il y avait probablement moins de nouvelles lignes dans l'entrée que je ne le pensais. J'ai donc sauté des parties de l'entrée via l'utilisation de sc.nextLine (). J'ai résolu le problème en utilisant uniquement sc.nextInt (). Votre réponse était correcte.



1
votes

Cela est probablement dû au nombre supplémentaire d'espaces entre les nombres.

Par exemple,

int i = 0;
for (String token : tokens){
    token = token.trim();
    if (!"".equals(token)) {
        list[i++] = Integer.parseInt(token);
    }
}

Voici à quoi ressemblera votre tableau après la division, p>

tokens = {"9", "", "", "", "8", "7", "9", "", "", "", "1"}

Ci-dessus lancera la NumberFormatException en raison d'espaces supplémentaires.

Vous pouvez essayer de rogner le contenu encore une fois,

9    8 7 9    1
  ^^       ^^
*Note: You have more than one spaces here.


4 commentaires

C'est faux. Le tableau ressemblera à ceci: {"9", "", "", "8", "7", ...} . Je le sais parce que je l'ai essayé. ;)


@RoddyoftheFrozenPeas Oui, vous avez raison. J'ai modifié ma réponse pour refléter cela.


depuis que j'ai imprimé le tableau et qu'il ressemblait à ceci: [8, 8, 9, 12, 110, 111, 117, 186, 298, 321] j'étais sûr que les espaces supplémentaires ne seraient pas la raison de mon problème.


C'est toujours éteint. Il n'y aura jamais d'espaces aucun dans le tableau de jetons car c'est votre caractère scindé. Il y aura une chaîne vide à la place de chaque espace doublé.



2
votes

Il existe plusieurs causes possibles:

  1. Il y a un non-nombre dans les jetons - par exemple. 9 1! 3 x 3 ...
  2. Les jetons sont séparés par plus d'un espace - par exemple 9 3

Vous devriez pouvoir dire par le texte de l'exception de format numérique. Par exemple, dans le cas de plusieurs espaces, vous obtiendrez:

Exception dans le thread "main" java.lang.NumberFormatException: Pour la chaîne d'entrée: ""

Et pour les non-nombres (par exemple "a"), vous obtiendrez:

Exception dans le thread "main" java.lang.NumberFormatException: Pour la chaîne d'entrée: "a"

Il existe bien sûr de nombreuses solutions possibles en fonction de ce que vous voulez faire lorsque vous rencontrez une entrée invalide (l'ignorez-vous? lancez une exception spéciale? essayez de supprimer les non-nombres?) / p>

Lorsque vous savez que vos entrées sont séparées par des espaces, mais que vous ne savez pas combien d'espace blanc, vous pouvez utiliser une expression régulière pour cibler plusieurs espaces dans votre commande split :

for(int i = 0; i < tokens.length; i++) {
  if(tokens[i].matches("\\d+")) {
    list[i] = Integer.parseInt(tokens[i]);
  } else {
    // Handle error case for non-digit input
  }
}

Ensuite, pour gérer les non-chiffres dans votre liste de jetons, vous pouvez ajouter une vérification dans votre boucle for:

str.split("\\s+"); // splits on one or more whitespace including tabs, newlines, etc.


0 commentaires

0
votes

Veuillez modifier votre code comme suit:

1
2
3
4
5

Entrée de la console:

Enter the size of the array : 
5
Enter a string : 
1       2     3      4    5

Sortie:

public class Example {

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        System.out.println("Enter the size of the array : ");
        int n = sc.nextInt();
        sc.nextLine();
        int[] list = new int[n];
        System.out.println("Enter a string : ");
        /** This regex will work for string having more than one space. */ 
        String trimmedToken = sc.nextLine().replaceAll("\\s+", " ");
        String[] tokens = trimmedToken.split(" ");
        for (int i = 0; i < tokens.length; i++) {
            list[i] = Integer.parseInt(tokens[i]);
            System.out.println(list[i]);
        }
        sc.close();
    }

}


2 commentaires

La saisie échoue toujours: 1 2 3 x y z


Cela échoue car la conversion de type explicite String en int est effectuée dans son code. Ainsi, vous ne pouvez pas envoyer de valeurs de chaîne dans celles qui ne peuvent pas être converties en entier.