CPF data in a C Struct

Asked

Viewed 3,403 times

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 can keep the CPF’s that contain '0' at the beginning, and with int or long int it does not return correct due to size. I need to sort with this data as well and the order is not correct either. I believe it is due to the type of data that is incorrect.

  • 1

    With numerics you simply add the zeros to the left when displaying. Char spends more space than it needs, but stores it in a very predictable way (and would have no problem ordering from left to right). In the middle of the field you would have the BCD, but then you would require some more specific functions. It would be nice to give details of the specific problem, and the ultimate goal of what you are doing (usually the focus on the goal is better than the focus on the current attempt).

2 answers

4

There are several ways you can store a Cpf in the memory/database.

  1. String: use a char[12], or else a char[11] since you know the size. Remember to never use operations that expect a string with null terminator, like strcpy. Use memcpy or even strncpy in place.

  2. Array: store 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.

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

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

  • How would a scanf of this uint64_t look? And what library corresponds to this function?

2

Hello, the main problem of storing number with zero start starts when the number has more than 7 digits, as is the case with 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 amount 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 going to work with the numbers themselves, perform some kind of validation or take only a part of the number, in this case we can use a CPF structure, you can implement your structure however 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 the 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 CPF has the first number 0 in any of the elements it can cause problems then it is better to return the value as a string again.

The logic is complete. I will post only the full code commented and hope I can assist you in 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;
};

Browser other questions tagged

You are not signed in. Login or sign up in order to post.