Ir ao conteúdo
  • Cadastre-se

C++ Consigo VALIDAR CPF tendo essa informação dentro de uma STRUCT?


Caio Lopez

Posts recomendados

Olá gente, estou estudando a Linguagem C++ e gostaria de saber se é possível validar um CPF puxando este DADO de dentro de uma Struct.

• Eu estou querendo testar a possibilidade de chamar esse CPF que terá um valor atribuído dentro da struct, pra uma validação.
• Coloquei ele em CHAR porque toda vez que eu tentava mostrar ele na tela lá no final, não funcionava (aparecia um monte de numero aleatorio).
• Além disso gostaria de saber se é possível atribuir os PONTOS e TRAÇOS (xxx.xxx.xxx.-xx), fazendo com que eles sejam mostrados na tela lá no final (Forçando o CPF a ficar formatado dessa forma).

 

O código abaixo está funcionando normalmente, vocês podem testar pra verem melhor do que se trata 🙂

Sou Novo nesse meio então desculpem qualquer erro bobo, dicas serão sempre bem vindas !

 

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <locale.h>

#define TAM 1


typedef struct {
	char nome[16];
	char cpf[12];
}cadastro;

int main (){
    
    cadastro ficha[TAM];
    
    int i, j;
    long long dig1, dig2, aux;   
   


    
    for (i=0; i<TAM; i++)
    {   
         
        printf ("\n*** Cadastro %d ***\n", i+1);
        printf ("Nome: ");
        scanf ("%30[^\n]s", &ficha[i].nome);

        fflush(stdin);
        printf("\nInforme seu CPF: ");
        scanf ("%s", &ficha[i].cpf);
        fflush(stdin);
	}
                     
    printf ("\n\n*** CONSULTA NO CADASTRO ***\n");
    printf ("Escolha uma posicão a exibir (1 a 10): "); // POR ENQUANTO SÓ FUNCIONARA O NUMERO 1 PORQUE EU DEFINI O VETOR TAM = 1, A IDEIA É ARMAZENAR MAIS CONTATOS DEPOIS AUMENTANDO O TAMANHO DO VETOR
    scanf ("%d", &i);
    printf ("Nome: %s\n", ficha[i-1].nome);
    printf ("CPF:  %s \n" , ficha[i-1].cpf);
  
}

 

  • Curtir 1
  • Obrigado 1
Link para o comentário
Compartilhar em outros sites

@Caio Lopez

41 minutos atrás, Caio Lopez disse:

estou estudando a Linguagem C++

🤔

O código que postou foi escrito em C, de C++ não tem nada.

 

1 hora atrás, Caio Lopez disse:
scanf ("%30[^\n]s", &ficha[i].nome);

fflush(stdin);
printf("\nInforme seu CPF: ");
scanf ("%s", &ficha[i].cpf);
fflush(stdin);

Não use fflush() para fluxos de entrada, apenas de saída.

Não precisa do & nesse caso, está lendo strings.

 

43 minutos atrás, Caio Lopez disse:

gostaria de saber se é possível validar um CPF puxando este DADO de dentro de uma Struct

Sim. Depois de ter a string `cpf´ em mãos, calcule o dígito verificador e compare com o inserido pelo usuário.

 

49 minutos atrás, Caio Lopez disse:

chamar esse CPF que terá um valor atribuído dentro da struct, pra uma validação

`cpf´ é um membro da struct `cadastro´, e para acessá-lo, considerando seu código, basta escrever ficha[indice].cpf.

Nada distingue `cpf´ de uma string qualquer, um valor atribuído à ela será somente atribuído à ela, e não "dentro da struct" ou coisa assim.

 

56 minutos atrás, Caio Lopez disse:

Coloquei ele em CHAR porque toda vez que eu tentava mostrar ele na tela lá no final, não funcionava (aparecia um monte de numero aleatorio)

Bem, e que outro tipo de dado tentou usar?

57 minutos atrás, Caio Lopez disse:
printf ("Nome: %s\n", ficha[i-1].nome);
printf ("CPF:  %s \n" , ficha[i-1].cpf);

Está usando o especificador de strings, não há razão para imprimir algo que não é uma string com isso.

 

1 hora atrás, Caio Lopez disse:

Além disso gostaria de saber se é possível atribuir os PONTOS e TRAÇOS (xxx.xxx.xxx.-xx), fazendo com que eles sejam mostrados na tela lá no final (Forçando o CPF a ficar formatado dessa forma)

Basta imprimir nesse formato...

#include <stdio.h>

int main()
{
    char dg[12] = "12345678912";
    
    printf("%c%c%c.%c%c%c.%c%c%c-%c%c",
    dg[0],dg[1],dg[2],
    dg[3],dg[4],dg[5],
    dg[6],dg[7],dg[8],
    dg[9],dg[10]);

    return 0;
}

Você poderia também usar sprintf(), veja:

#include <stdio.h>

int main()
{
    char dg[12] = "12345678912";
    char cpf[15];
    
    sprintf(cpf,
    "%c%c%c.%c%c%c.%c%c%c-%c%c",
    dg[0],dg[1],dg[2],
    dg[3],dg[4],dg[5],
    dg[6],dg[7],dg[8],
    dg[9],dg[10]);
    
    printf("%s", cpf);

    return 0;
}

A saída é a mesma:

image.png.df61a067741268a1032c227875ea3d4a.png

De qualquer forma, por que não pede ao usuário para inserir o cpf nesse formato?

  • Curtir 2
  • Obrigado 1
Link para o comentário
Compartilhar em outros sites

Citação

O código que postou foi escrito em C, de C++ não tem nada.

Eu sempre me confundo se é C / C++, estou tentando me acostumar com isso...
Desculpe por te definido o Tópico com a Linguagem errada.

 

Citação

Não use fflush() para fluxos de entrada, apenas de saída.

Não precisa do & nesse caso, está lendo strings.

Vou editar isso no meu código, obrigado !

 

Citação

Sim. Depois de ter a string `cpf´ em mãos, calcule o dígito verificador e compare com o inserido pelo usuário.

Vou dar uma olhada novamente nesse calculo do digito verificador, se eu não conseguir, volto aqui pra pedir uma luz haha 
Mas fico aliviado de que isso é possível.

 

Citação

Bem, e que outro tipo de dado tentou usar?

Eu estava usando INT, depois tentei long long.

 

Citação

Está usando o especificador de strings, não há razão para imprimir algo que não é uma string com isso.

Não entendi muito bem o que você quis dizer, o que posso fazer nesse caso?


 

  • Curtir 2
Link para o comentário
Compartilhar em outros sites

1 hora atrás, Caio Lopez disse:

Além disso gostaria de saber se é possível atribuir os PONTOS e TRAÇOS (xxx.xxx.xxx.-xx), fazendo com que eles sejam mostrados na tela lá no final (Forçando o CPF a ficar formatado dessa forma).

 

eu recomendo você deixar os números do cpf intactos na estrutura (sem as pontuações) porque para manipular depois será mais fácil.

para mostrar o Cpf pontuado você pode fazer algo assim

void
mostraCpf(char *cpf)
{
    int contador;
    for (contador = 0; cpf[contador] || contador < T_CPF-1; contador++) {
        printf("%c", cpf[contador]);
        if (contador+1 == 3 || contador+1 == 6) {
            printf(".");
        } else if (contador+1 == 9) {
            printf("-");
        }
    }
    printf("\n");
}

 

O exemplo completo com a validação do cpf

Spoiler
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>

#define T_CPF 12

void
mostraCpf(char *cpf);

int
validaCpf(char *cpf);

int main(void)
{
    char *cpf = "54706678552";
    mostraCpf(cpf);
    if (validaCpf(cpf)) {
        printf("Cpf valido!\n");
    } else {
        printf("Cpf invalido!\n");
    }
    getchar();
    return(0);
}

void
mostraCpf(char *cpf)
{
    int contador;
    for (contador = 0; cpf[contador] || contador < T_CPF-1; contador++) {
        printf("%c", cpf[contador]);
        if (contador+1 == 3 || contador+1 == 6) {
            printf(".");
        } else if (contador+1 == 9) {
            printf("-");
        }
    }
    printf("\n");
}


int
validaCpf(char *cpf)
{
    int digito, soma = 0, contador, aux;
    char tmp[2] = {'\0'};
    /* Testa se o tamanho do cpf está correto */
    if (strlen(cpf) == T_CPF-1) {
        /* Verifica se todos são numeros ou se contem caracteres */
        for (contador = 0; contador < T_CPF-1; contador++) {
            if (isalnum(cpf[contador])) {
                soma++;
            }
        }

        if (soma != T_CPF-1) {
            return(0);  /* Invalido */
        }

        soma = 0;
        for (contador = 0, aux = 10; contador < 9; contador++, aux--) {
            /* Converte para inteiro o digito */
            tmp[0] = cpf[contador];
            digito = atoi(tmp);
            soma += (digito*aux);
        }

        tmp[0] = cpf[9];
        digito = atoi(tmp);
        if ((soma*10)%11 == digito || (((soma*10)%11) == 10 && digito == 0)) {
            soma = 0;
            for (contador = 0, aux = 11; contador < 10; contador++, aux--) {
                tmp[0] = cpf[contador];
                digito = atoi(tmp);
                soma += (digito*aux);
            }

            tmp[0] = cpf[10];
            digito = atoi(tmp);
            if ((soma*10)%11 == digito || (((soma*10)%11) == 10 && digito == 0)) {
                return(1);      /* Valido */
            }
        }
    }
    return(0);
}

 

 

  • Curtir 1
  • Obrigado 1
Link para o comentário
Compartilhar em outros sites

@Caio Lopez

39 minutos atrás, Caio Lopez disse:

Vou editar isso no meu código, obrigado !

Quando chamamos a scanf(), teclamos Enter para finalizar a leitura, portanto sobra um '\n' na stdin que pode interferir na próxima leitura, de qualquer forma, fflush() só está definida para fluxos de saída, então considere usar um especificador no seguinte formato para ler e ignorar o '\n': %*c. Por exemplo:

#include <stdio.h>

int main()
{
    int x;
    char c;

    printf("Numero: ");
    scanf("%d%*c", &x);

    printf("Letra: ");
    scanf("%c%*c", &c);

    printf("%d\n%c\n", x, c);

    return 0;
}

Experimente sem o %*c aí e veja o '\n' sendo lido na segunda chamada da scanf(), impedindo o usuário de digitar o pretendido.

 

39 minutos atrás, Caio Lopez disse:

Mas fico aliviado de que isso é possível.

Os membros da struct são variáveis quaisquer. Isso já seria possível com ou sem struct.

 

39 minutos atrás, Caio Lopez disse:

Não entendi muito bem o que você quis dizer, o que posso fazer nesse caso?

Se declarou `cpf´ como sendo do tipo int ou long long, deve usar o especificador de formato correspondente ou pode ter surpresas na saída.

 

Se quer extrair algo da string `cpf´, pode usar sscanf(), por exemplo:

#include <stdio.h>

int main()
{
    char cpf[15] = "123.456.789-12";
    int dg[4];
    
    sscanf(cpf, "%d%*c%d%*c%d%*c%d",
    &dg[0], &dg[1], &dg[2], &dg[3]);
    
    printf("%d.%d.%d-%d", dg[0], dg[1], dg[2], dg[3]);

    return 0;
}

Olha o %*c aí de novo :D

Ele serve pra ler e ignorar um caractere, no caso o '.' e o '-' da string.

Na saída temos:

image.png.1ca82ccb1b3b4de5cada786bfd8bf56b.png

Isso pode lhe ser útil para calcular o dígito verificador.

Da mesma forma, você pode simplesmente usar scanf() para ler 4 inteiros sem a necessidade de ler uma string e ler 4 inteiros a partir desta:

#include <stdio.h>

int main()
{
    int dg[4];
    
    scanf("%d%*c%d%*c%d%*c%d",
    &dg[0], &dg[1], &dg[2], &dg[3]);
    
    printf("%d.%d.%d-%d", dg[0], dg[1], dg[2], dg[3]);

    return 0;
}
  • Curtir 1
  • Obrigado 2
Link para o comentário
Compartilhar em outros sites

1 hora atrás, Caio Lopez disse:

Vou dar uma olhada novamente nesse calculo do digito verificador, se eu não conseguir, volto aqui pra pedir uma luz haha 

 

 

3 horas atrás, Caio Lopez disse:

Eu estou querendo testar a possibilidade de chamar esse CPF que terá um valor atribuído dentro da struct, pra uma validação.
• Coloquei ele em CHAR porque toda vez que eu tentava mostrar ele na tela lá no final, não funcionava (aparecia um monte de numero aleatorio).

 

Eu já postei aqui programas e, C para calcular o dígito ou conferir de um número já existente. acho que pode pesquisar no conteúdo aqui do forum que eu postei, por exemplo.

 

É mehor usar char[] se vai calcular os DV. Se usar long tem que fazer muitas contas a toa.

 

Não faz diferença de o CPF estiver em uma struct ou em uma struct dentro de outra dentro de outra... Desde que tenha um endereço para acessar :) 

 

1 hora atrás, Caio Lopez disse:

Mas fico aliviado de que isso é possível.

 

Está programando em C. O sistema foi escrito em C (Unix, Windows, Android, MacOS, linux..). O compilador C foi escrito em C. Se pegar o CPF de um banco de dados boa chance do banco de dados ter sido escrito em  C (ou C++).  Então não fique surpreso: tudo é possível em C.

 

  • Obrigado 2
Link para o comentário
Compartilhar em outros sites

@kgin

Consegui utilizar seu código dentro do meu e ficou interessante demais.
Só estou com dificuldades de atribuir ele a um laço de repetição, poderia me ajudar?
 

do {
        printf("Informe seu CPF: ");
        scanf ("%s", &ficha[i].cpf);
        char *cpf = &ficha[i].cpf;
        mostraCpf(cpf);
        if (validaCpf(cpf)) {
        printf("Cpf valido!\n");
        } else {
        printf("Cpf invalido!\n");
        }
        getchar();
        } while ();


Nesse caso, eu tentei usar o DO-WHILE, porém não consigo inserir algo dentro do "while" que identifique a parte que alega quando o CPF é inválido.
A ideia basicamente é: 
Inseriu o CPF certo, segue para os próximos dados que meu código pedir (CELULAR, DATA DE NASCIMENTO), mas caso o CPF esteja invalido, o usuário tenha que inserir um  CPF válido pra seguir em frente.

Link para o comentário
Compartilhar em outros sites

10 horas atrás, Caio Lopez disse:

@kgin

Consegui utilizar seu código dentro do meu e ficou interessante demais.

Eu não recomendo você utilizar o meu código, principalmente a parte de validar o cpf.

Eu coloque só como exemplo, porque ele não vai detectar cpfs com sequencias repetidas.

10 horas atrás, Caio Lopez disse:

Nesse caso, eu tentei usar o DO-WHILE, porém não consigo inserir algo dentro do "while" que identifique a parte que alega quando o CPF é inválido.

Você já parou para pensar o que está acontecendo no if(validaCpf(cpf))?

 

Vou descrever para você em português

 

Se  validaCpf retornar verdadeiro (em C falso e 0 e verdadeiro e qualquer numero maior que 0) então faça a próxima instrução

 

No caso do do{}while() você teria que fazer algo assim

    do {
        char buffer[T_BUFFER];
        printf("Entre com o cpf:");
        fgets(buffer, T_BUFFER, stdin);
        /* retira o newLine do buffer (e o famoso enter) */
        buffer[strlen(buffer)-1] = '\0';
        /* Verifica se é possível copiar o buffer para o campo do cpf */
        if (strlen(buffer) == T_CPF-1) {
            strcpy(cpf, buffer);
            /* Verifica o cpf */
            if (validaCpf(cpf) == 1) {
                printf("Cpf valido!\n");
            } else {
                printf("Cpf invalido!\n");
            }
        }
    } while (validaCpf(cpf) == 0);

sempre utilize fgets() para lidar com caracteres e pesquise sobre os outros comandos da stdio.

 

Exemplo de como pegar entradas.

Spoiler
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>

#define T_BUFFER 256
#define T_CPF 12

void
mostraCpf(char *cpf);

int
validaCpf(char *cpf);

int main(void)
{
    char
        opcao,
        buffer[T_BUFFER],
        cpf[T_CPF] = {0};      /* Inicia os campos do cpf com 0 */

    do {
        /* Pega o cpf */
        printf("Digite o cpf sem pontos ou tracos:");
        fgets(buffer, T_BUFFER, stdin);
        /* retira o enter do buffer */
        buffer[strlen(buffer)-1] = '\0';
        /* verifica o tamanho do cpf digitado */
        if (strlen(buffer) == T_CPF-1) {
            /* Copia o cpf do buffer para o campo do cpf */
            strcpy(cpf, buffer);
            mostraCpf(cpf);
            if (validaCpf(cpf)) {
                printf("Cpf valido!\n");
            } else {
                printf("Cpf invalido!\n");
                /* limpa o cpf */
                memset(cpf, '\0', sizeof(cpf[0])*T_CPF);
            }
        } else {
            printf("Entrada invalida!\n");
        }

        /* Pega a opção */
        do {
            printf("Deseja entrar com o cpf novamente S\\N:");
            fgets(buffer, T_BUFFER, stdin);
            if (sscanf(buffer, "%c", &opcao) == 1) {
                if (toupper(opcao) != 'N' && toupper(opcao) != 'S')
                    printf("Entrada invalida\n");
            }
        } while (toupper(opcao) != 'S' && toupper(opcao) != 'N');

    } while (toupper(opcao) == 'S');

    if (validaCpf(cpf) == 1) {
        printf("Cpf cadastrado com sucesso\n");
        mostraCpf(cpf);
    } else {
        printf("Nenhum cpf foi cadastrado\n");
    }
    getchar();      /* Espera o enter */
    return(0);
}

void
mostraCpf(char *cpf)
{
    int contador;
    for (contador = 0; cpf[contador] || contador < T_CPF-1; contador++) {
        printf("%c", cpf[contador]);
        if (contador+1 == 3 || contador+1 == 6) {
            printf(".");
        } else if (contador+1 == 9) {
            printf("-");
        }
    }
    printf("\n");
}


int
validaCpf(char *cpf)
{
    int digito, soma = 0, contador, aux;
    char tmp[2] = {'\0'};
    /* Testa se o tamanho do cpf está correto */
    if (strlen(cpf) == T_CPF-1) {
        /* Verifica se todos são numeros ou se contem caracteres */
        for (contador = 0; contador < T_CPF-1; contador++) {
            if (isalnum(cpf[contador])) {
                soma++;
            }
        }

        if (soma != T_CPF-1) {
            return(0);  /* Invalido */
        }

        soma = 0;
        /* 
         * Multiplica os nove primeiros digitos do cpf pela sequencia 
         * decrescente de 9 a 2
         */
        for (contador = 0, aux = 10; contador < 9; contador++, aux--) {
            /* Converte de char para inteiro o digito */
            tmp[0] = cpf[contador];
            digito = atoi(tmp);
            soma += (digito*aux);
        }

        /* Converte de char para inteiro o digito primeiro digito verificador */
        tmp[0] = cpf[9];
        digito = atoi(tmp);
        if ((soma*10)%11 == digito || (((soma*10)%11) == 10 && digito == 0)) {
            soma = 0;
            /* 
            * Multiplica os dez primeiros digitos do cpf pela sequencia 
            * decrescente de 11 a 2
            */
            for (contador = 0, aux = 11; contador < 10; contador++, aux--) {
                tmp[0] = cpf[contador];
                digito = atoi(tmp);
                soma += (digito*aux);
            }

            tmp[0] = cpf[10];
            digito = atoi(tmp);
            if ((soma*10)%11 == digito || (((soma*10)%11) == 10 && digito == 0)) {
                return(1);      /* Valido */
            }
        }
    }
    return(0);
}

 

 

  • Curtir 1
  • Obrigado 1
Link para o comentário
Compartilhar em outros sites

13 horas atrás, Caio Lopez disse:

Consegui utilizar seu código dentro do meu e ficou interessante demais.

@kgin Aconselho evitar postar o código pronto ou o...

19 horas atrás, kgin disse:

exemplo completo

Como queira chamar :D

A maioria dos que recorrem ao fórum são estudantes que buscam a resposta para seu exercício, e não pensarão duas vezes antes de plagiar algum código que lhes foi enviado e que convenientemente é o que precisam 🤪

Te garanto, se for exatamente o que precisam, sequer irão ler seu código, e se faltar algo, não saberão como adicionar...

13 horas atrás, Caio Lopez disse:

estou com dificuldades de atribuir ele a um laço de repetição, poderia me ajudar?

Até porque não foram eles que escreveram :)

 

19 horas atrás, kgin disse:

para mostrar o Cpf pontuado você pode fazer algo assim

void
mostraCpf(char *cpf)
{
    int contador;
    for (contador = 0; cpf[contador] || contador < T_CPF-1; contador++) {
        printf("%c", cpf[contador]);
        if (contador+1 == 3 || contador+1 == 6) {
            printf(".");
        } else if (contador+1 == 9) {
            printf("-");
        }
    }
    printf("\n");
}

Uma chamada da printf() já não resolve?

20 horas atrás, Lucca Rodrigues disse:
printf("%c%c%c.%c%c%c.%c%c%c-%c%c",
    dg[0],dg[1],dg[2],
    dg[3],dg[4],dg[5],
    dg[6],dg[7],dg[8],
    dg[9],dg[10]);

 

2 horas atrás, kgin disse:

sempre utilize fgets() para lidar com caracteres

Se está lidando com um estudante, seja mais preciso...

@Caio Lopez fgets() é mais conveniente de usar do que scanf() por exemplo: te obriga a limitar a quantidade de caracteres os quais serão lidos e gravados, evita ter que usar um especificador de meio metro, etc 🤪

Nada te impede de usar scanf(), mas é preferível usar fgets(), dê uma olhada na documentação.

  • Obrigado 1
Link para o comentário
Compartilhar em outros sites

@Lucca Rodrigues

Eu estou tentando aprender a mexer com isso, achei interessante ele mandar o código daquela forma pra eu tentar implementar dentro do meu código, mas eu estou tentando compreender ele em um todo e ainda não finalizei minha atividade apesar de já ter ficado do jeito que eu pudesse encaminhar ao professor e ganhar a nota.
Estou aqui mexendo nele basicamente o tempo todo, quero poder entregar quando eu realmente tiver entendido o que estou realmente fazendo e entendido a Lógica do meu programa todo.
E concordo com tudo o que você disse, geralmente os estudantes só querem o código pronto pra se livrarem logo de uma atividade etc...
Quero que saiba, novamente, que estou tentando aprender de verdade e não me contento com algo mal feito e muito menos plagiado.

Fiz algumas alterações no código dele pra que funcionasse no meu, substitui as variaveis e consegui encaixar no laço de repetição de uma forma que acho que vocês vai pedir pra eu apagar porque vai estar muito irregular? hahaha
Ficou assim:


Na minha cabeça, eu pensei da seguinte forma:
Se "&ficha[i].cpf é o valor do CPF que eu insiro e T_CPF que partiu do código dele, pelo que entendi, trabalha com o processo do tamanho do código e também ta dentro da função de validação que verifica os caracteres..." 
Eu coloquei ele dentro de um While simples, dizendo que enquanto meu número do CPF for diferente do "aceito" (eu interpretei assim, não sei se ta certo), ele vai além de dizer que está INVÁLIDO, vai voltar pro inicio desse laço pedindo pra inserir novamente o CPF.
Quando fiz somente isso, criou um LOOP infinito e eu acabei colocando um BREAK, que ele para de repetir quando aquela condição ali de validação acontecer (for Válido) e dai o código continua normalmente.

 

while (&ficha[i].cpf != T_CPF)
        {
            printf("Informe seu CPF: ");
            scanf ("%s", &ficha[i].cpf);
            char *cpf = &ficha[i].cpf;
            if (validaCpf(cpf)) 
            {    
                printf("Cpf valido!\n");
                break;
            } else 
                {
                    printf("Cpf invalido!\n");
                }  
            getchar();
        } 

 

Testei suas dicas também sobre mostrar o CPF formatado com pontos e tudo mais, porém quando eu chego lá no final do código...
Eu ainda estou com um pouco de dificuldades, por conta desse [i-1], que não compreendi direito como ele funciona, eu só sei que se eu retirar ele, os numeros inseridos no CADASTRO não serão mostrados corretamente.
Ai quando eu tento por daquela forma que você me orientou a tentar fazer (pra formatar o CPF), eu não consigo rodar o código.
 

	printf ("\n\n*** CONSULTA NO CADASTRO ***\n");
    printf ("Escolha uma posicão a exibir (1 a 16): ");  // AQUI ESTÁ 16 porque SERIAM 16 REGISTROS QUE SERIAM FEITOS, NO CASO, SÓ VAI CONTER UM NO MOMENTO.
    scanf ("%d", &i);
    printf ("Nome: %s\n", ficha[i-1].nome);
    printf ("CPF: %d.%d.%d-%d", dg[0], dg[1], dg[2], dg[3], i-1);
    



 

Link para o comentário
Compartilhar em outros sites

@Caio Lopez

33 minutos atrás, Caio Lopez disse:

Eu ainda estou com um pouco de dificuldades, por conta desse [i-1], que não compreendi direito como ele funciona

[i-1]? desta linha?

33 minutos atrás, Caio Lopez disse:
printf ("Nome: %s\n", ficha[i-1].nome);

A primeira posição do vetor tem índice 0 e a última n-1, então...

33 minutos atrás, Caio Lopez disse:
printf ("Escolha uma posicão a exibir (1 a 16): ");

Logicamente devemos subtrair 1 do índice `i´, ou então peça para o usuário digitar um número de 0 a n-1, mas ficaria estranho :)

