Ir ao conteúdo
  • Cadastre-se

Menu em C - Dúvida no strcmp


JackSpesim

Posts recomendados

Estou com problemas com o uso do comando fgets e do comando strcmp e gostaria da ajuda de vocês.

O código está comentado e acho que está bem claro nas partes com o problema. Vou adcionar só a parte que está defeituosa para não precisar postar a função inteira.

O código todo:

#include <stdio.h>
#include <string.h>
#include <stdlib.h> //exit()

void main(void)
{
MenuPrincipal();
}

void MenuPrincipal()
{
int escolha;
char sair[4];
printf("\033[2J");
printf("Por favor escolha uma opcao:\n");
printf("1.Novo\n2.Carregar\n3.Sair\n\n");
printf("Selecione: ");
scanf("%i", &escolha);
switch(escolha)
{
case 1:
printf("Chama funcao novo"); //implementar
break;
case 2:
printf("Chama funcao carregar"); //implementar
break;
case 3:
printf("Tem certeza que deseja sair?\n");
scanf("%s", &sair); //Vai para pegar a string mas não compara corretamente nem com while nem com if
// fgets(sair,3,stdin); //O fgets está ignorando a função if e a função while(se usada)
if(strcmp(sair,"Sim") || (sair,"SIM") || (sair,"sim") || (sair,"s") || (sair,"S")!=0) //strcmp para comparar string //Usar while ou if?
{ //Se eu usar "==0" o programa roda, se eu usar "==1" dá erro de comperação entre ponteiro e inteiro
printf("Finalizando programa, obrigado por testar!\n");
printf("Pressione qualquer tecla para continuar...\n");
getchar();
exit(0);
}
else if(strcmp(sair,"Nao") || (sair,"NAO") || (sair,"nao") || (sair,"n") || (sair,"N")!=0)
{
MenuPrincipal();
}
else
{
printf("Por favor insira uma opcao valida (Sim/Nao)\n");
printf("Pressione qualquer tecla para continuar...\n");
getchar();
MenuPrincipal();
}
break;
default:
printf("Por favor insira uma opcao valida\n");
printf("Pressione qualquer tecla para continuar...\n");
getchar();
MenuPrincipal();
} //Fim do switch(escolha)
} //Fim do MenuPrincipal()

O problema se encontra nessa parte aqui:

case 3:
printf("Tem certeza que deseja sair?\n");

//Vai para pegar a string mas não compara corretamente nem com while nem com if

scanf("%s", &sair);
// fgets(sair,3,stdin); //O fgets está ignorando a função if e a função while(se usada)


//Se eu usar "==0" o programa roda, se eu usar "==1" dá erro de comperação entre ponteiro e inteiro
if(strcmp(sair,"Sim") || (sair,"SIM") || (sair,"sim") || (sair,"s") || (sair,"S")!=0) //Usar while ou if?
{
printf("Finalizando programa, obrigado por testar!\n");
printf("Pressione qualquer tecla para continuar...\n");
getchar();
exit(0);
}
else if(strcmp(sair,"Nao") || (sair,"NAO") || (sair,"nao") || (sair,"n") || (sair,"N")!=0)
{
MenuPrincipal();
}
else
{
printf("Por favor insira uma opcao valida (Sim/Nao)\n");
printf("Pressione qualquer tecla para continuar...\n");
getchar();
MenuPrincipal();
}
break;

Espero que não tenha ficado confuso essa segunda separação.

A função if ou while independente de qual eu usar não está comparando as strings com o strcmp corretamente, já alterei entre gets, fgets e scanf como podem ver o fgets está até comentado ali, nem apaguei que é para saber que já tentei.

Se alguém souber porque o código não compara as strings e não funciona corretamente eu fico agradecido, preciso dessa ajuda. Desculpe se estiver fora de alguma regra ou algo do tipo, eu dei uma lida no tópico que falava da tag code e vi que tem vários tópicos com dúvidas básicas como esta. Agradeço pela atenção de todos!

Shalom!

Link para o comentário
Compartilhar em outros sites

Tem várias maneiras de resolver, pensei numa mais simples.

Segue um trecho do seu código modificado.


char sair[ 4 ];

/* Inicializa com 4, pois se digitar "sim", temos ('s', 'i', 'm', '\0'), e
se digitar "nâo", temos ('n', 'a', 'o', '\0'). O último caracter é para
determinar o final da string.
*/

case 3:
printf("Tem certeza que deseja sair?\n");
scanf( "%3[^\n]", sair );

// Esse scanf, garante que somente os 3 primeiros caracteres serão aceitos.

