Solucionado (ver solução)
Solucionado
(ver solução)
1
resposta

Valida Cpf

Boa tarde, quis fazer o desafio de forma a deixar cadastrar cpfs no formato xxx.xxx.xxx-xx e xxxxxxxxxxx. Poderiam me dizer se está de acordo, bem feito e eficiente?

//Cpf.hpp
#pragma once
#include <string>
class CPF
{
private:
    std::string numero;
    bool verificaCpfComCaracteresEspeciais() const;
    bool verificaCpfSemCaracteresEspeciais() const;
    bool verificaCpf() const;
    bool ehNumero(char i) const;
public:
    CPF(std::string numero);
    std::string get() const;
};
//Cpf.cpp
#include "Cpf.hpp"
#include <iostream>
#include <stack>

CPF::CPF(std::string numero)
    :numero(numero) 
    {
    verificaCpf();
    }

bool CPF::verificaCpfComCaracteresEspeciais() const {
    int contNumeros = 0;
    std::stack <char> pilha;

    if (numero.size() > 14) {
        return false;
    }

    for (char i : numero) {

        if (contNumeros > 11) {
            return false;
        }

        if (ehNumero(i)) {
            if (contNumeros==0 || contNumeros % 3 != 0||!ehNumero(pilha.top())) {
                contNumeros++;
                pilha.push(i);
            }
            else {
                return false;
            }
        }
        else
        {
            if (i == '.') {
                if (contNumeros!=0 && contNumeros % 3 == 0 && contNumeros!=9 && ehNumero(pilha.top())) {
                    pilha.push(i);
                }
                else {
                    return false;
                }
            }

            if (i == '-') {
                if (contNumeros == 9 && ehNumero(pilha.top())) {
                    pilha.push(i);
                }
                else {
                    return false;
                }

            }

        }
    }
    return true;
}


bool CPF::verificaCpfSemCaracteresEspeciais() const {
    int contNumeros=0;
    if (numero.size() > 11) {	
        return false;
    }

    for (char i : numero) {
        if (!ehNumero(i)){
            return false;;
        }
    }
    return true;
}


bool CPF::verificaCpf() const {
    if (!verificaCpfSemCaracteresEspeciais() && !verificaCpfComCaracteresEspeciais()) {
        std::cout << "CPF INVALIDO" << std::endl;
        exit(1);
    }
    return true;
}

bool CPF::ehNumero(char i) const {
    return  (i >= '0') && (i <= '9');
}

std::string CPF::get() const {
    return numero;
}
1 resposta
solução!

Oi Samuel,

Seu código está bem estruturado e aborda a validação de CPF com e sem caracteres especiais, o que é ótimo 👍.

A lógica de validação com caracteres especiais é um pouco complexa, usando uma pilha para verificar a ordem dos números e caracteres. Uma alternativa seria usar expressões regulares, que podem simplificar a validação.

Abaixo, apresento uma versão modificada do seu código, utilizando expressões regulares para a validação, o que pode torná-lo mais conciso e fácil de manter:

//Cpf.hpp
#pragma once
#include <string>
#include <regex>

class CPF
{
private:
    std::string numero;
    bool validarCpf(const std::string& cpf) const;
public:
    CPF(std::string numero);
    std::string get() const;
};
//Cpf.cpp
#include "Cpf.hpp"
#include <iostream>
#include <regex>

CPF::CPF(std::string numero)
    :numero(numero)
{
    if (!validarCpf(numero)) {
        std::cout << "CPF INVALIDO" << std::endl;
        exit(1);
    }
}

bool CPF::validarCpf(const std::string& cpf) const {
    std::regex cpf_regex_formatado(R"(^\d{3}\.\d{3}\.\d{3}-\d{2}$)");
    std::regex cpf_regex_nao_formatado(R"(^\d{11}$)");

    return std::regex_match(cpf, cpf_regex_formatado) || std::regex_match(cpf, cpf_regex_nao_formatado);
}

std::string CPF::get() const {
    return numero;
}

🎓 Para saber mais: Expressões regulares em C++

Essa abordagem com expressões regulares torna o código mais limpo e fácil de entender. Continue praticando e explorando novas formas de resolver problemas 🤔.