2017-08-05 3 views
1

j'ai construire un petit programme qui convertirait le tableau de caractères donné à un nombre entier:Conversion d'un nombre entier multidigital à partir d'un tableau de caractères en un entier

#include <stdio.h> 

int char_to_int(char* value); 

int main(int argc, char* argv[]) 
{ 
    if (argc != 2) 
    { 
     printf("Illegal argument count!"); 
     return 1; 
    } 

    printf("As char array: %s\n", argv[1]); 
    printf("As integer: %i", char_to_int(argv[1])); 

    return 0; 
} 

int char_to_int(char* value) 
{ 
    return *value - '0'; 
} 

Le problème est que quand je rentre dans un numéro multidigital la nombre entier se compose uniquement d'un nombre à un chiffre, ce qui est logique, mais je n'ai aucune idée sur la façon de réécrire le code. Et je ne sais pas non plus pourquoi seul le premier personnage est converti. Je sais que c'est un truc assez basique, mais j'aimerais savoir comment l'implémenter correctement.

Je voudrais également éviter d'utiliser la fonction ato() dans la liste STL.

Code avec Reworked gestion des erreurs:

#include <stdio.h> 

int char_to_int(char* value); 

int illegal_conversion = 0; 

int main(int argc, char* argv[]) 
{ 
    if (argc != 2) 
    { 
     printf("Illegal argument count!"); 
     return 1; 
    } 

    int result = char_to_int(argv[1]); 

    if (illegal_conversion) 
    { 
     printf("Illegal arguments"); 
     return 1; 
    } 

    printf("As char array: %s\n", argv[1]); 
    printf("As integer: %i", result); 

    return 0; 
} 

int char_to_int(char* value) 
{ 
    int result = 0; 
    int negative_integer = 0; 

    while (*value) 
    { 
     if (*value == 43) 
     { 
      *value++; 
      continue; 
     } 
     else if (*value == 45) 
     { 
      *value++; 
      negative_integer = 1; 
      continue; 
     } 
     else if (*value < 48 || *value > 57) 
     { 
      illegal_conversion = 1; 
      return 1; 
     } 

     result *= 10; 
     result += *value++ - '0'; 
    } 

    if (negative_integer) 
     result *= -1; 

    return result; 
} 
+0

Qu'en est-il de la fonction 'atoi()' à convertir? –

+0

Ouais c'est une autre chose que je devais mentionner. Je voudrais éviter cette fonction puisque je veux implémenter cette conversion moi-même. Mais merci de mentionner. –

+0

@J ... S peut-être qu'il veut apprendre :) –

Répondre

3

Parce que vous revenez que la valeur numérique du premier chiffre.

Cette fonction convertit, mais sans aucun contrôle et il ne fonctionne que pour les nombres décimaux valides non négatifs, sinon il est un UB

int char_to_int(char* value) 
{ 
    int result = 0; 
    while(*value) 
    { 
     result *= 10; 
     result += *value++ - '0'; 
    } 
    return result; 
} 

ou un peu plus intelligent un:

int char_to_int(char* value, int *res) 
{ 
    int sign = 0; 
    int status = 0; 
    int result = 0; 


    if (value != NULL && res != NULL) 
    { 
     while (*value) 
     { 
      switch (*value) 
      { 
       case '+': 
       case '-': 
        if (sign) status = -1; 
        sign = *value == '-' ? -1 : 1; 
        break; 
       default: 
        if (!isdigit(*value)) status = -1; 
        if(!sign) sign = 1; 
        *result *= 10; 
        *result += *value - '0'; 
        break; 
      } 
      value++; 
      if (status) break; 
     } 
     if(!status)*res = sign * result; 
    } 

    return status; 
} 
+1

Je viens de réaliser ...C'est génial merci :) –

+1

Continuez à programmer :) –

+0

Essayez maintenant vous-même: 1. Vérifiez si la chaîne d'entrée est valide. 2. Détection de signe et suppression d'espaces. Très bons exercices –

0

Code Reworked incure comportement indéfini dans un cas où il peut être évité.

Exemple avec (complément à 2) int

char buf[100]; 
sprintf(buf, "%d", INT_MIN); // e.g. -2147483648 
int y = char_to_int(buf); 

La boucle while dans char_to_int() exécute éventuellement

// before 
// result: 214748364 
// *value: '8' 
result += *value++ - '0'; 
// after 
// `int` overflow, this is undefined behavior 

Pour éviter, plutôt que d'accumuler la réponse comme une valeur positive puis nier plus tard si " - 'trouvé, accumule la réponse en tant que valeur négative, puis annule plus tard si' - 'n'est pas trouvé. Ceci est moins intuitif, mais évite UB.

L'utilisation de unsigned en tant que plage étendue est une autre façon, mais échoue sur les machines rares où INT_MAX == UINT_MAX. Je n'ai rencontré qu'une seule fois une telle machine et cela pour son entier le plus large.

Autres améliorations notées dans les commentaires.

#include <ctype.h> 

int char_to_int(const char *value) { // use const 
    int sign = *value; 
    if (sign == '-' || sign == '+') { 
    value++; 
    } 

    bool digit_found = false; 
    int result = 0; 
    // while (isdigit(*value)) { // avoid this as it is UB when *value < 0, not EOF 
    while (isdigit((unsigned char) *value)) { // or (*value >= '0' && *value <= '9') 
    result *= 10; 
    result -= *value - '0'; // notice the `-=` 
    value++; 
    digit_found = true; 
    } 
    if (sign != '-') { 
    result = -result; 
    } 

    // Error detection 
    if (*value != '\0' || !digit_found) { 
    ; //Handle_Invalid_String(); 
    } 

    return result; 
} 

Remarque: la détection de débordement n'est pas incluse.