Ir ao conteúdo
  • Cadastre-se
isa.btdie

RESOLVIDO Erro ao finalizar executável

Recommended Posts

Olá pessoal, estou estudando um pouco de linguagem C e em um exercício está ocorrendo um erro (porém ao compilar não mostra nenhum erro) com a seguinte mensagem quando aperta a tecla enter para encerrar o executável: "Arquivo.exe parou de funcionar. Um problema fez com que o programa parasse de funcionar corretamente. O Windows fechará o programa e o notificará caso uma solução esteja disponível.".

O código está abaixo, se alguém puder dar uma olhada para ver o que está ocorrendo, pois não estou conseguindo encontrar o erro. Muito obrigada   ^_^

#include <stdio.h>#include <stdlib.h>#include <string.h>main () {    int i, tam;    char frase[40], continua;        printf("Digite uma frase: ");    gets(frase);        tam = strlen(frase);        if (tam > 40) {        continua = 'n';    }    else {        continua = 's';    }        if (continua == 'n') {        while (continua == 'n') {            printf("\n\n--FRASE INVALIDA...TENTE NOVAMENTE!--\n\n");            printf("Digite uma frase: ");            gets(frase);            tam = strlen(frase);                        if (tam <= 40) {                continua = 's';                break;            }        }    }    if (continua == 's') {        for (i=0; i <= tam; i++)            printf("%c \n", frase[i]);    }        system("pause");    return 0;}
 

Compartilhar este post


Link para o post
Compartilhar em outros sites

você quer validar si a pessoa introduziu uma frase maior que o tamanho que você reservou, é isso? Pois você esta fazendo isso até de maneira perigosa eu acho.

 

A função gets lê um string de qualquer tamanho, 10, 40, 100 até "infinito", ele toma todas essas letras de um X, e armazena na sua variável frase, que é do tamanho de 40 chars. Porém você já se perguntou o que acontece com o resto das letras si você escrever mais de 40 letras? A resposta é "buffer overflow", ou conhecido em nossa língua como transbordamento de buffer. você vai passar do limite que você estabeleceu e tudo o que ultrapassar vai sobrescrever dados "vizinhos", isso é um problema gravíssimo.

 

Prove isso baixo sua responsabilidade:

    char frase1[10];    printf ( "Escreva uma frase de mas de 10 letras e veja como gets nao controla o tamanho." );    gets(frase1);    printf ( "Frase1: %s\n", frase1);

Quando printf imprimir mais letras da que você reservou você já destruiu memória XD. Até pode que falhe o programa, incluindo até mesmo pode que seu computador fique inservível e você tenha que formatar. kkkkk

 

Quer uma forma correta de ler uma frase e não sobrepassar o tamanho?

#include <stdio.h>#include <stdlib.h>void flush_in(); int main (){        char frase1[10];    scanf("%9[^\n]", frase1 );    flush_in();        printf("O tamanho da frase %d letras, e contem: \"%s\\0\"", sizeof(frase1)/sizeof(frase1[0]), frase1);        getchar();    return 0;}void flush_in() {    int ch;        while ( ( ch = fgetc ( stdin ) ) != EOF && ch != '\n' ) {}}

Essa é a melhor forma de ler corretamente algo. Passamos a explicar cada linha.
 

Passamos direto para a linha 8, nessa linha faço uma declaração de um string de 10 letras.

 

Na linha 9 uso scanf com um parâmetros meio doidos kkk. o %9 impede que entre na frase1 mais de 9 letras. Por que só 9??? Porque ao se tratar de um string ESTAMOS OBRIGADOS A DEIXAR O ULTIMO CHAR LIVRE PARA O CARACTERE NULO '\0' que serve para indicar o final do string. Então é como si fosse 9 chars desde o teclado + o nulo que o scanf bota no final automaticamente por nós, si eu ler %10 o scanf teria colocado o nulo na décima primeira casa causando o tal "buffer overflow".

 

O [^\n]ignora o enter.

 

Que acontece com o resto das letras? Ficam no buffer aguardando outra variável para entrar, ou seja é lixo, não deveríamos fazer nada com isso. Aí é onde entra flush_in().

 

A função flush_in serve para esvaziar tudo o que sobrou do buffer. Resultado... Uma leitura correta. Recorde que a única forma de esvaziar o buffer é lendo o que contem nele, isso é exatamente o que faz essa função, lê letra por letra até esvaziá-lo completamente.

 

Si você entrar com um string como "vamos fazer uma prova" al executar o programa, vai sair algo como:

O tamanho da frase 10 letras, e contem: "vamos faz\0". <- Esse "vamos faz\0" seria o aspecto que teria o que foi lido, sendo considerado o '\0' como uma única letra, que marca o fim do string, isso esta sempre presente em "TODOS" os C_string (string tipo char[]) já que do contrario printf não saberia até onde ler. você já se perguntou como sabe printf onde tem que parar de imprimir si eu crio uma frase com 10 letras, porém reservei 1000?? Ele para no nulo sempre. A maioria das funções botam o nulo para você no final sem que você saiba, então tenha isso em conta na hora de fazer reservas de memória na hora de declarar char[].

 

Uma forma aconselhável de reservar um string pode ser char frase[100+1]; sendo esse 1 o para o null, então você dispõe de 100 chars livres e não 99.

 

Si você quiser alguma ideia de como controlar a entrada de forma efetiva posso lhe dar uns conselhos, é só você me agregar por skype, lá me chamo igual.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Crie uma conta ou entre para comentar

Você precisar ser um membro para fazer um comentário

Criar uma conta

Crie uma nova conta em nossa comunidade. É fácil!

Crie uma nova conta

Entrar

Já tem uma conta? Faça o login.

Entrar agora





Sobre o Clube do Hardware

No ar desde 1996, o Clube do Hardware é uma das maiores, mais antigas e mais respeitadas publicações sobre tecnologia do Brasil. Leia mais

Direitos autorais

Não permitimos a cópia ou reprodução do conteúdo do nosso site, fórum, newsletters e redes sociais, mesmo citando-se a fonte. Leia mais

×