C registration system saving in file

Asked

Viewed 8,293 times

2

Here is my code. I believe that the procedures of receiving strings, receiving information and entering into the global vector are working, but the program stops working when selecting the list option, once a structure is added into the global vector.

The program worked normally before implementing the removerQuebraLine function (which works normally in two other programs I tested), but even taking it and receiving data directly by fgets did not work anymore.

Without the function removeLine, saving in a binary file the outputs start to appear repeated, or summed with other parts of the vector.

When there are no users / consoles / games registered it lists 0 normally. Can anyone give me a light where is the error? I’ve been going through that code for a week.

Edit: Lacked space for the write functions.

edit2: I removed 1/3 of the functions, leaving only the client interactions in the code, since managing to remedy this bug, the others will be identical.

#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include <math.h>
#include <string.h>

//Declaração das Estruturas a serem utilizadas
typedef struct enderecoStruct
{
char rua[40];
char bairro[30];
char numero[6];
char cep[8];
char cidade[20];
char estado[20];
} Endereco;

typedef struct CadastroPessoaStruct
{
char nome[40];
char reg[12];
char rg[10];
char telefone[11];
Endereco end;
} Pessoa;

//Declaração das variáveis
int input = 0;
int qtdClientes;
int tamClientes;
Pessoa *clientes;
FILE *arquivo;
char clientes_dir[] = "Clientes.bin";

//Declaração dos Procedimentos e Funções a serem utilizados
void menuPrincipal();
void menuClientes();
void menuAlterarCliente();
void removerQuebraLinha();
Pessoa receberCliente();
Endereco receberEndereco();
void inserirCliente();
Pessoa *buscarCliente();
void alterarEndereco();
void alterarNomeCliente();
void alterarTelefoneCliente();
int removerCliente();
void listarClientes();

//Início do main
int main(int argc, char** argv)
{
    menuPrincipal();
    return 0;
}

void erro(char *nome_arquivo)
{
    printf("Nao foi possivel abrir o arquivo %s\n", nome_arquivo);
}

void sucesso()
{
    system("cls");
    printf ("Operacao realizada com sucesso!");
}

void menuPrincipal()
{
    do
    {
        printf("\n");
        printf ("\t\t\t\t  H&R GAMES!\n");
        printf ("\t\t\t===============================\n");
        printf ("\t\t\t|\t                      |\n");
        printf("\t\t\t|\t 1 - Cliente          |\n");
        printf("\t\t\t|\t 2 - Consoles         |\n");
        printf("\t\t\t|\t 3 - Jogos            |\n");
        printf("\t\t\t|\t 4 - Vendas           |\n");
        printf("\t\t\t|\t 0 - Sair             |\n");
        printf ("\t\t\t|\t                      |\n");
        printf ("\t\t\t===============================\n");
        printf ("\n\n");
        printf("\t\t\tPor favor, selecione uma opcao: ");
        fflush(stdin);
        scanf("%d", &input);
        system("cls");
        switch(input)
        {
        case 1:
            menuClientes();
            break;
        case 2:
            break;
        case 3:
            break;
        case 4:
            break;
        case 0:
            exit(EXIT_SUCCESS);
        default:
            printf ("\n\t\t\tOpcao invalida!\n\n");
            fflush(stdin);
        }
    }
    while(input != 0);
    system("cls");
}

void menuClientes()
{
    do
    {
        printf("\n");
        printf ("\t\t\t\t  H&R GAMES!\n");
        printf ("\t\t\t===============================\n");
        printf ("\t\t\t|\t                      |\n");
        printf("\t\t\t|    1 - Listar Clientes      |\n");
        printf("\t\t\t|    2 - Buscar Cliente       |\n");
        printf("\t\t\t|    3 - Cadastrar Cliente    |\n");
        printf("\t\t\t|    4 - Alterar Cadastro     |\n");
        printf("\t\t\t|    5 - Excluir Cadastro     |\n");
        printf("\t\t\t|    6 - Menu Principal       |\n");
        printf("\t\t\t|    0 - Sair                 |\n");
        printf ("\t\t\t|                             |\n");
        printf ("\t\t\t===============================\n");
        printf ("\n\n");
        printf("\t\t\tPor favor, selecione uma opcao: ");
        fflush(stdin);
        scanf("%d", &input);
        system("cls");
        switch(input)
        {
        case 1:
            listarClientes();
            break;
        case 2:
            buscarCliente();
            break;
        case 3:
            fflush(stdin);
            inserirCliente(receberCliente());
            break;
        case 4:
            menuAlterarCliente();
            break;
        case 5:
            removerCliente(qtdClientes, clientes_dir);
            break;
        case 6:
            menuPrincipal();
            break;
        case 0:
            exit(EXIT_SUCCESS);
        default:
            printf ("\n\t\t\tOpcao invalida!\n\n");
            fflush(stdin);
        }
    }
    while(input != 0);
    system("cls");
}

