Dexter's Lab 2 Denunciar mensagem Publicado 14 de Janeiro de 2013 Viva. O que está a acontecer com os meus divisores? Parece-me tudo bem mas o output está incorreto. Já agora, se me puderem dar umas dicas de como posso trabalhar/organizar este código melhor (principalmente) a nível de estrutura, agradecia - porque é para apresentar ao professor. # include <stdio.h> void menu (); void valores_mul (); void valores_div (); int cont; void menu () { int slct; do { system ("cls"); puts ("1...Divisor \n\n2...Multiplo\n\n0....Sair\n\nESCOLHA: "); scanf ("%d", &slct); switch (slct) { case 1: valores_div(); break; case 2: valores_mul(); break; case 0: exit(0); default: printf ("\nOpcao invalida!"); } } while (slct != '0'); } void valores_mul() { int num, n_mul; printf ("Valor a ser multiplo: "); scanf ("%d", &num); printf ("\n Agora numero de multiplos: "); scanf ("%d", &n_mul); for (cont = 1; cont <= n_mul; cont++) { printf ("%d x %d = %d \n", num, cont, num*cont); } getche(); } void valores_div() { int div; printf ("Digite valor para mostrar divisores: "); scanf ("%d", div); for (cont = 1; cont <= div; cont++) { if ((div%cont)==0) { printf ("%d ", cont); } } getch(); } int main (void) { menu(); getche(); return 0; } Todas as ajudas que me prestaram aqui têm sido muito importantes. Obrigado, desde já. output dos divisores: Valor: 6 Divisores: 1 2 3 4 5 6 7 8 9 10 12 14 15 20 ... Partilhar esta mensagem Ligação para a mensagem Partilhar noutros sites
pmg 96 Denunciar mensagem Publicado 14 de Janeiro de 2013 Na funcao valores_div() passas o valor actual da variavel div para a funcao scanf() quando deverias passar o endereco da variavel What have you tried? Não respondo a dúvidas por PM A minha bola de cristal está para compor; deve ficar pronta para a semana. Torna os teus tópicos mais atractivos e legíveis usando a tag CODE para colorir o código! Partilhar esta mensagem Ligação para a mensagem Partilhar noutros sites
HappyHippyHippo 1185 Denunciar mensagem Publicado 14 de Janeiro de 2013 (editado) // indentação é quase obrigatória !!!! # include <stdio.h> void menu (); void valores_mul (); void valores_div (); int cont; // <-- remove rvariavel global void menu () { int slct; do { system ("cls"); // <-------- não usar a função system puts ("1...Divisor \n\n2...Multiplo\n\n0....Sair\n\nESCOLHA: "); scanf ("%d", &slct); // falta validacao de input // falta limpeza do buffer de leitura switch (slct) { case 1: valores_div(); break; case 2: valores_mul(); break; case 0: exit(0); // <--- em vez de chamar exit, basta colocares um return, afinal é uma função default: printf ("\nOpcao invalida!"); // <--- falta um break simplesmente para normalização } } while (slct != '0'); } void valores_mul() { int num, n_mul; printf ("Valor a ser multiplo: "); scanf ("%d", &num); // falta limpeza do buffer de leitura printf ("\n Agora numero de multiplos: "); scanf ("%d", &n_mul); // falta limpeza do buffer de leitura for (cont = 1; cont <= n_mul; cont++) { printf ("%d x %d = %d \n", num, cont, num*cont); } getche(); // <--- não uses getche, mas sim getchar() } void valores_div() { int div; printf ("Digite valor para mostrar divisores: "); scanf ("%d", div); // <----------- o argumento deverá ser um endereço // falta limpeza do buffer de leitura for (cont = 1; cont <= div; cont++) { if ((div%cont)==0) { printf ("%d ", cont); } } getch(); // <--- não uses getch, mas sim getchar() } int main (void) { menu(); getche(); // <--- não uses getche, mas sim getchar() return 0; } o teu código com algumas correcções: # include <stdio.h> void menu (); void valores_mul (); void valores_div (); #ifdef __linux__ #define CLEAR_SCREEN system("clear"); #else #define CLEAR_SCREEN system("cls"); #endif #define CLEAR_INPUT while (getchar() != '\n'); #define PAUSE getchar(); CLEAR_INPUT void menu () { int slct, ok; do { CLEAR_SCREEN printf("1...Divisor \n\n2...Multiplo\n\n0....Sair\n\nESCOLHA: "); ok = scanf ("%d", &slct); CLEAR_INPUT if (ok) { switch (slct) { case 1: valores_div(); break; case 2: valores_mul(); break; case 0: return; default: printf ("\nOpcao invalida!"); PAUSE break; }; } else { printf ("\nOpcao invalida!"); PAUSE } } while (slct != '0'); } void valores_mul() { int num, n_mul, cont, ok; do { printf ("Valor a ser multiplo: "); ok = scanf ("%d", &num); CLEAR_INPUT } while (!ok); do { printf ("\n Agora numero de multiplos: "); ok = scanf ("%d", &n_mul); CLEAR_INPUT } while (!ok); for (cont = 1; cont <= n_mul; cont++) { printf ("%d x %d = %d \n", num, cont, num*cont); } PAUSE } void valores_div() { int div, cont, ok; do { printf ("Digite valor para mostrar divisores: "); ok = scanf ("%d", &div); CLEAR_INPUT } while (!ok); for (cont = 1; cont <= div; cont++) { if ((div%cont)==0) { printf ("%d ", cont); } } PAUSE } int main (void) { menu(); return 0; } Editado 14 de Janeiro de 2013 por HappyHippyHippo IRC : sim, é algo que ainda existe >> #p@p Portugol Plus Partilhar esta mensagem Ligação para a mensagem Partilhar noutros sites
Dexter's Lab 2 Denunciar mensagem Publicado 14 de Janeiro de 2013 (editado) .1 HHHippo, porquê o "ok!"? Sei o que faz, mas não sei o propósito e a mais valia em relação ao que estava anteriormente. .2 Porquê o if antes do switch se vai fazer o mesmo? .3 O scanf retorna dados? Sempre me disseram que o scanf tinha limitações (por exemplo, não podia fazer " if(scanf()) " porque não retorna dados - por isso acho estranho poder retornar para o "ok!". Ainda assim, qual a razão de estar assim? ok = scanf ("%d", &num); .4 Se pudesses dar também uma achega com isto: #define CLEAR_INPUT while (getchar() != '\n'); sff. Obrigado. Pmg, tens razão. Já é distração pelo cansaço. Obrigado pela observação. Editado 14 de Janeiro de 2013 por thoga31 Partilhar esta mensagem Ligação para a mensagem Partilhar noutros sites
HappyHippyHippo 1185 Denunciar mensagem Publicado 15 de Janeiro de 2013 sim, o scanf retorna dados. o scanf retorna o número de elementos lidos do teclado, exemplo: int i, v1, v2, v3, v4; i = scanf("%d %d %d %d", &v1, &v2, &v3, &v4); // se o input for : // 1 2 3 as 4 // somente as primeira 3 variáveis serão preenchidas e o scanf retorna 3 // logo à variável i será atribuído o valor de 3 // se o input for : // as 1 2 3 4 // nenhuma variável será preenchida e o scanf retorna 0 // logo à variável i será atribuído o valor de 0 com isso, espero que percebas a razão da variável ok ---- o if está lá para que o switch não seja executado quando não foi lido correctamente um valor do teclado. isto é importante porque como referi acima, a variável de destino dos dados do scanf só é actualizada se os dados forem correctamente lidos. para prevenir que uma leitura errada dos dados leve a que um valor anterior da variável slct implique a entrada numa das opções do switch, o if foi colocado no código. ---- é um problema muito usual que (por alguma razão muito estranha) nunca é explicada ao iniciantes de programação. nem imaginas a quantidade de tópicos aqui no forum que tiveram origem nesse problema. o problema é este: quando tu escreves na consola, estás a inserir dados num buffer de leitura. agora imagina que escreves o numero 123. o que acontece realmente é : - escreves os caracteres '1', depois o '2', de seguida o '3' aqui estes dados ainda não foram para o buffer de leitura, e é por isso que o scanf ainda não retornou nada. somente quando carregas na tecla Enter é que os dados são processados pela consola e gravados no buffer. o problema é que a tecla Enter também envia um caracter muito específico para o buffer de leitura, o caracter '\n'. mas no teu código tens: scanf("%d", &var); como podes ver, so estás a pedir para ler um número. e é isso que o scanf faz, lê um número e não toca no resto, ficando o caracter '\n' no buffer de leitura. outro tipo de casos é quando o utilizador adiciona mais do que o pretendido ou algo diferente. imagina o mesmo caso. pedes um número ao utilizador e ele insere o seguinte : "1 2" o scanf irá ler o número 1, ficando o número 2 no buffer de leitura. o que acontece é na próxima vez que chamares o scanf, os caracteres ' 2' serão os primeiros a serem processados, dando azo a muitos erros ou tópicos relativos com erros descritos do géneor: - o meu programa ignora o menu (porque a opção foi lida de dados inseridos anteriormente) - não aparece nada (porque o getchar leu algo que ficou no buffer) - etc ... o mesmo acontece com dados errados. se pedires num número no scanf, e inserires 'a123', o scanf não lê o número e não retira nada do buffer, devido ao 'a' inicial. agora, para resolver este tipo de problema (todos de uma vez) é limpar o buffer de leitura sempre que chamas o scanf. como te disse anteriormente, os dados só são inseridos no buffer de leitura quando carregas no Enter, e disse também que o Enter adiciona um caracter específico no buffer, o caracter '\n'. o código que está na macro, não é mais do que : enquando o caracter lido do buffer de leitura for diferente de '\n', não faz nada desta forma, o buffer de leitura é limpo de qualquer dados. prevenindo assim a miriedade de erros ai provenientes. IRC : sim, é algo que ainda existe >> #p@p Portugol Plus Partilhar esta mensagem Ligação para a mensagem Partilhar noutros sites