Erro no meio da execução

1. Erro no meio da execução

VInicius Vidima
xSliMx

(usa Outra)

Enviado em 03/04/2016 - 01:53h

Boa noite, sou novato na programação e o professor pediu pra que criassemos um programa que pedisse o nome a altura e o sexo de um individuo e depois devolvesse o peso ideal baseado em uma formula até ai OK, mas durante a execução ele da erro de //Windows encontrou um problema e precisou fechar bla bla
Segue abaixo meu codigo

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

int main()
{
float altura,homem,mulher;
char nome[40];
char sexo;


printf("Informe seu nome:\n "); \*esta parte executa normal, porem as poucas vezes que o programa funcionou ele nao retorna o nome e se eu mudar %s por %c ele nao finciona tambem *\
scanf("%s",&nome);

printf("Informe seu sexo (M/N):\n ");\\ Aqui ok tambem
scanf("%s",&sexo);

printf("Informe sua altura:\n ");\\ Aqui é o grande problema quando eu informo a altura o programa trava
scanf("%f",&altura);

homem=(72.7*altura)-52;
mulher=(62.1*altura)-44.7;

printf("O sexo informado e %s",sexo);
printf("O nome informado e %s",nome);
printf("peso para homem %f ",homem);
printf("peso para mulher %f",mulher);

return 0;

}

Se alguem puder me ajudar ficarei grato


  


2. Re: Erro no meio da execução

Marcelo Alves
foyd

(usa Outra)

Enviado em 03/04/2016 - 11:44h

Olá amigo!

Seu erro está nessa linha: printf("O sexo informado e %s",sexo);
O correto é: printf("O sexo informado e %c",sexo); // sexo é do tipo char, p/ leitura utilizamos c e não s.

Um detalhe, nessa parte do codigo:

printf("Informe seu nome:\n ");
scanf("%s",&nome);
fflush(stdin);
printf("Informe seu sexo (M/N):\n ");
scanf("%c",&sexo);

Utilize o comando fflush(stdin); pois limpa o buffer do teclado!


3. Re: Erro no meio da execução

Paulo
paulo1205

(usa Ubuntu)

Enviado em 03/04/2016 - 12:32h

foyd escreveu:

Utilize o comando fflush(stdin); pois limpa o buffer do teclado!


Desculpe pelo negrito, mas é que é preciso reforçar: nunca use fflush(stdin), nunca mesmo!

Quem pensa que precisa “limpar o buffer do teclado” o faz porque já fez alguma outra coisa errada antes.

Estou terminando de escrever uma resposta mais completa para a questão. Espero enviá-la em alguns minutos.


4. Re: Erro no meio da execução

Paulo
paulo1205

(usa Ubuntu)

Enviado em 03/04/2016 - 15:47h

Você está esbarrando em várias dificuldades relacionadas ao uso de scanf().

Antes de indicar os erros, permita-me uma contextualização (que eu coloco em destaque, para que, se você quiser pular, para ver apenas a resposta à sua dúvida, você possa, embora eu realmente recomende que você leia e tente entender).

Ao contrário do que talvez tenham lhe ensinado, a função scanf() (e suas derivadas) não é destinada apenas à leitura de valores de variáveis. Seu real intuito é procurar por determinados formatos de texto na entrada (razão que explica inclusive o nome da função: “scan” para “procura”, e “f”, que é a primeira letra de “formatted”, em referência a texto formatado), e a leitura ou conversão de partes desse texto formatado para variáveis especificadas pelo programador é apenas uma das coisas que ela pode fazer duante o exame do texto,


Por causa do uso variado (e poderoso) que scanf() e suas variações podem ter, elas constituem algumas das mais complexas funções oferecidas pela biblioteca padrão de funções do C.

Mesmo assim, tal complexidade não é nada que não se possa aprender por meio de uma leitura cautelosa da documentação e orientação adequada. Então, como primeira orientação, já adianto que a documentação de scanf() que vem com o Linux é excelente. Mesmo que você não use Linux, consulte a versão on-line, pois ela é melhor do que a da MSDN (pelo menos na última vez que eu olhei no site da Microsoft).

