C++: Programação correta

Muitas coisas incorretas são ensinadas aos estudantes de programação. Por exemplo:

system(“pause”);

Que para a tela em um certo ponto. O problema é que o comando system( ) envia algum comando ao prompt do sistema. O que, obviamente só vai funcionar em um SO. Um jeito melhor de fazer isso seria:

while(getchar() != ‘\n’);

Que tem o mesmo efeito, mas funciona em qualquer SO. Outro problema é:

fflush(stdin);

Ao ler uma string com gets ou fgets, se um scanf for dado antes, o ‘\n’ do ENTER utilizado para inserir um valor no scanf será pego pelo fgets/gets. O fflush limpa o buffer certo? Não. fflush é utilizado para buffers de saída, de forma que seu uso em buffers de entrada gera um comportamento imprevisível. Além, disso, não funciona fora do Windows. No Linux, você poderia usar:

__fpurge(stdin);

Que é a mesmo coisa (errada) e só funciona em Linux. O que fazer então? A questão é que você precisa “capturar” o  caractere ‘\n’ fujão do scanf( ). Você pode fazer isso com um:

scanf(“%i%*c “, &variavel);   (o scanf lê o inteiro que queremos e depois lê um caracter que, devido ao asterisco, será jogado fora. Esse é o ENTER)

Ou:

scanf(“%i”, &variavel)

getchar( );   (pega o ENTER que escapou acima)

Mas suponhamos que o usuário mala, ao (por exemplo) digitar um inteiro no scanf( ), deu uns 20 espaços e apertou o enter. O getchar( ) irá pegar um espaço e deixará todos os outros e mais o ENTER rodando por aí. O scanf( ) com asterisco fará a mesma coisa. Solução? Lembra do pause que eu criei acima? Ele basicamente pega qualquer caracter até achat um ‘\n’ (ENTER)! Então:

scanf(“%i”, &variável);

while(getchar() != ‘\n’);

fgets(….)

Com isso o buffer será limpo e o fgets irá funcionar. Você pode criar um procedimento para não ter que ficar digitando isso o tempo todo. Esse procedimento serve para dar pause e limpar o buffer (esse é bom!!!):

void pause( ){

while(getchar( ) != ‘\n’);

}

Lembra que eu falei sobre a dupla:

gets(variavel);

E:

fgets(variavel, 40, stdin);

onde:

variável: aonde você vai salvar a string.

40: valor de exemplo. Pode ser qualquer inteiro. Corresponde ao tamanho da variável aonde você vai    guardar a string lida.

stdin: local de onde a string será lida (stdin é a entrada padrão, o teclado). Poderia ser um arquivo, stream, etc.

O que as duas fazem? Ora, leem uma string. Se ambas fazem a mesma coisa, porque usar a segunda, que é mais complicada? Simples. Suponhamos que sua string tenha 20 caracteres. Na hora de ler, o usuário digitou 50 caracteres e deu ENTER. O gets vai pegar 20 caracteres, colocar na variável, e irá deixar os outros 30 no buffer, jogando dados aleatórios no seu programa todo. Que encrenca… O fgets pega as 20 e, como sabe que esse é o tamanho da string, apenas joga o resto fora, sem jogar os dados no resto do seu programa. Se você compilar o código no GCC, verá que ele nem aceita o gets (uma das maiores vantagens do GCC na minha opinião é que ele não aceita POG).

Espero que tenham apreciado essas dicas. A melhor forma de aprender a programar é aprender certo desde o começo. Isso gera código de qualidade e evita problemas.

Anúncios

6 Responses to “C++: Programação correta”


  1. 1 leandro silva 4 de outubro de 2009 às 23:48

    Cara show de bola o post. salvou a minha vida to desde ontem procurando por essa resposta. parabens

  2. 3 Joao 13 de fevereiro de 2010 às 08:43

    Muito bom o seu texto, e obrigado.
    No entanto tenho uma dúvida, da uma olhada nesta funçao, que le os dados de um novo aluno e insere em um arquivo texto:
    void novoAluno()
    {
    int numero;
    float nota1, nota2;
    char nome[20];
    FILE *arq;

    arq= fopen(“dados35.txt”, “a”);

    if (arq==NULL)
    {
    printf(“Erro ao abrir o arquivo\n”);
    return;
    }

    //obtencao dos novos dados
    printf(“\n”);
    printf(“Digite os dados do novo aluno:\n”);
    printf(“Numero…”);
    scanf(“%d”,&numero);
    while(getchar()!=’\n’);
    printf(“Nome…..”);
    fgets(nome, 20, stdin);
    while(getchar()!=’\n’);
    printf(“Nota 1…”);
    scanf(“%f”,&nota1);
    while(getchar()!=’\n’);
    printf(“Nota 2…”);
    scanf(“%f”,&nota2);

    //salvando os novos dados no arquivo
    fprintf(arq, “%d,%s,%.1f,%.1f\n”, numero,nome,nota1,nota2);

    fclose(arq);
    }//fim da funcao novoAluno

    Quando insiro um nome maior que 20 caracteres, ele pega os 20 primeiros e salva em um arquivo texto sem problemas. Porém se insiro um nome menor que 20 caracteres ele envia um \n para o arquivo texto e ai tenho problemas na leitura dos dados.

    Como será que poderia resolver isso?

    Abraço

    Rodolfo

  3. 4 scott 13 de junho de 2010 às 22:00

    Deu uma ajuda boa aqui. Vlw

  4. 6 Marcos 6 de junho de 2015 às 22:02

    Olá Trx64, como vai?
    Eu conheço programação C, porém bem pouco de C++. Gostaria de saber se as suas dicas são válidas para C também.

    Aliás, ótimo post, parabéns pelo trabalho 😀


Deixe um comentário

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s





%d blogueiros gostam disto: