Ir ao conteúdo

Posts recomendados

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

typedef struct
{
	int sequencial;
	char nome[50];
	char email[30];
	long int telefone;
} ContatoProfissional;

ContatoProfissional Contato;

int contSequencial = 1;

void menu();
void inserirContato();
void exibirContatosCadastrados();

int main()
{

	int opcao;

	do
	{

		system("cls");
		menu();
		scanf("%d", &opcao);
		printf("\n");

		switch (opcao)
		{
		case 1:
			inserirContato();
			break;

		case 2:
			exibirContatosCadastrados();
			break;

		default:
			printf("Opcao invalida,digite novamente.");
			break;
		}

	} while (opcao != 0);
}

void menu()
{
	printf("1 - Inserir um contato.\n");
	printf("2 - Exibir os contatos cadastrados.\n");
	printf("3 - Alteracao de dados de um contato.\n");
	printf("4 - Excluir um contato.\n");
	printf("5 - Consultar os dados de um determinado contato.\n");
	printf("0 - Sair.\n");
	printf(">> ");
}

void inserirContato()
{
	FILE *arquivoContatos = fopen("contatos.dat", "ab");

	if (arquivoContatos)
	{
		getchar();
		printf("Digite o nome do contato: ");
		fgets(Contato.nome, 50, stdin);

		printf("Digite o email: ");
		fgets(Contato.email, 30, stdin);

		printf("Digite o telefone (00 90000 0000): ");
		scanf("%ld", &Contato.telefone);

		Contato.sequencial = contSequencial;
		contSequencial++;

		fwrite(&Contato, sizeof(Contato), 1, arquivoContatos);
		fclose(arquivoContatos);
	}
	else
	{
		printf("ERRO AO ABRIR O ARQUIVO.\n");
	}
}

void exibirContatosCadastrados()
{
	ContatoProfissional LerContatos;
	FILE *arquivoContatos = fopen("contatos.dat", "rb");

	if (arquivoContatos)
	{
		while (fread(&LerContatos, sizeof(Contato), 2, arquivoContatos))
		{
			printf("Nome: %sEmail: %sTelefone: %ld\nSequencia: %d", LerContatos.nome, LerContatos.email, LerContatos.telefone, LerContatos.sequencial);
		}

		fclose(arquivoContatos);
	}
	else
	{
		printf("ERRO AO ABRIR O ARQUIVO.\n");
	}
}

 

  • Amei 1
Postado

Erro no Fread que imprimi de um arquivo apenas um contato é não o restante

 

  • Está lendo dois registros por vez
  • Teste com 4 ao menos e vai poder ver os ímpares.
  • Mas bem rapidinho. Notou que não para o programa para poder ver os contatos? Tem que ser muito dinâmico o leitor para poder ler antes que o programa apague a tela.

Tem muita coisa ainda errada em seu programa e está um pouco longe de funcionar.

 

Muitos são erros comuns, e deles eu tenho uma lista de onde copio essas coisas há tempos. Parece que todos esses programas tem a mesma origem e eu acabava escrevendo sempre as mesmas coisas, então recortar e colar é o simples.

 

Pode ser que tenham livros ruins, apostilas ruins, instrutores ruins, ou que copiem programas ruins durante gerações. Ou tudo isso.


Coisas para considerar (da minha lista 😄 

    

  •  Não use system() para nada. Não estará fazendo nada. Não estará aprendendo nada. Não há praticamente nada que possa fazer com system() que não possa fazer em C ou C++. system() foi escrita em C e o sistema quase todo também. E em geral é proibido em empresas e escolas afinal: é um risco grande de segurança. E se tem algo que você não possa inicialmente fazer em C ou C++ talvez não deva mesmo fazer.
  • evite retornar void de funções: em geral é um desperdício. E muitas vezes um erro. Use argumentos nas funções, e retorne algo delas. É mais esperto e expressivo.
  • Nunca use variáveis globais. Isso é um pesadelo e sempre vai cair na sua cabeça. Em geral é proibido em empresas e escolas. Não declare NADA que use memória  fora de main(). 
  • Nunca leia valores do teclado para alimentar seu programa antes dele estar rodando. Só vai te atrasar e não acrescenta absolutamente nada. Use constantes, use funções que retornam a estrutura preenchida. Leia de arquivos: é trivial em C. Ao terminar os  testes aí sim incorpore a leitura. Um programa interativo é chato para testar. Durante o desenvolvimento ninguém quer interagir com o programa. Nunca escreva um programa interativo, mesmo que seja o objetivo final.
  • Use nomes significativos para as variáveis e fuja de coisas como aux, aux1 e aux2. E não use nomes de variáveis enormes porque em uma expressão fica muito difícil de ler.
  • Se seu programa tem um menu, entenda que o menu() deve mostrar as opções e ler e retornar a opção. Um void menu() é um desperdício.
  • scanf() foi escrita para ler entrada formatada. Não use para ler do teclado, que claramente não é entrada formatada. Só vai dar mais trabalho. Muito mais trabalho.
  • Ao usar scanf() ou alguma função da família, como fscanf() entenda que ela retorna um valor. E teste. É ingênuo deixar o programa seguir sem testar. TESTE sempre. Exemplo: para 5 especificadores --- aquelas coisas com % na frente e que não tem um asterisco nem outro '%' --- como "%d %d %f %f %d" scanf() pode ler de 0 a 5 itens ou dar erro e retornar -1. Então teste o retorno que vai estar entre -1 e 5...
  •  Nunca escreva um programa interativo. Não vai aprender nada. Não vai ganhar nada. Escreva e teste todas as funções. DEPOIS de tudo testado coloque a parte interativa. isso inclui claro o eventual menu.
  • evite ler do teclado a menos que seja o objetivo do problema. Ler de arquivos é muito mais simples, seguro e fácil de reproduzir. Não há razão para ficar parado em frente a tela minutos inventando nomes de campos e coisas assim: o efeito é que vai acabar não testando direito porque é difícil controlar e repetir testes.
  • Não misture entrada de dados ou formatação com a apresentação dos dados ou a lógica do programa, Isso é um desastre para manutenção e desenvolvimento.
  • Um printf() de 6 linhas é muito, mas muito melhor que 6 printf() de 1 linha. E se só vai mostrar o texto puts() é ainda melhor e dezenas de vezes mais rápido que uma série de printf().
  • Ao usar uma estrutura de dados como uma lista, uma pilha ou fila, entenda que ela é um container e nada tem a ver com os dados. Não misture NUNCA os dados com a estrutura porque só via complicar tudo. Em especial vai ficar muito mais difícil aproveitar a estrutura em outros programas, e essa é toda a razão de escrever um programa.
 typedef struct
{
    int      sequencial;
    char     nome[50];
    char     email[30];
    long int telefone;
} ContatoProfissional;

 

Seu programa só tem um tipo de contato. Tanto faz se é Profissional ou Olímpico ou Verde. Use apenas Contato e quando tiver mais categorias então acrescente algo (especialização).

E long int para um telefone? E depois ainda escreve isso no prompt:
 

        printf("Digite o telefone (00 90000 0000): ");
        scanf("%ld", &Contato.telefone);

 

  • Acha mesmo que o usuário vai entender que é pra digitar um único número inteiro? Testou isso?
  • Vai operar com o número de telefone? Não vai. Use o simples: todo mundo (mesmo, já que é um padrão global) sabe como é um número de telefone: +XX (YY) ZZZZZZ use um char[]. 
  • Leia o manual: scanf retorna um int. Testou isso? Não. Claro que vai dar erro. Testou o que acontece se o cara for digitar 1 e bater a mão no q por exemplo? Seu programa entra em loop.


TESTE seu programa em partes, pra ver o que funciona e o que não funciona. Vai aprendr muito mais e muito mais rápido. Não perca horas digitando um programa "completo" que depois vai ficar horas cancelando na sua frente em segundos. Teste as partes.

 

void exibirContatosCadastrados()


Pra que esse nome gigante?  Só pode exibir contatos. E só os cadastrados. É a realidade. Exibir() não dá na mesma?

 

 

void menu()
{
    printf("1 - Inserir um contato.\n");
    printf("2 - Exibir os contatos cadastrados.\n");
    printf("3 - Alteracao de dados de um contato.\n");
    printf("4 - Excluir um contato.\n");
    printf(
        "5 - Consultar os dados de um determinado "
        "contato.\n");
    printf("0 - Sair.\n");
    printf(">> ");
}

 

  • Se isso é o menu, não seria muito mais simples e lógico ler aí dentro e retornar a opção? Faça o simples.
  • E para que nada menos que 7 chamadas a printf() para imprimir 7 linhas? Não seria mais simples, mais  legível e dezenas de vezes mais rápido usar uma única chamada?
  • Não retorne void.

EXEMPLO

 

Essa função. copiada da sua, faz a mesma coisa, com um só printf e retorna a opção.

 

int menu(void)
{
    char linha[20];
    do {
        printf("\
\n\
    1 - Inserir um contato.\n\
    2 - Exibir os contatos cadastrados.\n\
    3 - Alteracao de dados de um contato.\n\
    4 - Excluir um contato.\n\
    5 - Consultar os dados de um determinado\n\
        contato.\n\
\n\
    0 - Sair.\n\
\n\
    >> ");
        fgets(linha, sizeof(linha), stdin);
        if (linha[0] < '0') continue;  // le de novo
        if (linha[0] > '5') continue;  // le de novo
        return linha[0]; // retorna o primeiro numero
    } while (linha[0] != '0');
    return linha[0];
}

 

Sobre isso

 


ContatoProfissional Contato;

int contSequencial = 1;


int main()
{
  
  //...


Entenda que Contato e contSequencial serão globais, válidos por todo o programa. Você não quer isso: só dá erro, é o diabo pra testar e gera muitas dependências e fragilidades, além de ser proibido em muitas escolas e empresas.

Use argumentos e funções. É muito, mas muio mais simples.

 

        while (fread(
            &LerContatos, sizeof(Contato), 2,
            arquivoContatos))


Qual a razão para esse '2'? Vai ler um registro por vez.


Ao implementar as funções em seu programa a PRIMEIRA que escreve é sair. E testa. Sério que deixou essa de fora?

 

        while (fread(
            &LerContatos, sizeof(Contato), 2,
            arquivoContatos))
        {
            printf(
                "Nome: %sEmail: %sTelefone: "
                "%ld\nSequencia: %d",
                LerContatos.nome, LerContatos.email,
                LerContatos.telefone,
                LerContatos.sequencial);
        }


Vai repetir toda vez os nomes dos campos? Não seria mais simples e esperto ter uma linha de título com os nomes dos campos e depois só os dados, numerados talvez? Como todas as planilhas?

Em geral o comum nesses programas para iniciantes é ler os dados todos para a memória, em uma coleção de contatos, e apenas ler e gravar no disco no início e no fim do programa. É muito ais rápido e simples, já que em geral terá poucos contatos.

 

E para alterar um registro lá no meio vai ser complicado.

 

        getchar();
        printf("Digite o nome do contato: ");
        fgets(Contato.nome, 50, stdin);


Qual o propósito de getchar antes do printf, e sem avisar o usuário?


Mais um comentário: Sobre esse trecho

 

void inserirContato()
{
    FILE* arquivoContatos = fopen("contatos.dat", "ab");
    if (arquivoContatos)
    {
         // ...
         fwrite(
            &contato, sizeof(contato), 1, arquivoContatos);
        fclose(arquivoContatos);
    }
    else { printf("ERRO AO ABRIR O ARQUIVO.\n"); }
}

 

é muito comum isso, mas também é muito chato de digitar, de ler e de acompanhar um programa desses: entenda que se não conseguir abrir o arquivo vai mostrar aquela mensagem. Só isso. Não é muito mais simples escrever isso desse jeito mesmo? E para que esse nome gigante?

 

Compare:

 

  void inserirContato()
  {
      FILE* arq = fopen("contatos.dat", "ab");
      if (arq == NULL)
      {
          printf("ERRO AO ABRIR O ARQUIVO.\n");
          return;
      };
      // ...
      fwrite(&contato, sizeof(contato), 1, arq);
      fclose(arq);
  }

 

retornando assim que identificou o erro ao invés de deslocar todo o resto do código pra direita e colocar dentro do if...

  • Obrigado 1
Postado

@higor7   como  disse @arfneto  o erro  é por que está lendo dois blocos e sendo que no "fwrite" gravou apenas um bloco de cada vez ,  e na função  exibirContatosCadastrados coloque uma pausa ao final que pode ser a função "Sleep(3000);"  ou  outra de sua preferência , e seu código com algumas modificações ficou assim :

#include <stdio.h>
///#include <conio.h> não eh biblioteca padrão da linguagem C
#include <stdlib.h>
#include <windows.h>
#include <string.h>
#define _h GetStdHandle(STD_INPUT_HANDLE)
typedef struct
{
  int  sequencial;
  char nome    [30];
  char email   [30];
  ///long int telefone; /// esse nUmero gigante não servirAh para nada
  char telefone[15];    /// melhor que seja string
} ContatoProfissional;

ContatoProfissional Contato;

int  contSequencial = 1; /// var Global
int  menu            ();
void inserirContato  ();
void exibirContatosCadastrados();
void gettch          ();
int main             ()
{
  int opcao = -1;

  do
  {
    system("cls");
    opcao = menu();
    printf("\n");

    switch (opcao)
    {
    case 1:
      inserirContato();
      break;
    case 2:
      exibirContatosCadastrados();
      break;
    default:
      printf("OpCAo invAlida, digite novamente.");
      break;
    }
  } while (opcao != 0);
}

int menu()
{
  int opcao = -1;
  printf
  (
    " 0 - Sair.\n"
    " 1 - Inserir um contato.\n"
    " 2 - Exibir os contatos cadastrados.\n"
    " 3 - Alteracao de dados de um contato.\n"
    " 4 - Excluir um contato.\n"
    " 5 - Consultar os dados de um determinado contato.\n"
    " >> "
  );
  scanf("%d", &opcao);
  return opcao;
}

void inserirContato()
{
  FILE *arquivoContatos = fopen("contatos.dat", "ab");

  if (arquivoContatos)
  {
    getchar();
    printf("Digite o nome do contato: ");
    fgets(Contato.nome, 50, stdin);
    Contato.nome[strlen(Contato.nome)-1] = 0;/// remove o newLine pego por fgets

    printf("Digite o email: ");
    fgets(Contato.email, 30, stdin);
    Contato.email[strlen(Contato.email)-1] = 0;/// remove o newLine

    printf("Digite o telefone (00 90000 0000): ");
    ///scanf("%ld", &Contato.telefone);/// esse nUmero gigante não servirA para nada
    int ret = scanf("%s", Contato.telefone); /// melhor que seja string e essa funCAo não pega o newLine nem espaCo
    if(ret != 1)return;

    Contato.sequencial = contSequencial;
    contSequencial++;

    fwrite(&Contato, sizeof(Contato), 1, arquivoContatos);
    fclose(arquivoContatos);
  }
  else
  {
    printf("ERRO AO ABRIR O ARQUIVO.\n");
  }
}

void exibirContatosCadastrados()
{
  ContatoProfissional LerContatos;
  FILE *arquivoContatos = fopen("contatos.dat", "rb");

  if (arquivoContatos)
  {
    while (fread(&LerContatos, sizeof(Contato), 1, arquivoContatos))/// apenas um Bloco de cada vez
    {
      printf
      (
        "Nome ------: %s\n"
        "Email -----: %s\n"
        "Telefone --: %s\n"
        "Sequencia -: %d\n"
        "'----------------------------------'\n\n"
        ,LerContatos.nome   , LerContatos.email    ,
        LerContatos.telefone, LerContatos.sequencial
      );
    }
    fclose(arquivoContatos);
  }
  else
  {
    printf("ERRO AO ABRIR O ARQUIVO.\n");
  }
  gettch();
  ///Sleep(3000); pausa pelo tempo determinados
}
void	     gettch() /// pausa etherna até teclar algo
{
  fprintf(stdout,"\tTecle !");
  FlushConsoleInputBuffer(_h );
  WaitForSingleObject(_h, INFINITE);
}

 

Postado
Em 14/05/2024 às 23:38, devair1010 disse:

como  disse @arfneto  o erro  é por que está lendo dois blocos e sendo que no "fwrite" gravou apenas um bloco de cada vez

 

Bem, sim e não, @devair1010

 

Não existe relação entre uma coisa e outra. Não há nada de especial em ler um certo número de blocos por vez, ou gravar um certo número de blocos por vez. Desde que seja de propósito.

 

É preciso ver os argumentos passados para cada função...

 

Ao usar 
 

		while (fread(&LerContatos, sizeof(Contato), 2, arquivoContatos))

 

fread vai ler 2 registros do tamanho sizeof(Contato), e transferir os dados para o endereço &LerContatos, que vai ser visto como unsigned char*. E o ponteiro do arquivo vai ser avançado pelo  total de bytes lidos.

 

Só que 

 

	ContatoProfissional LerContatos;
	FILE *arquivoContatos = fopen("contatos.dat", "rb");

E

typedef struct
{
	int sequencial;
	char nome[50];
	char email[30];
	long int telefone;
} ContatoProfissional;

ContatoProfissional Contato;

 

Então se vê que não foi uma escolha feliz de nomes, e o programa está uma bagunça. 

 

Mas

  • pode ter dados suficientes no arquivo para ler dois registros
  • certamente não tem onde gravar os dois se conseguir ler
  • então deve cancelar o programa. E se não cancelar por certo esses dados lidos além do tamanho de LerContatos vão se perder para sempre, e por isso disse que vai ler apenas os ímpares, 1,3,5...

A questão do fwrite é similar.

 

Se tiver dados no endereço especificado pode gravar tantos quanto precise. Mas se não tiver dados fwrite vai seguir pela memória copiando o que tiver lá e gravando no arquivo. E se não tiver acesso à memória a partir de algum ponto desses o programa vai cancelar. Só isso. Exemplo:

 

	Contato contato[300];

 

Se tem algo assim fwrite pode gravar os 300 de uma vez. E é mais eficiente, claro. Mas não tem como saber se tem de fato dados válidos lá para os 300. Isso é a lógica do programa que vai fazer acontecer. E não dá pra saber se tem espaço na saída para gravar isso. Por isso fwrite retorna o total gravado.

 

Em 14/05/2024 às 23:38, devair1010 disse:
  ///long int telefone; /// esse nUmero gigante não servirAh para nada
  char telefone[15];    /// melhor que seja string

 

Em geral isso é pouco. Existe uma norma para isso. Veja ITU E.123, E.164, o RFC 2806. E as convenções, por exemplo nos celulares. Um número aqui no BR estaria bem descrito como +123 (12) 123456789. Pode ser ok aceitar hifens e espaços para formatar os números. E no teclado pode usar letras ao invés de números, apesar de ser pouco comum no Brasil. Talvez alguém se lembre da campanha da Porto Seguros que tentou emplacar o 333-Porto para o telefone... Ou alguém se lembre de usar o teclado do celular para entrar com texto... 8 pode ser T,U ou V também...

 

Em 14/05/2024 às 23:38, devair1010 disse:
    fgets(Contato.nome, 50, stdin);
    Contato.nome[strlen(Contato.nome)-1] = 0;/// remove o newLine pego por fgets

 

Isso está errado, @devair1010.

 

  • Entenda que fgets só deixa o '\n' lá se tiver espaço. Não pode ir lá cegamente e colocar um 0 porque se o usuário entrar com 50 ou mais dígitos fgets vai colocar exatamente os 50 lá. 
  • Entenda que fgets pode não ler nadinha e aí seu programa segue sem olhar pra trás, cosiderando que leu algo.
  • fgets retorna char* por uma boa razão. Esse erro é o mesmo de não testar o retorno de scanf. Contato.nome é um endereço e tem certamente algo lá. Algum valor tem. Não há garantia que o que está lá na linha seguinte foi lido por fgets

 

 

 

  • Curtir 1
Postado
Em 14/05/2024 às 23:38, devair1010 disse:

está lendo dois blocos e sendo que no "fwrite" gravou apenas um bloco de cada vez

É isso ai; ela acessa 2 variáveis a partir do endereço de somente uma.

 

 

Em 14/05/2024 às 18:41, higor7 disse:
	ContatoProfissional LerContatos;
	FILE *arquivoContatos = fopen("contatos.dat", "rb");

	if (arquivoContatos)
	{
		while (fread(&LerContatos, sizeof(Contato), 2, arquivoContatos))

 

 

Erro no Fread que imprimi de um arquivo apenas um contato é não o restante

Por que o programa encerra logo em seguida?

 

Olhe lá, declarou-se LerContatos, sendo 1x ContatoProfissional, depois, expressa-se nos argumentos 2x, assim a fread escreve 1x variável além da definição; escreve em bytes indefinidos ou definidos, porém não para essa operação.

 

ERRO NA DIGITACAO 🙂

  • Obrigado 1
Postado
Em 16/05/2024 às 11:19, arfneto disse:

fgets só deixa o '\n' lá se tiver espaço. Não pode ir lá cegamente e colocar um 0 porque se o usuário entrar com 50 ou mais dígitos fgets vai colocar exatamente os 50 lá. 

isso ainda não sabia ,   porém nesse caso será apenas um caractere que se perderia    ,   e creio que você quis dizer que fgets pega o '\n' digitado pelo usuário se houver espaço na variável para guarda lo  ali ,  e  se não couber ,  a string vai ficar sem o '\n' e receberá  o '\0' finalizando a string ?    

  • Obrigado 1
Postado

@devair1010 Sim, @devair1010 o 0 no final --- que é a mesma coisa que '\0' que usa 4 letas e que é a mesma coisa que 0x00 que usa quatro letras --- é garantido.

 

O newline só vai se houver espaço, então não pode cegamente trocar o último valor antes do 0 por 0 achando que seria o tal newline porque pode muito bem não ser. Se você ler 10 e o usuário digitar 300 fgets vai ler apenas 10.

 

Por outro lado, que vai chamar strlen() --- como todo iniciante e muitos profissionais --- para saber o tamanho da string, e depois testar o último não nulo pra ver se é '\n'  entenda que strlen() é um loop e é uma função externa --- que o otimizador pode até copiar para o local da chamada --- e isso tem um custo.

 

Então o simples é usar um ponteiro desde o início da string até o 0 e se achar um '\n' trocar por 0 porque se tiver um será o último.

 

Mais ainda, não se esqueça do que eu expliquei sobre o valor de retorno: não testar o retorno de fgets() é até mais ingênuo que não testar o retorno de scanf(). Todo dia programas de iniciantes e mesmo de profissionais entram em loop porque o código testa a string que foi chamada pra fgets() e não o valor de retorno. Só que se fgets() não ler nada nada vai ser transmitido para o endereço da string e fica tudo igualzinho, então o programa entra em loop.

 

RTFM: no manual, entenda que fgets() retorna char* para sinalizar o erro, e você pode usar feof() ou ferror() para ver o que houve se retornar NULL. 

 

Não sei explicar como não ensinam isso nos livros e apostilas e programas que vejo. É uma pena.

 

 

 

  • Obrigado 1
Postado

1#

Em 14/05/2024 às 23:38, devair1010 disse:
typedef struct
{
  int  sequencial;
  char nome    [30];
  char email   [30];
  ///long int telefone; /// esse nUmero gigante não servirAh para nada
  char telefone[15];    /// melhor que seja string
} ContatoProfissional;

ContatoProfissional Contato;

 

#2

Em 14/05/2024 às 23:38, devair1010 disse:
fgets(Contato.nome, 50, stdin);
Contato.nome[strlen(Contato.nome)-1] = 0;/// remove o newLine pego por fgets

 

No #1 recorte, há declaração dum dado composto e uma variável deste dado. O

dado composto tem 4 campos, um deles é o nome do tipo char [30]: um arranjo

com capacidade para 30x caracteres.

 

Em seguida, @devair1010, expressa-se, no segundo argumento da função

fgets, como se aquele campo fosse para 50x caracteres. E mais abaixo ainda no

#2 recorte, insinua-me que não conhece a capacidade do nome ao utilizar

'strlen' para determinar o tamanho de sua string.


😄 

*** Capacidade é de 30x 

Curiosamente, reforça o caso do autor da pergunta, que também expressa

variáveis além da definição.

 

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

LANÇAMENTO!

eletronica2025-popup.jpg


CLIQUE AQUI E BAIXE AGORA MESMO!