Parte da dificuldade de lidar com scanf() se deve à compreensão inadequada de como os espaços em branco são tratados em cada situação. “Espaços em branco”, para scanf(), não são apenas os caracteres ' ' que aparecem quando se aperta a barra de espaços, mas também quebras de linhas ('\n', como as produzidas pela tecla <Enter>), retorno de carro ('\r'), tabulações ('\t', produzido no teclado com a tecla <Tab>), quebra de página ('\f'), e tabulações verticais ('\v').

Algumas conversões de texto para variáveis, como as numéricas ("%d", "%i", "%u", "%o", "%x, "%f" e suas variações) e de string com "%s") provocam o descarte de espaços em branco que ocorram antes de se perceber algum outro caráter que não seja espaço em branco. Assim sendo, se você pedir para ler um inteiro em base decimal (com "%d"), e digitar “<espaço><Enter><tab>10<Enter>”, scanf() vai desprezar o espaço, a quebra de linha e a tabulação, vai converter o valor 10, e vai parar a leitura quando enxergar a próxima quebra de linha, que é interpretada como fim do dado ser convertido. O caráter que marca o fim da conversão, seja ele um espaço ou algum caráter inválido para o tipo de dados sendo convertido (por exemplo: qualquer caráter diferente de algarismo durante a conversão de um decimal inteiro) nunca é removido do buffer de leitura, pois a função assume que ele pode ser relevante para a próxima conversão ou operação de leitura,

Outras conversões, como "%c" (leitura de um caráter simples, sem ser como string) e "%[" (leitura de string formada por conjunto fixo de caracteres) nunca desprezam espaços em branco que ocorram antes do dado. No caso particular de "%c", a conversão consome o primeiro caráter presente na entrada, mesmo tal caráter tenha sido o terminador de alguma conversão feita anteriormente.

Contudo a função scanf() oferece uma forma de provocar o descarte de espaços em branco, se você quiser forçá-lo. Basta, para tanto, colocar um espaço em branco na string de formatação. Um espaço em branco provoca o descarte de uma quantidade qualquer (incluindo zero) de espaços em branco na entrada.

Veja o trecho de código abaixo.

int i;
char c;
printf("Entre com um valor inteiro: ");
scanf("%d", &i);
printf("Entre com um caráter: ");
scanf(" %c", &c); /* Note o espaço antes do ‘%c’. */
printf("\nO número digitado foi %d, e o caráter foi '%c'.\n", i, c);


Com esse código, se eu digitar “10<Enter>x<Enter>”, o programa vai imprimir que eu digitei o número 10 e o caráter 'x'. Plenamente como esperado: a quebra de linha após o 10 termina a conversão do primeiro scanf(), e o espaço presente no segundo scanf() provoca o descarte dessa quebra de linha, antes de converter o caráter 'x'.


No seu código, sexo é um caráter simples, não um array de caracteres que possa acomodar uma string. Assim sendo, você deve ler seu valor com uma convesão "%c", não com "%s". Entretanto, você deve se lembrar também que "%c" não despreza espaços em branco. Se você suspeita que possa haver espaços sobrando de uma conversão anterior, pode se livrar deles colocando um espaço antes do “%c” na string de formatação de scanf() (i.e. algo como “scanf(" %c", &sexo);”).

Se, no mesmo exemplo acima, eu digitar “10x<Enter>”, também será impresso o mesmo resultado, mas o programa não vai parar para esperar após imprimir a mensagem “Entre com um caráter: ”. Por quê? Porque o 'x' que terminou a conversão do primeiro scanf() permaneceu no buffer satisfez imediatamente também o segundo scanf(), que “desprezou” zero espaços antes de converter o 'x'.

Por outro lado, seu eu digitar “10<Enter><Enter><Enter><Enter><Enter>...”, o primeiro scanf() vai converter o valor 10 e seguir a diante, mas o segundo scanf() vai ficar descartando tantas quebras de linha quantas eu permanecer digitando, até que apareça algum caráter que não seja considerado espaço em branco, que permita à função avançar para a conversão "%c".

A moral da história é que pode ser difícil com funções de entrada formatada, como scanf(), lidar com variações de formatação a que se está sujeito quando quem interage com o programa é um ser humano, que frequentemente comete erros e que às vezes é intencionalmente hostil. Ainda é possível fazê-lo usando apenas scanf(), graças a outras opções de que ela dispõe, que permitem desprezar conversões, saber quantos caracteres foram consumidos e saber quantas conversões foram bem sucedidas. Mesmo assim, uma abordagem mais simples é sempre ler linhas inteiras (usando fgets(), gets_s() ou getline() (esta última disponível em sistemas POSIX, que pode não ser o caso do Windows)), e depois converter a linha lida, ou partes dela, com sscanf().


Outro erro que você cometeu foi aplicar o operador & ao array nome. A conversão "%s" de scanf() espera receber o endereço do primeiro caráter de um array, a partir do qual os sucessivos caracteres convertidos pela função serão armazenados.

Quando você tem um array qualquer, usar simplesmente o nome do array numa expressão tem o sentido de entregar o endereço do primeiro elemento. Assim sendo, teria sido suficiente e correto dizer “scanf("%s", nome);”. Quando você colocou aplicou operador & a nome, você trocou o sentido: em vez de ter um ponteiro para o primeiro elemento, você passou a ter um ponteiro para o array como um todo.

Ainda que numericamente o endereço do array como um todo seja idêntico ao endereço do primeiro elemento, em termos de tipos de dados, os dois valores de endereço são diferentes: o tipo de um é “ponteiro para array com 40 elementos do tipo char” (em C, “char (*)[40]”) , o do outro é “ponteiro para char” (em C, “char *”). Existem sistemas em que o compilador é programado para verificar a correspondência entre a string de formatação e os argumentos de scanf(), e em tais sistemas o uso que você fez impediria a compilação de ser feita com sucesso.


Por fim, eis algumas sugestões de melhoria:

1) O programa pergunta se a pessoa é home ou mulher. Isso tem pouca serventia, pois você imprime incondicionalmente valores finais para homens e mulheres. Seria interessante estudar execução condicional de código diferenciado para cada sexo.

