#include #include #include #include #include #include typedef struct Agenda{ char nome[50]; int telefoneFixo; int telefoneCelular; char email[100]; }Agenda; Agenda agenda={0}; //Prototipos //funções modularizadas int menu(int opc); void tomarDadosContato ( Agenda* contato ); int lerDadosArquivo ( FILE* arquivo, Agenda* contato ); void imprimirContato ( Agenda* contato ); void guardarDadosArquivo ( FILE* arquivo, Agenda* contato ); void pausa(); void limparTela(); void copiar( Agenda* A, Agenda* B ); //Funcionalidades principais do programa(menu). void incluir (); void listar (); void organizar(); void excluir (); int main (){ //ajusta o console a 70 letras e 50 linhas system("MODE CON cols=70 lines=50"); //Permite letras como ç, ã, á etc setlocale(LC_ALL, "portuguese-brasilian"); bool sair = false; int opc = 0; while( !sair ){ switch ( menu(opc) ) { case 1: incluir (); break; case 2: listar (); break; case 3: organizar(); break; case 4: excluir (); break; case 0: sair = true; break; default: printf( "Não existe essa opcao\n" ); pausa(); break; }//FIN SWITCH }//FIN WHILE return 0; }//FIN MAIN //Implementação funções do menú void incluir(){//Função que inclui um contato novo al final do arquivo agenda.txt limparTela(); FILE* arquivo = fopen( "agenda.txt", "a" ); if ( arquivo == NULL ){ printf ("Nao foi posivel abrir o arquivo incluir o contato.\n"); return; } Agenda contato = {0}; tomarDadosContato ( &contato ); guardarDadosArquivo( arquivo, &contato ); printf("Contato guardado corretamente. "); pausa(); fclose(arquivo); return; } void listar (){//Função que imprime todos os contatos de agenda.txt na tela. limparTela(); //preparamos um arquivo de leitura. FILE* arquivo = fopen( "agenda.txt", "r" ); if ( arquivo == NULL ){ printf ("Nao foi posivel abrir o arquivo para listar os contatos.\n"); return; } Agenda contato; rewind(arquivo); //Lemos um a um e mostramos na tela. while ( lerDadosArquivo( arquivo, &contato ) != EOF ){ //A funçao leerDadosArquivo le um usuario por vez, e se chega no fim do arquivo retorna EOF(fim do arquivo.). //Evitamos listar contatos excluidos. if ( contato.nome[0] != '*' ){ imprimirContato( &contato ); } } pausa(); fclose(arquivo); return; } void organizar(){//Função que organiza em ordem alfabetica o arquivo, e elimina excluidos otimisando assim o arquivo. limparTela(); //Abrimos um arquivo para modo leitura. FILE* arquivo = fopen( "agenda.txt", "r" ); if ( arquivo == NULL ){ printf("Não foi possivel abrir o arquivo para contar usuarios. "); pausa(); limparTela(); return; } //Contamos quantos usuarios tem no arquivo... excluindo os que estão marcados de esta forma(excluidos): "**** **** **** *****" Agenda contato; int contador = 0; while ( lerDadosArquivo( arquivo, &contato ) != EOF ){ if ( contato.nome[0] != '*' ){ contador++; } } //Informamos quantos contatos existem no arquivo excluindo todos os marcados com '*'. printf("Encontrados %d contatos validos. ", contador); pausa(); //Reservamos memoria dinamica para carregar contatos validos(excluindo os marcados) na free storage(heap). Agenda* lista = ( Agenda * )calloc( contador, sizeof( Agenda ) ); //calloc reserva memoria e tambem formata toda ela com nulos. //voltamos ao principio do arquivo e o carregamos na memoria(lista) rewind(arquivo); int indice = 0; while ( lerDadosArquivo(arquivo, &contato) != EOF ){ if ( contato.nome[0]!= '*' ){ //Somente copiamos contatos sem excluir(todos os contatos que não sejam *** ***...) copiar( &contato, &lista[indice]); indice++; if ( indice > contador ){ indice = contador; //Isso evita que nos ultrapassamos o range maximo. } } } fclose(arquivo); //Imprime contatos sem organizar printf ("Sem organizar:\n\n"); for( int i = 0; i< contador; i++){ imprimirContato( &lista[i] ); } //Organiza lista de contatos por ordem alfabetica for ( int i = 0; i < contador; i++ ){ for ( int j = 0; j < contador; j++ ) { if ( i != j ){ if ( strcmp ( lista[i].nome, lista[j].nome ) < 0 ) { copiar(&lista[i], &contato); copiar( &lista[j], &lista[i] ); copiar( &contato, &lista[j]); } } } } //Mostra lista organizada por ordem alfabetica printf ("Organizados:\n\n"); for( int i = 0; i< contador; i++){ imprimirContato( &lista[i] ); } //Procedemos a guardar em um novo arquivo, criamos o ponteiro. FILE* novoArquivo = fopen("agenda.txt", "w"); //Essa vez o modo é destrutivo, borrará todo o conteudo que estiver no arquivo. if ( novoArquivo == NULL ){ printf("Não foi possivel abrir o arquivo para guardar os dados organizados. "); pausa(); limparTela(); return; } //Guardando a lista organizada no arquivo. indice = 0; while ( indice < contador ){ guardarDadosArquivo( novoArquivo, &lista[indice]); indice++; } //liberando recursos free(lista); //memoria dinamica deve ser liberada antes de sair fclose(novoArquivo); //fechamos o novo arquivo //Avisamos que tudo terminou corretamente printf("Arquivo organizado. "); pausa(); return; } void excluir(){//Função que procura um contato, se o encontrar troca todas as letras do campo de esse contato por asteriscos'*'. limparTela(); //Abrimos em modo leitura extendido a W FILE* arquivo = fopen("agenda.txt", "r+"); if(arquivo == NULL){ printf("Nao foi possivel abrir o arquivo para excluir o contato"); return; } Agenda contato; //Variavel auxiliar bool encontrado = false; //flag... vira true quando o nome é encontrado fpos_t antesDeUsuario = 0; //Variavel que vai conter a posição do inicio de cada linha. //perguntamos por qual contato queremos eliminar printf("Nome do contato a excluir?: "); char nome[50] = {0}; scanf("%s%*c",nome); limparTela(); //buscamos no arquivo o usuario tomado anteriormente por teclado rewind(arquivo); fgetpos( arquivo, &antesDeUsuario); while ( lerDadosArquivo( arquivo, &contato ) != EOF ){ if ( strcmp(nome, contato.nome) == 0 ){ encontrado = true; break; } fgetpos( arquivo, &antesDeUsuario); } //Si o contato existe excluimos ele transformando suas letras em asteriscos'*' deixando marcado no arquivo, pois o espaço permanece em branco, por isso devemos marcar com *, para posteriormente eliminar esses espaços com *** *** ao organizar o arquivo. if ( encontrado == true ){ char linha[200] = {0}; fsetpos( arquivo, &antesDeUsuario ); fgets(linha,200, arquivo); //Subistituindo todas as letras por * for( int i = 0; linha[i] != '\0'; i++ ){ if ( linha[i] != ' ' && linha[i] != '\r' && linha[i] != '\n' ){ linha[i] = '*'; } } fsetpos( arquivo, &antesDeUsuario ); fputs(linha, arquivo); fclose(arquivo); printf("Contato excluido. "); pausa(); limparTela(); return; }else{ //Si o usuario não estiver no arquivo avisamos e saimos sem alterar nada. limparTela(); printf("Não existe esse contato. "); pausa(); fclose(arquivo); return; } //Fin da função. } //Implementação funções básicas int menu( int opc ){ //Esse é o menu de opçoes limparTela(); printf("Escolha uma opçao \n1-Incluir \n2-Listar \n3-Ordenar \n4-Excluir \n0-Sair \n?>>"); scanf(" %d%*c",&opc ); return opc; //<-retorna a opçao para o switch desde aqui a main deixando a mesma más organizada. } void tomarDadosContato ( Agenda* contato ){ //Pede ao usuario os dados do contato a incluir ao arquivo e guarda ele no contato recebido por referencia. printf("Entre com os dados do usuario\n\n"); printf ("Nome....: "); scanf ( "%s%*c", contato->nome ); printf ("Tel fixo: "); scanf ( "%d%*c", &contato->telefoneFixo ); printf ("Tel cel.: "); scanf ( "%d%*c", &contato->telefoneCelular ); printf ("e-mail..: "); scanf ( "%s%*c", contato->email ); return; } int lerDadosArquivo ( FILE* arquivo, Agenda* contato ){ //Le um usuario por vez, e se chega no fim do arquivo retorna EOF(fim do arquivo.). É uma versao más curta do fscanf praticamente. return fscanf ( arquivo, "%s %d %d %s%*c", contato->nome, &contato->telefoneFixo, &contato->telefoneCelular, contato->email ); } void imprimirContato ( Agenda* contato ){ //imprime o contato recebido por referencia. printf("%s %d %d %s\n", contato->nome, contato->telefoneFixo, contato->telefoneCelular, contato->email); return; } void guardarDadosArquivo( FILE* arquivo, Agenda* contato ){ //Escreve os dados do contato tomados previamente normalmente por tomarDadosContato na posiçao atual em que esteja o descritor de archivo ou tambem chamado cursor. fprintf( arquivo, "%s %d %d %s\n", contato->nome, contato->telefoneFixo, contato->telefoneCelular, contato->email ); return; } void pausa(){ //pausa o programa. É melhor Opçao que usar system("pause"); já que nao precisamos incluir más headers. printf("Presione uma tecla para continuar..."); scanf("%*c"); return; } void limparTela(){ //bastante obvio que limpa nossa tela só no windows. si estamos en linux é só incluir aqui a funçao que limpa tela no linux ;) //v1 //COORD inicio = {0, 0}; //int linhas = 100; //int colunas = 60; //DWORD n; //FillConsoleOutputCharacter(GetStdHandle(STD_OUTPUT_HANDLE), ' ', linhas*colunas, inicio, &n); //v2 COORD coord; DWORD written; CONSOLE_SCREEN_BUFFER_INFO info; coord.X = 0; coord.Y = 0; GetConsoleScreenBufferInfo ( GetStdHandle ( STD_OUTPUT_HANDLE ), &info ); FillConsoleOutputCharacter ( GetStdHandle ( STD_OUTPUT_HANDLE ), ' ', info.dwSize.X * info.dwSize.Y, coord, &written ); SetConsoleCursorPosition ( GetStdHandle ( STD_OUTPUT_HANDLE ), coord ); return; } void copiar( Agenda* A, Agenda* B ){ //Copia contato A em contato B recebido por punteiros. strcpy( B->nome, A->nome ); B->telefoneFixo = A->telefoneFixo; B->telefoneCelular =A->telefoneCelular; strcpy( B->email, A->email ); }