void menuAlterarCliente()
{
    do
    {
        printf("\n");
        printf ("\t\t\t\t  H&R GAMES!\n");
        printf ("\t\t\t===============================\n");
        printf ("\t\t\t|\t                      |\n");
        printf("\t\t\t|    1 - Alterar Nome         |\n");
        printf("\t\t\t|    2 - Alterar Telefone     |\n");
        printf("\t\t\t|    3 - Alterar Endereco     |\n");
        printf("\t\t\t|    4 - Menu Principal       |\n");
        printf("\t\t\t|    0 - Sair                 |\n");
        printf ("\t\t\t|                             |\n");
        printf ("\t\t\t===============================\n");
        printf ("\n\n");
        printf("\t\t\tPor favor, selecione uma opcao: ");
        fflush(stdin);
        scanf("%d", &input);
        system("cls");
        switch(input)
        {
        case 1:
            alterarNomeCliente();
            break;
        case 2:
            alterarTelefoneCliente();
            break;
        case 3:
            alterarEndereco();
            break;
        case 4:
            menuPrincipal();
            break;
        case 0:
            exit(EXIT_SUCCESS);
        default:
            printf ("\n\t\t\tOpcao invalida!\n\n");
            fflush(stdin);
        }
    }
    while(input != 0);
    system("cls");
}

void removerQuebraLinha(char *string)
{
    if(string != NULL && strlen(string) > 0)
    {
        short tamanho = strlen(string);
        if(string[tamanho-1] == '\n')
        {
            string[tamanho-1] = '\0';
        }
    }
}

void receberString(char *string_destino, int quantidade_caracteres)
{
    fgets(string_destino, quantidade_caracteres, stdin);
    removerQuebraLinha(string_destino);
}

Pessoa receberCliente()
{
    Pessoa p;

    printf("Nome: ");
    receberString(p.nome, 39);
    printf ("CPF: ");
    receberString(p.reg, 13);
    fflush(stdin);
    printf ("RG: ");
    receberString(p.rg, 11);
    fflush(stdin);
    printf ("Telefone: ");
    receberString(p.telefone, 12);
    fflush(stdin);

    p.end = receberEndereco();

    sucesso();
    return p;
}

Endereco receberEndereco()
{
    Endereco e;

    printf ("Rua: ");
    receberString(e.rua, 39);
    fflush(stdin);
    printf ("Numero: ");
    receberString(e.numero, 5);
    fflush(stdin);
    printf ("CEP: ");
    receberString(e.cep, 9);
    fflush(stdin);
    printf ("Bairro: ");
    receberString(e.bairro, 29);
    printf ("Cidade: ");
    receberString(e.cidade, 20);
    printf ("Estado: ");
    receberString(e.estado, 20);

    sucesso();
    return e;
}

void inserirCliente(Pessoa p)
{
    if(qtdClientes == tamClientes)
    {
        tamClientes *= 1.5;
        clientes = realloc(clientes, tamClientes*sizeof(Pessoa));
    }
    clientes[qtdClientes] = p;
    qtdClientes++;
}    

void listarClientes()
{
    int c;
    printf("\nListando %d clientes cadastrados\n", qtdClientes);
    for(c=0; c < qtdClientes; c++)
    {
        printf("-----------------------------------\n");
        printf("(%d)\n", c+1);
        printf("Nome  = %s\n", clientes[c].nome);
        printf("CPF = %s\n", clientes[c].reg);
        printf("RG = %s\n", clientes[c].rg);
        printf("Telefone = %s\n", clientes[c].telefone);
        printf("Endereco = %s", clientes[c].end.rua);
        printf(" - %s,", clientes[c].end.numero);
        printf(" %s,", clientes[c].end.bairro);
        printf(" %s", clientes[c].end.cidade);
        printf(" - %s.", clientes[c].end.estado);
    }
}