if( strcmp(sair, "sim") == 0 || (sair, "Sim") == 0 || (sair, "SIM") == 0 )
printf( "DEU CERTO !" );

else
printf( "NAO DEU CERTO !" );

Espero ter ajudado...

Link para o comentário
Compartilhar em outros sites

Tem várias maneiras de resolver, pensei numa mais simples.

Segue um trecho do seu código modificado.


char sair[ 4 ];

/* Inicializa com 4, pois se digitar "sim", temos ('s', 'i', 'm', '\0'), e
se digitar "nâo", temos ('n', 'a', 'o', '\0'). O último caracter é para
determinar o final da string.
*/

case 3:
printf("Tem certeza que deseja sair?\n");
scanf( "%3[^\n]", sair );

// Esse scanf, garante que somente os 3 primeiros caracteres serão aceitos.

if( strcmp(sair, "sim") == 0 || (sair, "Sim") == 0 || (sair, "SIM") == 0 )
printf( "DEU CERTO !" );

else
printf( "NAO DEU CERTO !" );

Espero ter ajudado...

Irmão obrigado pela tentativa e pela intenção de ajudar, mas pelo menos aqui no meu compilador gcc do linux

gcc version 4.5.1 20100924 (Red Hat 4.5.1-4) (GCC) 

o código ainda não deu certo,

Saída do código:

Por favor escolha uma opcao:
1.Novo
2.Carregar
3.opções
4.Sair

Selecione: 4
Tem certeza que deseja sair



Por favor escolha uma opcao:
1.Novo
2.Carregar
3.opções
4.Sair

Selecione:

É exibido o print do

 case 3:
printf("Tem certeza que deseja sair?\n");
scanf( "%3[^\n]", sair );

Mas já pula um monte de linha e reinicia a função, nem fica a opção de digitar qualquer coisa. Não sei se você usa windows, talvez seja isso, talvez aqui no linux o parâmetro "%3[^\n]" do scanf não funcione corretamente.

Obrigado pela ajuda. Se alguém puder ainda aguardo respostas e estou tentando aqui de outras formas também.

Shalom!

Link para o comentário
Compartilhar em outros sites

Eu acho que o erro deve estar nesse argumento do if:


strcmp(sair, "sim") == 0 || (sair, "Sim") == 0 || (sair, "SIM") == 0

você chama a função strcmp() uma vez só, o resto que tá ali não faz sentido.

Minha solução é você incluir a <ctype.h> e antes de fazer a comparação você faz um tolower() na string sair toda, e ai sim você faz strcmp() com "sim" ou "nao", pra dizer a verdade eu seria mais prático ainda e ao invés de mandar o usuário escrever 'sim' ou 'nao' pediria só um S/N e usaria um variável char só...

E quanto ao resto do seu programa, a sua função MenuPrincipal() é recursiva caso uma opção não desejada seja executada ou o usuário não queira sair, isso tá feio demais, simplesmente faça uma função MenuPrincipal() que tenha um while( op != 5 )

e dentro do switch na opção pra sair assim que o usuário confirmar a saida você muda op pra 5 e a função sai do loop e encerra MenuPrincipal() ou algo do tipo.

Do jeito que sua função está escrita você corre o risco de ter um estouro de pilha na memória e uma bela mensagem de erro no seu programa (isso só aconteceria se o usuário fizesse a função MenuPrincipal() ser chamada muitas vezes, mas para um programa real e em outro contexto isso poderia ser facilmente realizável).

Link para o comentário
Compartilhar em outros sites

Eu acho que o erro deve estar nesse argumento do if:


strcmp(sair, "sim") == 0 || (sair, "Sim") == 0 || (sair, "SIM") == 0

você chama a função strcmp() uma vez só, o resto que tá ali não faz sentido.

Como assim não faz sentido? Usar lógica matemática (ou álgebra booleana) não é uma boa forma de trabalhar no programa para ele ficar mais inteligente e flexível?

Isso é uma pergunta ok!? Não é um desafio ou zombaria, pergunto para aprender mesmo pois até agora me parece uma maneira bacana de se trabalhar, até porque pelo que eu quero fazer que vou explicar já já é a melhor forma que eu tinha encontrado, já que uso de If ou Switch gastaria muita linha de código.

Minha solução é você incluir a <ctype.h> e antes de fazer a comparação você faz um tolower() na string sair toda, e ai sim você faz strcmp() com "sim" ou "nao", pra dizer a verdade eu seria mais prático ainda e ao invés de mandar o usuário escrever 'sim' ou 'nao' pediria só um S/N e usaria um variável char só...

Então irmão, eu não conhecia essa biblioteca "ctype.h" e esse tolower() parece ser um comando interessante para começar a usá-lo bastante pelo que li e entendi do uso aqui.