2) Outro problema comum com scanf() é dar ao usuário condições de entregar mais caracteres do que uma strings tem capacidade de armazenar. Quando isso acontece, a função pode acabar sobrescrevendo memória destinada a outras variáveis ou mesmo a estruturas de controle do programa. Para evitar isso procure sempre especificar o tamanho máximo que uma strings pode ter, levando em consideração que o último byte da string tem de ser um byte nulo. No seu programa, como nome tem tamanho 40, seria mais prudente fazer a leitura do seguinte modo: “scanf("%39s", nome)”.

3) Usar a conversão "%s" impede o uso de espaços no meio da string, pois o primeiro espaço que ocorrer após uma sequência de caracteres não-espaço será interpretado como terminador da conversão. Se você quiser permitir que alguém que se apresente sempre como “Ana Paula”, por exemplo, possa se apresentar assim também ao seu programa, você deve estudar a respeito da conversão "%[".

4) Se, por outro lado, você não quiser permitir que o usuário digite nomes compostos contendo espaços, você deveria deixar isso claro na mensagem em que pede que o usuário digite seu nome.


5. Re: Erro no meio da execução

VInicius Vidima
xSliMx

(usa Outra)

Enviado em 03/04/2016 - 17:52h

Obrigado ao amigo que respondeu primeiro mas segue um agradacimento em especial ao PAULO1205 Obrigado pela explicação nao so me ajudou com o problema como me ensinou também vou usar sua resposta como complemento de estudo, Grato !!






Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts