CPF data in a C struct

2

Hello. I'm having a problem reading data from a CPF. I tried using int, long int or even a char vector [12]. With char I keep the CPF's containing '0' at startup, and with int or long int it does not return correct due to size. I need to sort with this data too and the order is not correct either. I think it's due to the wrong data type.

    
asked by anonymous 21.06.2014 / 18:37

2 answers

4

There are several ways you can save a cpf in memory / database.

  • String: use char[12] , or else char[11] since you know the size. Be sure to never use operations that expect a null-terminated string, such as strcpy . Use memcpy or even strncpy instead.

  • Array: save each digit in an array. It can be uint8_t[11] . It is similar to using the string option. But you will need to use a loop to do any operation with the digits.

  • Integer: Use a single uint64_t . It is the simplest way to operate if you do not need separate digits. To display the screen use: print("cpf: %011"PRIu64".", cpf); Explaining the format: an integer uint64_t with 11 digits in size, filling in the missing space with 0 . The PRIu64 macro denotes the string used in printf . For scanf you can use this way: scanf("%"SCNu64, &cpf);

  • Any of the three serves and no doubt there are more. Choose the one that best suits your specific case.

        
    21.06.2014 / 19:50
    2

    Hello, the main problem of storing number with zero start starts when the number has more than 7 digits, as is the case of the CPF. The compiler believes that when a number has more than 7 digits and starts with zero it is from base 8. Causing some problems for us. The best option is to store the numbers in this case as a string.

    For example, to check if the number of numbers is correct we could do something like:

    #include <stdio.h>
    #include <string.h>
    
    
    int checkCPF(char* cpf) {
            printf("CPF como string: %s \n", cpf);
            printf("Números do CPF: %lu \n", strlen(cpf));
            if(strlen(cpf)==11) {
                return 1;
            }
            return 0;
    }
    
    
    int main() {
            char* cpfA = "18315228889";
            char* cpfB = "0031522888";
    
            checkCPF(cpfA);
            checkCPF(cpfB);
    
            return 0;
    }
    

    But this is not very practical if you are to work with the numbers themselves, perform some type of validation or take only a part of the number, in this case we can use a CPF structure, you can implement its structure the way you want , for example:

    typedef struct _CPF{
        unsigned int a;
        unsigned int b;
        unsigned int c;
        unsigned int verificador;
    } CPF;
    

    It's a very simple structure, and you can work with numbers in isolation. To get the full CPF as a long int you can use a function like:

    long int getCPFCompleto(CPF cpf) {
        long int cpfCompleto = 0;
        char buffer[12];
        char* fixEnd;
        sprintf(buffer, "%d%d%d%d", cpf.a, cpf.b, cpf.c, cpf.verificador);
        cpfCompleto = strtol (buffer,&fixEnd,10);
        return cpfCompleto;
    }
    

    Of course, if the CPF has the first number 0 in any of the elements this can cause problems so it is better to return the value as a string again.

    The logic is complete. I will post only the complete commented code and hope that I can help you with something.

    #include <stdio.h>
    #include <stdlib.h> // malloc
    
    // Nossa estrutura básica para armazenar o CPF
    typedef struct _CPF{
        unsigned int a;
        unsigned int b;
        unsigned int c;
        unsigned int verificador;
    } CPF;
    
    
    // Retorna o CPF completo
    // É possivel informar se queremos o número formatado ou não
    void getCPFCompleto(char* buffer, CPF cpf, int formatado) {
        long int cpfCompleto = 0;
    
        // Aqui está um ponto fundamental
        // Perceba que informmos %03d informando que esperamos 3 dígitios
        // Caso ele conter menos que 3 digitos ele adiciona zero a esquerda.
        // Execeto no número verificado com 2 dígitos
        if(formatado)
            sprintf(buffer, "%03d.%03d.%03d-%02d", cpf.a, cpf.b, cpf.c, cpf.verificador);
        else
            sprintf(buffer, "%03d%03d%03d%02d", cpf.a, cpf.b, cpf.c, cpf.verificador);
    }
    
    // Populamos nossa variavel CPF
    void populateCPF(CPF* cpf, char* cpfString, int formatado) {
        if(formatado)
            sscanf(cpfString, "%03u.%03u.%03u-%02u", &cpf->a, &cpf->b, &cpf->c, &cpf->verificador);
        else
            sscanf(cpfString, "%03d%03d%03d%02d", &cpf->a, &cpf->b, &cpf->c, &cpf->verificador);
    }
    
    
    
    int main() {
        CPF mCPF;
        char* cpfCompleto;
    
        // Alocamos 15 caso o valor retornado possuir formatação
        cpfCompleto = (char*) malloc(15*sizeof(char));
    
        // Passamos nossa o ponteiro para nossa variavel CPF
        // O CPF para ser formatado como string
        // E se o número é formatado ou não
        populateCPF(&mCPF, "08315228802", 0);
    
        // Podemos imprimir os elementos de forma unitaria
        printf("CPF A: %03d\n", mCPF.a);
        printf("CPF B: %03d\n", mCPF.b);
        printf("CPF C: %03d\n", mCPF.c);
        printf("CPF Verificador: %02d\n", mCPF.verificador);
    
    
        // Podemos imprimir o número completo utilizando a função
        // getCPFCompleto
        // Informamos um ponteiro para char a variavel com o CPF
        // e se queremos formatada ou não
    
        getCPFCompleto(cpfCompleto, mCPF, 0);
        printf("O número do CPF completo é: %s \n", cpfCompleto);
    
    
        // Vamos liberar a memoria do buffer
        free(cpfCompleto);
    
        return 0;
    };
    
        
    21.06.2014 / 20:06