O que acontece é o seguinte, eu usei o operador lógico || pois não conhecia esse tolower(), e eu não quero trabalhar com s/n pois eu estou tentando estudar a criação de "console inteligente" (não sei se o nome é esse), eu estou tentando criar um projeto de jogo em texto sabe? Aqueles teste-based game antigões mesmo, e para isso o console precisa ser inteligente, tanto a pessoa digitar "sim", "SIM" ou "s" o console entender, compreende? Por isso o tolower() vai me ajudar bastante, mas trocar para o uso de s/n não vai servir aqui.

E quanto ao resto do seu programa, a sua função MenuPrincipal() é recursiva caso uma opção não desejada seja executada ou o usuário não queira sair, isso tá feio demais, simplesmente faça uma função MenuPrincipal() que tenha um while( op != 5 )

e dentro do switch na opção pra sair assim que o usuário confirmar a saida você muda op pra 5 e a função sai do loop e encerra MenuPrincipal() ou algo do tipo.

Do jeito que sua função está escrita você corre o risco de ter um estouro de pilha na memória e uma bela mensagem de erro no seu programa (isso só aconteceria se o usuário fizesse a função MenuPrincipal() ser chamada muitas vezes, mas para um programa real e em outro contexto isso poderia ser facilmente realizável).

Eu não sei como o outro carinha não comentou isso antes, eu estou ciente de que o uso do "while" é melhor prática de programação do que o uso de recursão como eu deixar a função, ficou parecendo goto não é? rs

Pois é eu ainda não sei se vou mudar para while ou não, quando eu escrevi esse código em shell script eu fiz usando while, mas quando fui começar a trabalhar em C agora eu comecei a experimentar usar esse recurso de chamar a função, vou levar o seu comentário em conta apesar de que eu já sabia disso e vou decidir depois se eu mudo para while ou não, eu coloquei a função recursiva principalmente porque o source que eu estou estudando e usando de exemplo trabalha dessa forma, então eu acabei colocando assim para ficar igual, mas de qualquer forma obrigado por comentar.

Vou testar o uso do tolower() aqui e ver se funciona dessa forma, de qualquer forma eu já agradeço pela ajuda e pela atenção desde já...

Shalom!

Link para o comentário
Compartilhar em outros sites

Como assim não faz sentido? Usar lógica matemática (ou álgebra booleana) não é uma boa forma de trabalhar no programa para ele ficar mais inteligente e flexível?

O problema não é a álgebra, é a sintaxe, creio que a sua intenção pareceu ser:


strcmp(sair, "SIM") == 0 || strcmp(sair, "Sim") == 0 || strcmp(sair, "sim") == 0

Aqui tem uma descrição resumida da biblioteca padrão http://www.acm.uiuc.edu/webmonkeys/book/c_guide/, acho que lhe ajudará muito.

Quanto a chamada recursiva, não existe problema em usar recursão, o problema é usar da forma errada e creio que o jeito com o qual você usa nesse código é realmente feio e propenso a erros, já que o controle do uso da recursão acaba dependendo do usuário e bem... por melhor que você escreva documentação e instruções você nunca deve esperar que um usuário vá realmente fazer a coisa certa, por isso acho mais seguro e como você mesmo disse tá parecendo algo do nível de goto.

Link para o comentário
Compartilhar em outros sites

Irmão muito obrigado! Vocês são mesmo bons! Agora já funcionou aqui, ficou assim caso alguém com a mesma dúvida queira ver no futuro...

case 4:
printf("Tem certeza que deseja sair?\n");
scanf("%s", &sair); //Vai para pegar a string

//Transforma toda a string para minusculo
for(i=0;i<=3;i++){sair[i]=tolower(sair[i]);}

if(strcmp(sair,"sim")==0) //Compara string
{
printf("Finalizando programa, obrigado por jogar!\n");
printf("Pressione qualquer tecla para continuar...\n");
getchar();
exit(0);
}
else if(strcmp(sair,"nao")==0)
{
MenuPrincipal();
}
else
{
printf("Por favor insira uma opcao valida (Sim/Nao)\n");
printf("Pressione qualquer tecla para continuar...\n");
getchar();
MenuPrincipal();
}
break;

O problema não é a álgebra, é a sintaxe, creio que a sua intenção pareceu ser:


strcmp(sair, "SIM") == 0 || strcmp(sair, "Sim") == 0 || strcmp(sair, "sim") == 0

Aqui tem uma descrição resumida da biblioteca padrão http://www.acm.uiuc.edu/webmonkeys/book/c_guide/, acho que lhe ajudará muito.

