2017-10-05 1 views
0

Rédaction cette méthode avec les critères suivants ..Obtention d'une sortie inattendue avec l'erreur

ENTRÉE: aabbb SORTIE: a2b3

INPUT: ab SORTIE: ab (parce que sa plus courte que A1B1)

INPUT: a23 SORTIE: erreur (ne pas lire les chiffres)

Voici la méthode actuelle que j'ai pour cela.

void encrypt(char* crypt, const char* source) { 


    while (1) { 

     char tmp = *source; 

     if (!tmp) { 
      *crypt = 0; 
      printf("error\n"); 
      return; 
     } 

     size_t count = 1; 
     while (*(++source) == tmp){ 
      if(isdigit(tmp)){ 
       printf("error\n"); 
       return; 
      } 
      ++count; 
     } 
     *(crypt++) = tmp; 
     crypt += sprintf(crypt, "%zu", count); 
    } 

} 

int main(int argc, char **argv) { 

    if (argc != 2) { 
     fprintf(stderr, "error\n"); 
     return 1; 
    } 

    const char* source = argv[1]; 

    char* crypt = malloc(strlen(source)*2+1); 

    encrypt(crypt, source); 
    printf("%s\n", crypt); 
// free(crypt); 
    return 0; 

} 

Très curieusement, chaque fois que je cours, j'obtenir la sortie:

./prog abbbb 
error 
a1b4 

./prog a23r 
error 
a1 

Pourquoi est-ce erreur survenant? Comment puis-je faire en sorte que le premier message d'erreur s'arrête et pourquoi le programme ne se casse pas lorsqu'il y a des nombres au milieu de la chaîne entrée?

+0

Ce programme est parfaitement adapté à un débogueur. –

+0

Honnêtement, et très embarrassant ne sais pas comment utiliser un débogueur correctement et j'utilise une machine distante à travers ssh et vim – sgerbhctim

+0

Vous avez besoin d'un chemin qui se termine normalement lorsque la chaîne se termine. – BLUEPIXY

Répondre

-1

Premier cas: abbbb

Vous appelez la fonction encrypt(), qui prépare la chaîne a1b4 dans le tampon que vous avez alloué (sprintf() arrive en mémoire et ne provoque rien à afficher sur la console) .

La chaîne se termine par un terminateur null. Lorsque votre boucle arrive à ce point, tmp sera nul. Malheureusement, un message immédiat error est imprimé sur la console. Ensuite, la fonction retourne et le résultat dans le tampon est imprimé.

Deuxième cas: a23r

D'abord, encrypt() démarre l'analyse de la chaîne d'entrée et crée la chaîne de sortie pour les lettres valides. Cela produit . À la deuxième itération, il rencontre le chiffre '2', ce qui fait que isdigit(tmp) est vrai. Encore une fois, il y a une sortie immédiate de error à la console. La fonction retourne ensuite. Mais a1 est déjà dans le tampon, donc il est également sorti vers la console.

Comment obtenir les choses dans le bon ordre?

Modifiez votre fonction pour informer l'appelant d'une situation d'erreur. Par exemple, un retour de 0 signifierait ok et une autre valeur signifierait qu'une erreur est survenue.

#define ERR_EMPTY 1   /* error: empty string */ 
#define ERR_INVALID 2   /* error: invalid character */ 

int encrypt(char* crypt, const char* source) { 
    int rc = 0;     // return= 0; 

    if (!*source)     // if input string is empty 
     rc = ERR_EMPTY; 
    else {  
     while (*source) {    // loop while the char is not zero 
      char tmp = *source; 
             // (don't show a error at the null terminator) 
      if(isdigit(tmp)){ 
       rc = ERR_INVALID; 
       break; 
      } 
      size_t count = 1; 
      while (*(++source) == tmp){ 
       ++count; 
      } 
      *(crypt++) = tmp; 
      crypt += sprintf(crypt, "%zu", count); 
     } 
    } 
    *crypt = 0; // prevent risks: in every case put a null terminator 
    return (rc); 
} 

Avec ce changement, vous pourriez alors mieux contrôler la sortie en main():

int err = encrypt(crypt, source); 
if (!err) 
    printf("%s\n", crypt); 
else printf ("Error (code %d)\n", err); 

remarque finale

Attention: malloc(strlen(source)*2+1) suppose que strlen(source)<(SIZE_MAX-1)/2. Si cette condition n'est pas remplie, vous pouvez rencontrer un dépassement d'entier entraînant une allocation insuffisante et une corruption de la mémoire.