Lembre-se de alterar o tamanho n do vetor quando for testar:

Em 08/07/2021 às 16:35, Caio Lopez disse:
#define TAM 1

Deveria ser:

#define TAM 16

 

33 minutos atrás, Caio Lopez disse:

Ai quando eu tento por daquela forma que você me orientou a tentar fazer (pra formatar o CPF), eu não consigo rodar o código

Poste o código completo.

De qualquer forma...

33 minutos atrás, Caio Lopez disse:
printf ("CPF: %d.%d.%d-%d", dg[0], dg[1], dg[2], dg[3], i-1);

O intuito disso era só mostrar que você consegue ler inteiros a partir de uma string com sscanf(), ou ler os inteiros com scanf(). Isso lhe seria útil para calcular o dígito verificador.

Copiar e colar trechos de código não vai dar certo se não adaptar no contexto de seu código, até porque creio que você não declarou um vetor `dg´ :D

Inclusive tem um argumento a mais ali, um tal i-1 no final.

Se quer imprimir o cpf, sendo este uma string, pode fazer algo assim:

Em 08/07/2021 às 18:03, Lucca Rodrigues disse:
#include <stdio.h>

int main()
{
    char dg[12] = "12345678912";
    
    printf("%c%c%c.%c%c%c.%c%c%c-%c%c",
    dg[0],dg[1],dg[2],
    dg[3],dg[4],dg[5],
    dg[6],dg[7],dg[8],
    dg[9],dg[10]);

    return 0;
}

No contexto de seu código:

printf("%c%c%c.%c%c%c.%c%c%c-%c%c",
    ficha[i-1].cpf[0],ficha[i-1].cpf[1],ficha[i-1].cpf[2],
    ficha[i-1].cpf[3],ficha[i-1].cpf[4],ficha[i-1].cpf[5],
    ficha[i-1].cpf[6],ficha[i-1].cpf[7],ficha[i-1].cpf[8],
    ficha[i-1].cpf[9],ficha[i-1].cpf[10]);
  • Obrigado 1
Link para o comentário
Compartilhar em outros sites

@Lucca Rodrigues

 

Consegui formatar pra aparecer lá no final o CPF formatado, que legal !
No inicio eu dei uma leve confundida, achando que tinha que criar uma variavel pra isso, mas depois entendi que já tava criado dentro da propria struct que eu só precisava informar a posição igual você fez aqui:

 

printf("%c%c%c.%c%c%c.%c%c%c-%c%c",
    ficha[i-1].cpf[0],ficha[i-1].cpf[1],ficha[i-1].cpf[2],
    ficha[i-1].cpf[3],ficha[i-1].cpf[4],ficha[i-1].cpf[5],
    ficha[i-1].cpf[6],ficha[i-1].cpf[7],ficha[i-1].cpf[8],
    ficha[i-1].cpf[9],ficha[i-1].cpf[10]);

 

56 minutos atrás, Lucca Rodrigues disse:

Lembre-se de alterar o tamanho n do vetor quando for testar:
 

56 minutos atrás, Lucca Rodrigues disse:
printf ("CPF: %d.%d.%d-%d", dg[0], dg[1], dg[2], dg[3], i-1);

 

Eu coloquei como 1 só pra eu preencher uma vez os dados, pra não ter que digitar tudo 16 vezes.

Agora voltando a respeito da validação do CPF, eu vi pela internet que tem várias formas de construir essa validação...
Vou dar uma olhada no conteúdo do @arfneto que ele diz que criou um Tópico ensinando como fazer e vou tentar construir um do Zero e depois implementar nesse meu código.
Se você @Lucca Rodrigues conhecer algum lugar que eu possa compreender a construção desse código pra validar o CPF, construindo um código a partir do zero, ficaria agradecido (Na verdade já estou mais que agradecido pelo suporte que vocês tem me dado aqui, obrigado de verdade !)
Acredito que assim, eu consiga aprender bem mais, porque apesar de eu poder estudar o código do @kgin, acho que é interessante eu criar esse código partindo da lógica da construção dele.

Comecei minha faculdade no inicio do Ano, então ainda estou bem iniciante hahaha
Obrigado pelos toques quando eu digo algo de forma errada (começando pelo próprio Tópico que aleguei estar em C++).
 

Link para o comentário
Compartilhar em outros sites

@Caio Lopez

4 minutos atrás, Caio Lopez disse:

conhecer algum lugar que eu possa compreender a construção desse código pra validar o CPF

Basta dar uma googlada em como validar um CPF.

Tem várias postagens no fórum sobre isso... Estarei colando aqui uma postagem minha de um tempo atrás.

Citação

Vamos considerar o CPF 145.382.206-20.

1. Multiplicar cada dígito da esquerda para a direita do CPF (desconsiderando os dois últimos dígitos), começando pelo multiplicador 10 e decrementando 1 a cada nova multiplicação.

2. Somar os produtos, obter o resto da divisão por 11 e caso o mesmo seja menor que 2, o nosso primeiro dígito verificador se torna 0, caso contrário, efetuamos a subtração de 11 pelo valor obtido.

3. Multiplicar cada dígito da esquerda para a direita do CPF (desconsiderando apenas o último dígito dessa vez, pois já obtemos um dos dígitos), começando pelo multiplicador 11 e decrementando 1 a cada nova multiplicação.

4. Somar os produtos, obter o resto da divisão por 11 e caso o mesmo seja menor que 2, o nosso segundo dígito verificador se torna 0, caso contrário, efetuamos a subtração de 11 pelo valor obtido.

5. Com os dois dígitos em mãos, caso os inseridos sejam iguais a esses calculados, o CPF é válido.

 

Um exemplo: 145.382.206-20

1  X 10 = 10

4 X 9 = 36

5 X 8 = 40

3 X 7 = 21

8 X 6 = 48

2 X 5 = 10

2 X 4 = 8

0 X 3 = 0

6 X 2 = 12

10 + 36 + 40 + 21 + 48 + 10 + 8 + 0 + 12 = 185

185 % 11 = 9

11 - 9 = 2 ---> Dígito 1

 

1  X 11 = 11

4 X 10 = 40

5 X 9 = 45

3 X 8 = 24

8 X 7 = 56

2 X 6 = 12

2 X 5 = 10

0 X 4 = 0

6 X 3 = 18

2 X 2 = 4

11 + 40 + 45 + 24 + 56 + 12 + 10 + 0 + 18 + 4 = 220

220 % 11 = 0 ---> Dígito 2

 

CPF: 145.382.206-20, dígito verificador calculado: 20, logo, o CPF é válido.

 

9 minutos atrás, Caio Lopez disse:

acho que é interessante eu criar esse código partindo da lógica da construção dele

O método é só um, tente criar o seu código, tenho certeza que consegue.

  • Obrigado 1
Link para o comentário
Compartilhar em outros sites

23 minutos atrás, Caio Lopez disse:

conhecer algum lugar que eu possa compreender a construção desse código pra validar o CPF

 

Isso deve estar em alguma norma da SRF, mas eu nunca achei isso na legislação. No entanto é uma forma de cálculo comum, chamada de módulo 11. módulo 10 é outro cálculo comum, e CRC é outra bem conhecida. Pode ver todos na WikiPedia ou perguntar aqui de novo.  A ideia é fazer umas contas com o número e calcular um ou mais dígitos que são acrescentados ao número original. Isso acontece por exemplo com RG, CPF e os campos que constam de todo cheque.

 

No caso do CPF eu postei aqui exemplos em C, C++ e java e as funções em C estão aqui:
 

int			calculaDV(const char*);
int			DV_ok(const char*);

 

calculaDV() retorna um número entre 0 e 99 que é o tal DV do cpf. DV_ok() retorna 1 se o dígito está ok ou 0 para erro, o clássico em C

 

Como usar? trivial: como foi declarado const char o argumento, não precisa sequer de uma variável e pode chamar assim
 


    const char* numero = "111222333";
    int n = calculaDV(numero); // n = DV em decimal
    // ou mesmo 
    n = calculaDV("04504630028");

 

e DV_ok() é igual:
 

	if ( DV_ok("11122233396") )
		printf("DV ok\n");
	else
		printf("DV incorreto\n");

 

E nesse caso estaria certo: 96.

 

Vou deixar um exemplo completo abaixo

 

Lendo um CPF

 

Para ler um CPF talve seja mais simples usar uma função e deixar o cara digitar de qualquer jeito. É muito mais simples e o usuário pode preferir digitar bonitinho para se orientar ou só pra ver se você pensou nisso. E é um programa em C. Não custa nada.

 

    int			le_CPF(char*);

 

Imagine uma função com esse nome que lê um CPF e retorna 9 ou 11 se leu um CPF completo sem ou com os DV e algo negativo se não leu direito.

 

Como ler um CPF então?
 

	char	teste[15];
	int res = le_CPF(teste);

 

Pois é, Nada mais. 

 

Eis um exemplo que lê um CPF e se o cara digitou só 9 dígitos calcula os DV e mostra e se o cara digitou 11 confirma se os DV são válidos.

 

	// agora tenta ler um CPF
	printf("\nTenta ler um CPF\n\n");
	char	teste[15];
	int res = le_CPF(teste);
	if (res < 0)
	{
		printf("Erro %d!\n", res);
		return -1;
	};
	// se leu com DV confere
	if (res == 11)
	{	// com DV
		if (DV_ok(teste))
			printf("DV ok!");
		else
			printf("DVD incorreto!");
	}
	else // calcula e mostra o DV
		printf("DV calculados para \"%s\": '%d'\n",	teste, calculaDV(teste));

 

Um exemplo completo

 

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

int			calculaDV(const char*);
int			DV_ok(const char*);
int			le_CPF(char*);


int main(int argc, char** argv)
{
	const char* numero = "111222333";
	int n = calculaDV(numero); // n = DV em decimal
	char DV1 = n / 10 + '0'; // um char
	char DV2 = n % 10 + '0'; // outro char
	printf("\
Para o CPF '%s' digitos verificadores = %d, DV1 = '%c' DV2 = '%c'\n",
		numero, n, DV1, DV2 );

	// agora pega os DV calculados e coloca em uma
	// string para testar com a outra rotina
	char numero_com_dv[15] = { 0 };
	memcpy(numero_com_dv, numero, 9);
	numero_com_dv[9] = DV1;
	numero_com_dv[10] = DV2;
	printf("numero com DV: '%s'\nTestando %d como DV para %s: ", 
		numero_com_dv, n, numero );
	if ( DV_ok(numero_com_dv) )
		printf("DV ok\n");
	else
		printf("DV incorreto\n");

	// agora tenta ler um CPF
	printf("\nTenta ler um CPF\n\n");
	char	teste[15];
	int res = le_CPF(teste);
	if (res < 0)
	{
		printf("Erro %d!\n", res);
		return -1;
	};
	// se leu com DV confere
	if (res == 11)
	{	// com DV
		if (DV_ok(teste))
			printf("DV ok!");
		else
			printf("DVD incorreto!");
	}
	else // calcula e mostra o DV
		printf("DV calculados para \"%s\": '%d'\n",	teste, calculaDV(teste));

	return 0;
};	// main


int calculaDV(const char* numero)
{
	// aqui vão os digitos 1 a 1 para calcular os DV
	int digito[11] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
	int soma = 0;
	int i = 0;
	for (i = 0; i < 9; i += 1) digito[i] = numero[i] - '0';

	// o primeiro digito verificador, modulo 11 dos 9
	soma = 0;
	for (i = 0; i < 9; i = i + 1)
		soma = soma + digito[i] * (10 - i); // 10..2
	// essa e a conta que da nome ao processo
	soma = soma % 11;
	if (soma > 1)
		digito[9] = 11 - soma;
	else
		digito[9] = 0;

	// o segundo DV, modulo 11 dos 10
	soma = 0;
	for (i = 0; i < 10; i = i + 1)
		soma = soma + digito[i] * (11 - i); // 11..2
	// essa e a conta que da nome ao processo
	soma = soma % 11;
	if (soma > 1)
		digito[10] = 11 - soma;
	else
		digito[10] = 0;

	//printf("\nDV calculados: %d %d\n", digito[9], digito[10]);
	return digito[9] * 10 + digito[10];
};	


int DV_ok(const char* numero)
{
	if (strlen(numero) < 11) return 0;
	char cpf[10];
	memcpy(cpf, numero, 9);
	cpf[9] = 0;
	int dv = (numero[9] - '0') * 10
		+ numero[10] - '0';
	int calculado = calculaDV(cpf);
	return (dv == calculado);
}


int le_CPF(char* cpf)
{
	char	linha[15];
	char*	p = linha; // um ponteiro para o retorno
	printf("Digite CPF (com ou sem pontos/DV): ");
	p = fgets(linha, 15, stdin);
	if (p == NULL) return -1; // não leu nada

	// precisa de 9 sem DV ou 11 digitos com DV
	char	temp[15] = { 0 }; // para montar o CPF
	char*	sai = temp; // aponta para o prox digito na saida

	char	n_digitos = 0;
	while (*p != 0)
	{	// tenta ler os digitos
		if ((*p >= '0') && (*p <= '9'))
		{ // digito
			*sai = *p; // copia o digito
			n_digitos += 1;
			sai += 1;
		};
		p += 1; // avanca a entrada
	};	// while()
	if ((n_digitos != 9) && (n_digitos != 11)) return -2; // tem que ter 9 ou 11
	strcpy(cpf, temp);
	return n_digitos;
};

 

mostraria
 

Para o CPF '111222333' digitos verificadores = 96, DV1 = '9' DV2 = '6'
numero com DV: '11122233396'
Testando 96 como DV para 111222333: DV ok

Tenta ler um CPF

Digite CPF (com ou sem pontos/DV): 111.222.333-96
leu 11 digitos: "11122233396"
DV ok!

 

Rode em seu computador e adapte :) 

  • Obrigado 1
Link para o comentário
Compartilhar em outros sites

Crie uma conta ou entre para comentar

Você precisa ser um usuário para fazer um comentário

Criar uma conta

Crie uma nova conta em nossa comunidade. É fácil!

Crie uma nova conta

Entrar

Já tem uma conta? Faça o login.

Entrar agora

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...

 

GRÁTIS: ebook Redes Wi-Fi – 2ª Edição

EBOOK GRÁTIS!

CLIQUE AQUI E BAIXE AGORA MESMO!