Pois é irmão, acho que dessa forma é que funcionaria bem, mas por fim acabou que agora ficou bem melhor mesmo, quanto ao link eu agradeço muito, realmente será de muita utilidade vou até ver se tem um pdf depois para não precisar ficar abrindo link por link.

Quanto a chamada recursiva, não existe problema em usar recursão, o problema é usar da forma errada e creio que o jeito com o qual você usa nesse código é realmente feio e propenso a erros, já que o controle do uso da recursão acaba dependendo do usuário e bem... por melhor que você escreva documentação e instruções você nunca deve esperar que um usuário vá realmente fazer a coisa certa, por isso acho mais seguro e como você mesmo disse tá parecendo algo do nível de goto.

Vou analisar isso irmão, dando uma olhada aqui estou suspeitando que essa chamada da função nos if's e nos casos é que está sendo responsável por um problema aqui com o getchar(), quando eu escolho a opção ele não para no getchar() como devia, suspeito que deve ser porque o programa lê a chamada da função logo abaixo e já chama a função sem esperar o resto dos comandos do bloco.

Muito obrigado pela ajuda, agradeço a todos, vocês são muito bons e ajudaram de muito boa vontade, postei a ajuda horas antes em um fórum "hacker" e os "hackers" nenhum botou a cara para ajudar, sinal que ninguém sabe lá pois quando alguém acha um erro em algum programa todo mundo aponta, mas na hora de resolver problema ninguém sabe, venho observando isso lá...

Agradeço muito irmãos, gostaria de saber se qualquer outro problema de outro tipo que aparecer eu posso postar aqui mesmo ou se deixaria muito bagunçado... Mas se Deus quiser não vai dar mais problemas não...

Que Deus abençoe vocês irmãos, vocês ficarão cada vez melhores do que já são.

Shalom!

Link para o comentário
Compartilhar em outros sites

Vou analisar isso irmão, dando uma olhada aqui estou suspeitando que essa chamada da função nos if's e nos casos é que está sendo responsável por um problema aqui com o getchar(), quando eu escolho a opção ele não para no getchar() como devia, suspeito que deve ser porque o programa lê a chamada da função logo abaixo e já chama a função sem esperar o resto dos comandos do bloco.

Não, programas simplesmente não pulam comandos, o que acontece é que ao pedir que o usuário digite uma string via scanf() o programa lê caracteres da stdin até que um espaço em branco ou um pula linha seja encontrado, mas ele não tira o espaço em branco ou o pula linha do buffer, então quando você dá o getchar() ele simplesmente lê o '\n' que ficou no buffer e continua executando, para evitar que fique alguma coisa no buffer apos a leitura da string você deve dar um fflush(stdin) após a leitura, isso garante que ao chamar o getchar() a stdin está vazia e o comando vai realmente esperar você digitar algo.

E sinta-se a vontade para expor suas dúvidas, mas não seja muito exigente quanto ao tempo de resposta, isso realmente depende da disposição de alguém vir e te responder.

Link para o comentário
Compartilhar em outros sites

Não, programas simplesmente não pulam comandos, o que acontece é que ao pedir que o usuário digite uma string via scanf() o programa lê caracteres da stdin até que um espaço em branco ou um pula linha seja encontrado, mas ele não tira o espaço em branco ou o pula linha do buffer, então quando você dá o getchar() ele simplesmente lê o '\n' que ficou no buffer e continua executando, para evitar que fique alguma coisa no buffer apos a leitura da string você deve dar um fflush(stdin) após a leitura, isso garante que ao chamar o getchar() a stdin está vazia e o comando vai realmente esperar você digitar algo.

E sinta-se a vontade para expor suas dúvidas, mas não seja muito exigente quanto ao tempo de resposta, isso realmente depende da disposição de alguém vir e te responder.

Show de bola irmão, você é muito fera mesmo!

Só que o fflush() não funciona no linux, então tive que usar o __fpurge() e agora ficou tudo certinho.

Muito obrigado irmão, peço desculpas caso tenha parecido que fui muito exigente quanto ao tempo de resposta, depois que você falou eu fui no outro fórum e pedi desculpas também, as vezes a gente faz groceria e nem percebe...

Mais uma vez obrigado por tudo, vocês me trouxeram muito conhecimento hoje, foi muito útil tudo o que os dois me disseram.

Shalom!

Link para o comentário
Compartilhar em outros sites

Arquivado

Este tópico foi arquivado e está fechado para novas respostas.

Sobre o Clube do Hardware

No ar desde 1996, o Clube do Hardware é uma das maiores, mais antigas e mais respeitadas comunidades 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

×
×
  • Criar novo...