1. Este site usa cookies. Ao continuar a usar este site está a concordar com o nosso uso de cookies. Saber Mais.

Validar caracteres [Linguagem C]

Discussão em 'Programação' iniciada por Patrick_maura, 18 de Julho de 2008. (Respostas: 13; Visualizações: 7744)

  1. Patrick_maura

    Patrick_maura Power Member

    Boa tarde,

    tenho uma duvida e precisava que alguém me desse uma ajuda.

    O código é o seguinte:

    Código:
    do{
                printf("\nUtiliza conta poupanca-habitacao (1-Sim, 0-Nao):\n\n");
                printf("Opcao:");
                scanf("%d",&dad.conta_pouhab);
            }while(dad.conta_pouhab<0 || dad.conta_pouhab>1);
    
    Nas aulas para validar os caracteres fazia-mos while (dad.conta_pouhab>'a' && dad.conta_pouhab<'z'), no entanto isso não está a dar resultado.

    Como faço para validar os caracteres, ou seja, para que não seja possível introduzi-los?
     
  2. Baderous

    Baderous Banido

    Não percebi.
     
  3. MPalhas

    MPalhas Power Member

    falas em validar caracteres, mas o que eu vejo no código é uma variavel to tipo int.
    pelo que percebo do código, queres que o utilizador insira 0 ou 1. então basta isto:

    while (dad.conta_pouhab!=0 && dad.conta_pouhab!=1)
     
  4. z80

    z80 Power Member

    penso que ele quer uma espécie de filtro de caracteres introduzidos pelo teclado, mas tambem nao percebi se apenas os quer validar (i.e, depois de introduzidos) ou ..."quando se carrega numa tecla `inválida' nada aparece no ecrã".
     
  5. Patrick_maura

    Patrick_maura Power Member

    O que eu quero é que não seja possivel introduzir caracteres. Por exemplo, se for introduzido um numero qualquer alem de 0 ou 1 a pergunta é feita novamente porque aquela resposta nao é valida.. Quero fazer o mesmo para letras. Se introduzir uma letra, por exemplo o caracter x a pergunta é feita novamente.

    Perceberam? Estou a ser confusa?
     
  6. Goncalo Silva

    Goncalo Silva Power Member

    Usa antes uma implementação do getline. Supondo que estás a trabalhar em C, e não em C++, precisas de implementar a função. Tenho aqui uma de um projecto meu anterior:

    Código:
    /**
     * Getline implementation in C
     */
    int getline(char *s, int lim) {
        char *t;
        int c;
    
        t = s;
        while((--lim > 1) && ((c=getchar()) != EOF) && (c != '\n'))
            *s++ = c;
        if(lim == 1) {
            fprintf(stderr, "WARNING. getline: Line too long.\n");
            exit(-1);
        }
        *s = '\0';
        return s - t;
    }
    É melhor prática. Depois disto, apenas tens de filtrar os "alcances" (ranges) usando a tabela ASCII da posição 0 do que foi lido. Se queres apenas letras, queres < codigo_do_z e > codigo_do_a. Se queres numeros, queres < codigo_do_9 e > codigo_do_0. Se forem números, não te esqueças de fazer o atoi do buffer[0].

    Podes alterar ligeiramente o código para ler apenas o primeiro caracter e descartar todos os seguintes (mas descartá-los mesmo, senão ficam no buffer de entrada).
     
  7. _freelancer_

    _freelancer_ Power Member

    Eu percebi o teu problema e penso ter a solução.

    -> dad.conta_pouhab é um inteiro.
    -> Por defeito, os inteiros são inicializados com o valor 0.

    Agora, pelo que eu pude testar (em Linux), o comportamento do scanf é que quando usas o placeholder %d (que é exclusivo para valores inteiros) e passas outra coisa que não seja números ao scanf pelo teclado, ele simplesmente limita-se a deixar o valor que estava na variável intocado. Ou seja, imagina que tinhas:

    Código:
    dad.conta_pouhab = 2000;
    ...e depois tinhas:

    Código:
    scanf("%d", &dad.conta_pouhab);
    E nesta segunda operação, escrevias "abc" pelo teclado. Depois do scanf, a variável dad.conta_pouhab iria ter 2000 tal como tinha antes do scanf. Isto é, o valor só muda quando lhe passas um inteiro válido, que ele consegue processar.

    Ora, isto resulta num problema muito grave no teu caso. Assumindo que a variável está realmente inicializada a 0, quando o utilizador mete lixo no input (i.e. texto em vez de algarismos), a variável continua com o valor 0...... QUE por acaso, é um valor válido para a tua verificação.

    Moral da história: ou alteras o teu espaço de resultados possíveis de 0 e 1 para, por exemplo, 1 e 2; ou inicializas a variável com outro valor (-1 costuma ser uma boa opção). Fica ao teu critério :)
     
  8. Mr_Miguel

    Mr_Miguel Power Member

    Esta afirmação não é necessariamente verdadeira. Comparem-se as seguintes instruções:

    Código:
    int x;
    int y = 0;
    
    Apenas a segunda garante que é um inteiro inicializado com o valor 0.

    Quanto a essa questão do scanf, pode-se perfeitamente verificar se o utilizador introduziu um número inteiro - muito embora algumas pessoas possam não o saber, o scanf tem um valor de retorno, que corresponde ao número de conversões bem sucedidas.

    Exemplo:

    Código:
    int valor_do_scanf = scanf("%d", &o_meu_int);
    
    Quantos itens queremos converter neste caso? Apenas um, especificado pelo %d. Por isso, a variável "valor_do_scanf" tomará um de dois valores possíveis:

    0, se a conversão para inteiro não tiver sido bem sucedida.
    1, se a conversão para inteiro tiver sido bem sucedida.

    Com isto, se o utilizador introduzir "abc" como disseste, a variável "o_meu_int" permanecerá inalterada de facto, mas possuímos agora outra variável "valor_do_scanf" que nos vai permitir detectar se houve algum erro.

    Cumprimentos.
     
  9. Neptune

    Neptune 1st Folding then Sex

    O teu problema é que a protecção do scanf não está a ser bem feita. Falta introduzir aí um scanf que descarte os caracteres não numéricos deixados pelo utilizador na entrada padrão bem como utilizar o valor de retorno do já existente para saber se ele leu correctamente um valor.

    Fica assim então:

    Código:
    do {
        printf("\nUtiliza conta poupanca-habitacao (1-Sim, 0-Nao):\n\n");
        printf("Opcao:");
        j=scanf("%d",&dad);
        scanf("%*[^\n]");
    }while((dad<0 || dad>1) && j<1);
     
  10. Master_piece

    Master_piece Power Member


    Desculpa la mas para que serve o J e esse segundo scanf()

    </div>
     
  11. _freelancer_

    _freelancer_ Power Member

    O segundo scanf serve para limpar o STDIN (i.e. para remover o \n que lá fica depois de pressionares ENTER) e o j é para garantir que o primeiro scanf processa algo. (j == 1, então recebeu um parametro).
     
  12. Master_piece

    Master_piece Power Member

    Mas esse scanf() só irá ser necessário no caso de se introduzir caracteres inválidos, pois iremos ter que voltar a introduzir. Corrigeme se estiver errado.

    Nesse caso não bastava colocar um space antes de %d.

    assim:
    Código:
    do {
        printf("\nUtiliza conta poupanca-habitacao (1-Sim, 0-Nao):\n\n");
        printf("Opcao:");
        j=scanf(" %d",&dad);
       }while((dad<0 || dad>1) && j<1);
     
    Última edição pelo moderador: 20 de Julho de 2008
  13. Neptune

    Neptune 1st Folding then Sex

    Exacto.

    O objectivo não era prever casos de input de caracteres inválidos para o programa em questão? Um espaço antes de %d não irá fazer nada. O funcionamento do scanf consiste em ler aquilo que lhe é mandado ler até encontrar um \n. Se deres um espaço (ou quantos quiseres) e só depois colocares o número ele lê bem na mesma com o código que eu aqui coloquei (sem qualquer espaço). O único problema que existia era não descartar os caracteres inválidos que ficavam no stdin, o que causava um erro ou um loop infinito no programa original. Esta limpeza do buffer pode ser feita da forma que indiquei ou através de um gets.
     
    Última edição: 20 de Julho de 2008
  14. deepshoot

    deepshoot Power Member


    Pode-se limpar o buffer do teclado atraves de fflush(stdin);
    Dá muito jeito mesmo pa capar nomes através do gets, ou getfs.

    Já agor, se alguém me puder ajudar, como faço validação através do código ascii?!
    Já tou farto de tentar e não consigo, pensava que era do género:
    while(a!='\65');
    Mas não me está a dar resultados...se alguém puder ajudar agradeço.

    Cumps
     
    Última edição: 16 de Janeiro de 2009

Partilhar esta Página