Gambiarra não relacionada

Esta gambiarra é muito simples e útil. Ela existe por causa de um comportamento peculiar da função atoi. Como sabemos ela serve para converter uma string, que contém um número representado em decimal, para o seu respectivo valor do tipo int. A assinatura da função é esta:

int atoi( const char *str );

Acontece que existe um pequeno probleminha que ocorre quando, por exemplo, estamos usando atoi para ler alguma coisa que o usuário digitou:

#include <stdlib.h> 
#include <stdio.h> 

int main() 
{ 
 char buf[256]; 
 
 scanf("%s", buf); 
 printf("Li o numero %dn", atoi(buf)); 
 
 return 0; 
}

Tudo OK certo? Bem, como vocês sabem é totalmente possível que o conteúdo da string buf não esteja formatado como um número, podem ser letras, caracteres estranhos, o que você quiser. Nesses casos o que a atoi faz? Ela retorna 0 e fica por conta do programador repetir o teste até ter certeza que leu um número. Qual o problema então? Veja o exemplo à seguir:

#include <stdlib.h> 
#include <stdio.h> 

int main() 
{ 
 char *s1 = "42", *s2 = "errado", *s3 = "0";
 
 printf("string: %s n: %dn", s1, atoi(s1)); 
 printf("string: %s n: %dn", s2, atoi(s2)); 
 printf("string: %s n: %dn", s3, atoi(s3)); 

 return 0;
}

O problema é que o valor que denota uma string inválida é um valor de retorno válido e não temos como saber se o usuário na realidade digitou um 0 ou não.

… e a gambiarra?

A solução de verdade para o problema exige o uso de funções como strtol ou sscanf que fazem algumas checagens a mais na string e requerem um porquinho mais de esforço… mas quem sabe a gente não faz isso?

#include <stdlib.h> 
#include <stdio.h> 

int main() 
{ 
 char buf[256]; 
 int n; 

 scanf("%s", buf); 
 n = atoi(buf); 

 if (n == 0 && buf[0] != '0') // retorno == 0 e primeiro char nao eh 0 
 { 
     printf("String invalidan");
 } 
 else 
 { 
     printf("Li o numero %dn", n);
 } 

 return 0;
}

Gambiarra por gambiarra eu acho esta bem bonitinha, mas não funciona pra todos os casos e peço que vocês prefiram soluções mais robustas (a não ser que o programa seja para daqui a 2 horas :).

Este post faz parte da série Pequenos Programadores & Grande Gambiarras