paulo1205 
		 
		(usa Ubuntu)
		 
		Enviado em 12/07/2019 - 16:17h 
		Bacagine escreveu: 
 
Minhas dúvidas são: 
1) Por que devo usar getchar no lugar de getch? 
Porque 
getch () não é uma função padronizada e, portanto, não existe em qualquer sistema (existe uma 
getch () no Linux, como parte da biblioteca Curses, mas o comportamento dela é diferente da versão que tem no MS-DOS).
2) Porque devo usar getchar duas vezes (um professor me eplicou uma vez mas acabei esquecendo e gostaria de me lembrar) 
O que acontece, tanto no Linux como no Windows, é que geralmente a entra e saída de dados são orientadas a linha.  A orientação a linha implica que simplesmente apertar uma tecla não basta para que a a função 
getchar () retorne imediatamente, porque, por trás de um 
getchar (), a biblioteca de entrada e saída do C está tentando ler uma linha inteira, e essa tentativa só acaba sendo bem sucedida quando o caráter de fim de linha é encontrado, ou quando acaba o espaço interno de 
buffer  para conter os caracteres encontrados antes do caráter que marca o fim da linha.
Além disso, o caráter de fim de linha, quando encontrado, é colocado no 
buffer  de entrada como parte do conteúdo lido; se ele não for explicitamente consumido pelo seu programa, ficará lá, à espera da próxima operação de leitura.  Quando seu programa executa “
scanf("%f", &x) ”, o que acontece não é a leitura de uma linha inteira e a extração do número de ponto flutuante que está presenta nessa linha; a função 
scanf () é muito mais complexa que isso — e por isso eu recomendo que sua documentação seja lida com muito cuidado.  O que acontece realmente é que a conversão 
"%f"  provoca um descarte de espaços que porventura ocorram antes do número, seguida pela busca de caracteres que possam compor o número, até que seja encontrado o primeiro caráter que não possa ser considerado parte do número.  Tal caráter, quando encontrado, não é consumido, mas permanece no 
buffer  de leitura.
Se, no momento da execução, o usuário digitar “
2.5 ”, o programa (isto é: a biblioteca de entrada e saída que seu programa usa) vai continuar aguardando a marca de fim de linha.  Quando o usuário aperta a tecla <Enter>, essa marca finalmente injeta o caráter de fim de linha no terminal, e o programa recebe esse caráter e o coloca no 
buffer .  
scanf (), por sua vez, vê que a marca de fim de linha não faz parte do número, e grava o valor lido no local apontado, deixando a marca de linha de linha no 
buffer .  Se a operação de leitura seguinte for “
scanf("%f", &y) , a marca de fim de linha que tinha ficado pendente no 
buffer  será consumida como parte do descarte automático de espaços, antes de começar a consumir os caracteres que compõem o número a ser lido.  Se o usuário digitar “1.5” e teclar <Enter>, a conversão var consumir 
'1' , 
'.'  e 
'5' , mas mas deixar o 
'\n'  correspondente à tecla <Enter> no 
buffer , até a próxima operação de leitura.
Então, se você quiser ler um único caráter, é importante garantir que não haja nenhuma sobra de operações anteriores no 
buffer .
Fora tudo isso, que está sob o controle do programa em C usando funções padronizadas, o próprio driver do terminal, sob controle do sistema operacional, também emprega 
buffers , para que o que é digitado não se perca, caso a aplicação que está rodando no terminal demore pedir para a ler o que o usuário digita.
getchar () poderia retornar imediatamente após uma tecla ser apertada.  Mas, para isso, você teria primeiro de ter o cuidado de não deixar sobras no 
buffer , e depois teria de pedir à biblioteca de leitura do C que parasse de usar orientação à linha e pedir ao sistema operacional que altere o comportamento do driver do terminal, a fim de eliminar o efeito dos seus 
buffers .  O primeiro pedido pode ser feito com funções do C padrão; o segundo requereria o uso de funções particulares do seu sistema operacional.
getch () é uma maneira de pedir ao sistema operacional que interaja diretamente com o terminal, sem passar pelo sistema de entrada e saída do C.  Misturar 
getch () com funções de leitura padronizadas do C aplicadas ao terminal é geralmente um erro, inclusive no MS-DOS/Windows.
3) Por que em partes do código como esta não aceitam apenas que eu escreva main():
 else{ 
           main();                                        
           } 
           }while (x != -0);  
Queria que caso o usuario não digitasse nenhuma das opções anteriores, o programa mostrasse o que tem na função main, no entanto não consigo fazer isso para o LINUX. 
 
Seria importante ver a mensagem de erro específica que o compilador mostra.  Mas eu não consigo pensar em nenhum caso válido pelo qual um programa devesse chamar 
main () explicitamente.  A forma como você fez isso no seu programa denota um erro de modelagem.
A forma correta de fazer em C o que você fez (mantendo as mesmas funções que você fez, embora eu também não ache que elas estão muito bem divididas) seria mais ou menos a seguinte.
    bool read_until_eol(void){ 
  int ch; 
  while((ch=getchar())!=EOF && ch!='\n') 
    ; 
  return ch=='\n'; 
} 
 
void input_error(){ 
  if( 
    ferror(stdin) || 
    (fprintf(stderr, "Dados inválidos. Tentando limpar o buffer... "), !read_until_eol()) 
  ){ 
    perror("Erro de leitura"); 
    exit(1); 
  } 
  fprintf(stderr, "OK.\n"); 
} 
   
void soma(void){ 
  while(1){ 
    float x, y; 
    printf("Digite a primeira parcela (ou 0 para encerrar): "); 
    if(scanf("%f", &x)!=1){ 
      input_error(); 
      fprintf(stderr, "Tecle <Enter> para voltar ao menu principal."); 
      read_until_eol(); 
      break; 
    } 
    else if(x==0.0f) 
      break; 
    printf("Digite a segunda parcela: "); 
    if(scanf("%f", &y)!=1){ 
      input_error(); 
      fprintf(stderr, "Tecle <Enter> para voltar ao menu principal."); 
      read_until_eol(); 
      break; 
    } 
    printf("%f%+f=%f\n\n", x, y, x+y); 
  } 
} 
 
void subtracao(void){ /* Semelhante a soma, com as devidas alterações. */ } 
 
void multiplicacao(void){ /* Semelhante a soma, com as devidas alterações. */ } 
 
void divisao(void){ /* Semelhante a soma, com as devidas alterações. */ } 
 
bool menu(void){ 
  /* Apresenta menu. */ 
  /* Lê opção. */ 
  switch(opcao){ 
    case 1: soma(); break; 
    case 2: subtracao(); break; 
    case 3: multiplicacao(); break; 
    case 4: divisao(); break; 
    case 0: return false; 
  } 
  return true; 
} 
 
int main(void){ 
  do { 
    printf("blablabla... \n"); 
  } while(menu()); 
  return 0; 
}  
... “Principium sapientiae timor Domini, et scientia sanctorum prudentia.” (Proverbia 9:10)