void alterarNomeCliente()
{
    int i;
    char cpf[11], nome[40];
    printf ("Digite o CPF do cliente a ter o nome alterado: ");
    fgets(cpf, 11, stdin);
    printf ("Digite o novo nome: ");
    fgets(nome, 39, stdin);
    for (i=0; i < qtdClientes; i++)
    {
        if(strcmp(clientes[i].reg, cpf) == 0)
        {
            strcpy(clientes[i].nome, nome);
            break;
        }
    }
}

void alterarTelefoneCliente()
{
    int i;
    char cpf[11], fone[11];
    printf ("Digite o CPF do cliente a ter o telefone alterado: ");
    fgets(cpf, 11, stdin);
    printf ("Digite o novo numero: ");
    fgets(fone, 11, stdin);
    for (i=0; i < qtdClientes; i++)
    {
        if(strcmp(clientes[i].reg, cpf) == 0)
        {
            strcpy(clientes[i].telefone, fone);
            break;
        }
    }
}

void alterarEndereco()
{
    int i;
    char cpf[12];
    printf ("Digite o CPF do cliente a ter o endereco alterado: ");
    fgets(cpf, 11, stdin);
    Endereco e;
    e = receberEndereco();
    for (i=0; i < qtdClientes; i++)
    {
        if(strcmp(clientes[i].reg, cpf) == 0)
        {
            clientes[i].end = e;
            break;
        }
    }
}

Pessoa *buscarCliente()
{
    Pessoa *p = NULL;
    int i;
    char cpf[12];
    printf ("Digite o CPF do cliente a ser buscado: ");
    fgets(cpf, 11, stdin);
    for (i=0; i < qtdClientes; i++)
    {
        if(strcmp(clientes[i].reg, cpf) == 0)
        {
            p = &clientes[i];    
            break;
        }
    }
    return p;
}

int removerCliente(int qtd, char *dir)
{
int i, CPF, sucess = 0;
printf("Digite o CPF do cliente que deseja remover: ");
scanf ("%d", &CPF);
for (i=0; i < qtd; i++)
{
    if((clientes[i].reg - CPF) == 0)
    {
        while(i < qtd-1)
        {
            clientes[i] = clientes[i+1];
            i++;
        }
        qtd--;
        sucess = 1;
        break;
    }
    else
    {
        erro(dir);
    }
}
return sucess;
}
  • 1

    xiiiiiiiii ... tries to reduce the code to a small piece that has the error. If I had to guess I would say that the error comes from the mixture of scanf() and fgets().

  • I left the code in function of the customer pointer only. Since for the other structures the concept will be the same, solving the bug in a set of functions, just do the same in the other...

1 answer

1

How about using the utility gdb to debug your program at runtime ?

This is a widely used tool for debugging Leaks memory in large and complex programs.

Assuming you’re trying to find the Leak memory in the code below, follows a step-by-step example of how to use the utility.

1) Code listing to be debugged:

/* programa.c */

#include <stdio.h>

int main( void )
{
    printf("Antes do leak!\n");

    printf("leak: %s\n", (char*) 1234 );

    printf("Apos o leak!\n");

    return 0;
}

/* fim-de-arquivo */

2) Compiling your program with the gcc in debug mode (option -g):

$ gcc -g programa.c -o programa

3) Threshing with the gdb:

$ gdb ./programa
GNU gdb (GDB) Red Hat Enterprise Linux 7.6.1-80.el7
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-redhat-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /tmp/programa...done.

4) On the console of gdb, use the command run to run the program and simulate failure:

(gdb) run
Starting program: /tmp/./programa 
Antes do leak!

Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7a61ab4 in vfprintf () from /lib64/libc.so.6
Missing separate debuginfos, use: debuginfo-install glibc-2.17-106.el7_2.6.x86_64

5) Now just use the command backtrace to identify where exactly Leak happened:

(gdb) backtrace
#0  0x00007ffff7a61ab4 in vfprintf () from /lib64/libc.so.6
#1  0x00007ffff7a6ac99 in printf () from /lib64/libc.so.6
#2  0x00000000004005a2 in main () at programa.c:7

Ready! According to the gdb, the Leak memory occurred on the line 7 of the archive programa.c within the function main().

References:

Wikipedia: https://pt.wikipedia.org/wiki/GNU_Debugger

Project Page: https://www.gnu.org/software/gdb/

I hope I’ve helped!

Browser other questions tagged

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