Ir ao conteúdo

Ajuda em exercício de C++


DalPai

Posts recomendados

Postado

Estou precisando fazer um programa em C++ que leia um CPF e diga se ele é válido ou não. Eu forneceria o CPF de 11 dígitos, e o programa calcularia os 2 últimos dígitos usando os 9 primeiros. Caso os 2 números calculados fossem os mesmo que os 2 digitados, o programa diria que o CPF está correto. Caso contrário, ele diria que o CPF está incorreto. Se o usuário digitar um cpf com um tipo de numero (ex.: 11111111111), o programa informa cpf invalido.

Tentei fazer o exercicio com um amigo, mas nós só conseguimos fazer o programa dar certo quando o usuario digita um numero do cpf por vez, e aperta enter.

Como faço o programa dar certo, fazendo com que o usuario possa digitar o cpf de uma só vez?

aqui está o código que fizemos:

#include <cstdlib>
#include <iostream>

using namespace std;

/*O Programa roda perefitamete, desde que a entrada seja feita linha a linha
* Ou seja cada digito do cpf deve ser digitado individualmente e seguido de enter
*/

int main(void) {


cout << "Verificador de CPF\n\n";


int i, mult = 1, mult2 = 0, verificador = 0,cpf[11], dv[2] = {0, 0};

/*Entrada do CPF*/
cout << "Digite o Cpf : ";



for (i = 0; i < 11; i++) {
cin >> cpf[i];
}


/*Verifica se o cpf não tem os digitos todos iguais */
for (i = 1; i <= 11; i++) {
if (cpf[i] == cpf[i - 1]) {
verificador++;

}

if (verificador == 10) {
cout << "\n O cpf digitado é invalido ! todo os digitos são iguais \n\n";
return 0;
}
}


cout << "\n";


for (i = 0; i < 9; i++) {
dv[0] = dv[0] + cpf[i] * mult;
mult++;


}
dv[0] = dv[0] % 11;
if (dv[0] == 10) {
dv[0] = 0;
} for (i = 0; i < 10; i++) {
dv[1] = dv[1] + cpf[i] * mult2;
mult2++;


}
dv[1] = dv[1] % 11;
if (dv[1] == 10) {
dv[1] = 0;
}




if ((dv[0] == cpf[9]) && (dv[1] == cpf[10])) {
cout << "Cpf valido \n";

} else {
cout << " Cpf invalido \n\n";
}


return 0;
}

Grato

Postado

Pelo que li nos comentarios, só funciona se digitar linha a linha...

Você pode armazenar ele numa string, como caracteres mesmo.

Depois você usa a função atoi, da string.h

Ela pega uma string/char e converte em inteiro.

num=atoi(ch);

Postado

Gozzy, preencha os 11 de uma vez numa string de 12 elementos (o último é '\0').

Depois usa um for, e passa cada elemento pra um vetor de inteiros, usando a função atoi

Postado

Gozzy,

Além da solução apresentada pelo WhiteDog, você também poderia usar a classe stringstream para manipular e converter cada elemento da string para um número inteiro. Para percorrer a string, use um laço for também.

NW

Postado
Pelo que li nos comentarios, só funciona se digitar linha a linha...

Você pode armazenar ele numa string, como caracteres mesmo.

Depois você usa a função atoi, da string.h

Ela pega uma string/char e converte em inteiro.

num=atoi(ch);

Não me lembro agora se atoi() é ANSI.

Este trecho aqui

for (i = 0; i < 9; i++) {
dv[0] = dv[0] + cpf[i] * mult;
mult++;
}

dá prá fazer assim:

for (i = 1; i <= 9; i++)  
dv[0] += cpf[i] * i;

O mesmo com mult2.

*** ADD ***

atoi() é ANSI. Encontrei.

O que não deve ser é itoa().

*** /ADD ***

Postado

Listeiro, pode me falar sobre isso de ser ou não ANSI?

Nem sei bem o que quis dizer com isso, meus conhecimentos, ao contrário dos seus, vão bem superficialmente (o que os livros pra beginners ensinam).

Postado

ANSI é uma coisa tipo ABNT que faz normas e padrões.

Que nem a ISO, que faz normas para certificação de qualidade e outras 200 coisas.

Além de ANSI C, tem ISO C.

Recentemente foi lançado a especificação C11.

Era esperada desde a C99.

Não tenho certeza se depois da C99 teve algo.

Ou estou confundindo com alguma outra coisa.

Eles estipulam os protótipos que fazem parte das bibliotecas-padrão.

Por exemplo, a tal conio.h que só tinha em determinados compiladores e não é encontrada normalmente. Isto inclui a função para remover caracteres da tela.

Aí quando alguém tenta fazer isto usa system("cls") ou system("clear").

Que é o jeito quando não se tem outra alternativa.

Ou algum ***** fala prá lamber o dedo e esfregar na tela, pano com 'Veja", isopropílico etc.

Quando o compilador é proprietário ele pode não ter coisas que os outros têm ou o contrário.

Pega um destes programas da "Era DOS" e tenta compilar com algo sem <conio.h>.

Tinha uma implementação de <conio.h> perdida na internet há um tempo atrás.

Não consegui fazer funcionar.

São várias funções neste header: limpeza de tela, uso de cores, coordenadas, funções de entrada e saída de dados melhoradas etc.

Prá adaptar perde-se um bom tempo.

Resumindo: Quem daqui teve problema semelhante? Seja com <conio.h> (bem velha) ou parecido?

*** ADD ***

No caso de itoa(), seria integer to array. Transformar inteiros em vetor de caracteres.

Se for 0, o array deve ter tamanho 1 e colocar zero ali.

Tirar o logaritmo base 10 arredondado para cima e usar como tamanho do vetor.

De 1 a 9, tamanho 1 e o valor ali.

De 10 a 99, tamanho 2. Divide-se por 10. Resto em cada posição do vetor.

De 100 a 999, tamanho 3. divide-se por 100, depois por 10. Mesma coisa.

...

Tudo feito com loop.

Para se colocar o caracter no vetor, usa-se um macete:

caracter = '0' + valor_do_algarismo.

Esse '0' é um caracter. O compilador pega o valor ASCII dele, soma com o valor (número mesmo) encontrado e joga o resultado como caracter no lado esquerdo da atribuição. Se valor_do_algarismo for 0, acrescenta 0 e fica '0'. Se for 1, '0'+1 = '1', que é o sucessor de '0' na tabela ASCII. E segue...

Pode ser feito parecido para converter de maiúsculas para minúsculas, vice-versa e semelhantes com criptografia, compactação e o que se imaginar!

Muita coisa? Não, é que eu não devo ter achada a bendita função ainda...

Às vezes isso pode ser bom. :)

*** /ADD ***

*** ADD ***

A última coisa que li sobre C11 é que lançaram funções extras de strings que previnem estouro.

No caso, uma strcpy(), que tem um campo a mais. Ela é identificada como algo tipo strcpy_x().

C não tem objetos. Para ter o mesmo nome haveria polimorfismo.

Não me lembro do nome agora.

*** /ADD ***

Postado

Pesquisando pelo google cheguei nesse código (modificado um pouco por mim para se adequar no exercicio)


#include <cstdlib>
#include <iostream>

using namespace std;

int main(){

char cpf[12];
int icpf[12];
int i,somador=0,digito1,result1,result2,digito2,valor;

cout<<"Digite o CPF: ";
cin>>cpf;

//Efetua a conversao de array de char para um array de int.
for(i=0;i<11;i++){
icpf[i]=cpf[i]-48;
}

if(icpf[0]==icpf[1] && icpf[1]==icpf[2] && icpf[2]==icpf[3] && icpf[3]==icpf[4] && icpf[4]==icpf[5] && icpf[5]==icpf[6] && icpf[6]==icpf[7] && icpf[7]==icpf[8] && icpf[8]==icpf[9] && icpf[9]==icpf[10]){
cout<<"\nCPF Invalido\n";
}

else{

//PRIMEIRO DIGITO.

for(i=0;i<9;i++){
somador+=icpf[i]*(10-i);
}

result1=somador%11;

if( (result1==0) || (result1==1) ){
digito1=0;
}

else{
digito1 = 11-result1;
}

//SEGUNDO DIGITO.

somador=0;

for(i=0;i<10;i++){
somador+=icpf[i]*(11-i);
}

valor=(somador/11)*11;
result2=somador-valor;

if( (result2==0) || (result2==1) ){
digito2=0;
}

else{
digito2=11-result2;
}

//RESULTADOS DA VALIDACAO.

if((digito1==icpf[9]) && (digito2==icpf[10])){
cout<<"\nCPF Valido\n";
}
else{
cout<<"\nCPF Invalido\n";
}
return 0;
}
}

Entendi quase todo ele, menos a parte do

for(i=0;i<11;i++){
icpf[i]=cpf[i]-48;
}

O que seria esse -48

Para evitar que o programa considere 11111111111 como cpf válido eu fiz isso:

if(icpf[0]==icpf[1] && icpf[1]==icpf[2] && icpf[2]==icpf[3] && icpf[3]==icpf[4] && icpf[4]==icpf[5] && icpf[5]==icpf[6] && icpf[6]==icpf[7] && icpf[7]==icpf[8] && icpf[8]==icpf[9] && icpf[9]==icpf[10]){
cout<<"\nCPF Invalido\n";
}

Teria algo menos "porco" pra colocar no lugar?

Postado

48 é o código ascii para '0'.

É o que eu expliquei na minha postagem última.

No lugar do '0', que é mais intuitivo pode-se colocar o decimal correspondente, que é 48.

Este '0' sai no DOS se você segurar uma das teclas ALT e digitar 48 no teclado numérico da direita (se vocẽ o tiver). Quer dizer, saía. Acabaram com o DOS... Não sei. Isto não é muito popular hoje.

*** ADD ***

if(icpf[0]==icpf[1] && icpf[1]==icpf[2] && icpf[2]==icpf[3] && icpf[3]==icpf[4] && icpf[4]==icpf[5] && icpf[5]==icpf[6] && icpf[6]==icpf[7] && icpf[7]==icpf[8] && icpf[8]==icpf[9] && icpf[9]==icpf[10]){

cout<<"\nCPF Invalido\n";

}

- Crie uma flag.

- Aqui chamo de FLAG uma variável que se der algum problema muda de valor, como se fosse um código de erro.

- Pode ser "mudança de estado", "evento" etc. Nem sempre um código de erro.

- Dependendo do caso, nem seria um tipo de flag.

- Use um "while".

- Coloque como condição icpf==icpf[++i]

- Jogue o valor da igualdade na flag

- Fica FLAG=(icpf==icpf[++i]))

- Tudo dentro do "while".

- Se der falso, "while" pára e o valor fica guardado.

- Por último você compara: if (FLAG igual FALSO) { ... } ou if (FLAG igual VERDADEIRO) { ... }

É o que faria. No momento.

*** /ADD ***

Postado

Gozzy,

Ainda aproveitando aquele seu código lá do início (em C++), você pode resolver esse problema da leitura do CPF da seguinte forma:

#include <cstdlib>
#include <iostream>
[B]#include <string>
#include <sstream>[/B]

using namespace std;

int main(void)
{

cout << "Verificador de CPF\n\n";

int i, mult = 1, mult2 = 0, verificador = 0, cpf[11], dv[2] = {0, 0};

[B] string scpf;
stringstream ss;
[/B]
cout << "Digite o CPF: ";
[B]cin >> scpf;[/B]

for (i = 0; i < 11; i++) {
[B] ss << scpf[i];
ss >> cpf[i];
ss.clear();
[/B] }

for (i = 1; i <= 11; i++) {
if (cpf[i] == cpf[i - 1]) {
verificador++;
}

if (verificador == 10) {
cout << "\nO CPF digitado e invalido! Todos os digitos sao iguais.\n\n";
return 0;
}
}

cout << "\n";

for (i = 0; i < 9; i++) {
dv[0] = dv[0] + cpf[i] * mult;
mult++;
}

dv[0] = dv[0] % 11;
if (dv[0] == 10) {
dv[0] = 0;
}

for (i = 0; i < 10; i++) {
dv[1] = dv[1] + cpf[i] * mult2;
mult2++;
}

dv[1] = dv[1] % 11;
if (dv[1] == 10) {
dv[1] = 0;
}

if ((dv[0] == cpf[9]) && (dv[1] == cpf[10]))
cout << "CPF valido!\n\n";
else
cout << "CPF invalido!\n\n";

return 0;
}

As principais modificações no código aparecem em negrito. Também acertei algumas mensagens de saída e removi os comentários.

;)

LNW

Postado

for (i = 0; i < 9; i++) {
dv[0] = dv[0] + cpf[i] * mult;
mult++;
}

Você não acha redundante usar ao mesmo tempo duas variáveis que mudam por diferença de unidade para a mesma coisa? No lugar de "mult1" coloque i+1.

Postado

Olá,

Sim Listeiro, você tem razão... é que nesse código do Gozzy apenas me ative a essa questão da entrada do CPF como ele queria fazer. Basicamente, só mexi mesmo na entrada de dados.

As checagens de consistência, otimizações, limpeza, etc., ficaram de fora mesmo. Isso aí eu deixo como exercício pro Gozzy. :D

Abraço,

;)

NW

Arquivado

Este tópico foi arquivado e está fechado para novas respostas.

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