The program does not return to the menu after the function call in C

Asked

Viewed 691 times

-1

I created 2 functions, a menu function and another incluirRegistroDeObras which can be enabled by the menu. However. By enabling the incluirRegistroDeObras, i can perform the function, but at the end of it the program closes and does not return to the menu.

I have tried the solution proposed in the question How to return to the menu after performing function?, but it didn’t work.

Follow the problem statement and the code below:

José, university professor of Architecture and Urbanism, has in his office boxes and more boxes of books and magazines, which are gradually being catalogued by his secretary Vanessa. Vanessa is cataloging in an electronic spreadsheet the main data of Books and Magazines, such as (title of the work, edition, name of the author, publisher, isbn, number of copies, box where the work is stored and year).

The purpose of the map activity is to develop a small system to control where the architect’s works are stored. To build this system, you must use the C language, storing the data in a text file.

The system to be built will need to meet the functional requirements below:

  1. Have your ID (RA-Name-Course)

  2. Have an option menu.

    2.1. Include registration of works.

    2.2. List all books.

    2.3. List all magazines.

    2.4. List works by box.

#include <stdlib.h>
#include <stdio.h>

// constantes com os dados do aluno
#define nome "Alexandre Guerreiro";
#define RA "19110675-5";


//Prototipacao (definicao do prototipo das funcoes que serao utilizadas)
//O sistema a ser construído necessitará atender aos requisitos funcionais abaixo:
//
//1 - Possuir a sua identificação (RA-Nome-Curso)
//2 - Possuir um menu de opção.
//2.1 - Incluir o registro das obras.
//2.2 - Listar todos os livros.
//2.3 - Listar todas as revistas.
//2.4- Listar as obras por caixa.

void menuOpcao();
void incluirRegistroDeObras();
void listarLivros();
void listarRevistas();
void listasObrasPorCaixa();

int main() {

    menuOpcao();

}


// estrutura obra(para livro e revistas). Deve conter:
// título da obra, edição, nome do autor, editora, isbn, quantidade de exemplares, caixa onde a obra está armazenada e ano.
typedef struct obra {
    int tipo; //aqui sera definido se a obra é um livro ou revista
    char autor[500];
    char titulo[500];
    char editora[500];
    int edicao;
    int isbn;
    int qtdExemplares;
    int anoLancamento;
    struct obra *anterior;
    struct obra *seguinte;
} obra;

obra *obras;

// estrutura da caixa onde sera armazenado os livros e revistas
typedef struct caixa {
    int capacidade;
    int qtdObrasArmazenadas;
    obra *inicio;
    obra *fim;
} caixa;

caixa *caixa1;
caixa *caixa2;
caixa *caixa3;

void incluirRegistroDeObras() {
    obra *novaObra;
    char getBuffer;
    novaObra = malloc(sizeof(obra));
    printf("\nRevista ou Livro? (1 para revista e 2 para livro): ");
    scanf("%d", &novaObra->tipo);
    scanf("%c", &getBuffer);
    printf("%d",novaObra->tipo);
    printf("\nTítulo da obra: ");
    fgets(novaObra->titulo,sizeof novaObra->titulo,stdin);
    printf("%s",novaObra->titulo);
    printf("\nAutor da obra: ");
    fgets(novaObra->autor,sizeof novaObra->autor,stdin);
    printf("%s",novaObra->autor);
    printf("\nEditora da obra: ");
    fgets(novaObra->editora,sizeof novaObra->editora,stdin);
    printf("%s",novaObra->editora);
    printf("\nNúmero da edicao da obra: ");
//    fgets(novaObra->edicao,sizeof novaObra->edicao,stdin);
    scanf("%d", &novaObra->edicao);
    scanf("%c", &getBuffer);
    printf("%d",novaObra->edicao);
    printf("\nNúmero ISBN: ");
//    fgets(novaObra->isbn,sizeof novaObra->isbn,stdin);
    scanf("%d", &novaObra->isbn);
    scanf("%c", &getBuffer);
    printf("%d",novaObra->isbn);
    printf("\nQuantidade de exemplares disponíveis: ");
//    fgets(novaObra->qtdExemplares,sizeof novaObra->qtdExemplares,stdin);
    scanf("%d", &novaObra->qtdExemplares);
    scanf("%c", &getBuffer);
    printf("%d",novaObra->qtdExemplares);
    printf("\nAno de lancamento: ");
//    fgets(novaObra->anoLancamento,sizeof novaObra->anoLancamento,stdin);
    scanf("%d", &novaObra->anoLancamento);
    scanf("%c", &getBuffer);
    printf("%d",novaObra->anoLancamento);
    if (caixa1->inicio == NULL) {
        caixa1->inicio = novaObra;
    } else {
        caixa1->fim->anterior = caixa1->fim;
        caixa1->fim = novaObra;
        caixa1->qtdObrasArmazenadas++;
    }

}

void listarLivros() {
    caixa *tmp = caixa1;
    if (caixa1->qtdObrasArmazenadas > 0) {
        for (int i = 0; i < caixa1->qtdObrasArmazenadas; i++) {
            printf("%c", tmp->inicio->titulo);
            tmp->inicio = tmp->inicio->seguinte;
        }
    }
}


void menuOpcao() {
    int opcao = 0;
    do {
        printf("1 - Incluir o registro das obras.\n");
        printf("2 - Listar todos os livros.\n");
        printf("3 - Listar todas as revistas.\n");
        printf("4 - Listar as obras por caixa.\n");
        printf("5 - Sair.\n");
        printf("Opcao: ");
        scanf("%d",&opcao);
        getchar();
        system("cls || clear");
        switch(opcao) {
        case 1:
            incluirRegistroDeObras();
            break;
        case 2:
            listarLivros();
            break;
        case 3:
//        listarRevistas();
            break;
        case 4:
//        listasObrasPorCaixa();
            break;
        case 5:
            printf("\nAté a proxima!");
            break;
        default:
            printf("\nOpcão inválida!\n");
            break;
        }
    } while (opcao!=5);

}
  • Where are you declaring box 1? And what is the definition of type work?

  • @OGRO2077 edited the question by placing the problem statement and the complete code to be better understood.

  • Actually this app is not finished, there are several errors including in the malloc variable where I am not able to finish the same, besides this there are other.

1 answer

1


Your program has many problems and the solution to your question requires a little more than a one-off change. The program does not return to the main menu pq vc is not managing the data structures right, and its operations with the pointers are wrong generating a segmentation failure. Analyzing your code, it is necessary to restructure the database, define who owns the structures, create initialization and destruction routines, rewrite the menu, entry routines, among others.

When defining a data structure it is essential to think about property relations and who will manage the pointers life time in dynamic allocation. In its code there is no separation between nodes and data, the lists and the boxes are global variables, anyway, it’s a mess. This is my suggestion of how to solve this problem:

// Definição do tipo Obra

#define MAX_CARACTERES 500

typedef enum tipo_obra
{
    LIVRO   = 1,
    REVISTA = 2
} tipo_obra;

typedef struct obra
{
    tipo_obra tipo;
    char autor[MAX_CARACTERES], titulo[MAX_CARACTERES], editora[MAX_CARACTERES];
    int edicao, isbn, qtdExemplares, anoLancamento;
} obra;


// Definição do tipo Lista de Obras
typedef struct no_obra
{
    struct obra    *dados_obra;
    struct no_obra *anterior;
    struct no_obra *seguinte;
} no_obra;

no_obra* adicionar_no(no_obra** lista, obra* dados)
{
    no_obra* novo_no = malloc(sizeof(no_obra));
    novo_no->dados_obra = dados;

    if(*lista == NULL)
    {
        //inserir primeiro item da lista
        novo_no->anterior = novo_no->seguinte = NULL;
        *lista = novo_no;
    }
    else
    {
        //buscar último nó da lista
        no_obra* ultimo_no = *lista;
        while(ultimo_no->seguinte != NULL)
            ultimo_no = ultimo_no->seguinte;

        //inserir nó no fim da lista
        novo_no->anterior = ultimo_no;
        novo_no->seguinte = NULL;
        ultimo_no->seguinte = novo_no;
    }

    //retorna o nó adicionado ao fim da lista
    return novo_no;
}

I have not defined the list destruction routine because I am only reorganizing the code you posted, but it will be necessary that you implement this function for your program to be complete:

//pseudo-código
void destruir_lista(no_obra** lista)
{
    para cada nó em lista {
        deletar dados_obra
        remover nó da lista
        deletar nó
    }
}

Each box must own its own list of works, managing the pointers when necessary. I kept the variables "qtdObrasArmazenadas" and "end" because I do not know if you plan to use them in the future, but for now their existence is not necessary.

typedef struct caixa
{
    int qtdObrasArmazenadas;
    struct no_obra *inicio;
    struct no_obra *fim;
} caixa;

void inicializar_caixa(caixa* c)
{
    c->inicio = c->fim = NULL;
    c->qtdObrasArmazenadas = 0;
}
void destruir_caixa(caixa* c)
{
    //implementar
}
void adicionar_obra(caixa* c, obra* nova_obra)
{
    c->fim = adicionar_no(&c->inicio, nova_obra);
    (c->qtdObrasArmazenadas)++;
}

In the main function you can use a box array to avoid creating a variable for each box. Through the boot and destroy functions, your program ensures that the structures are ready during the menus and that at the end of the execution there is no memory leak.

#define NUM_CAIXAS 3

int main()
{
    struct caixa caixas[NUM_CAIXAS];
    for(int i=0; i<NUM_CAIXAS; ++i)
        inicializar_caixa(&caixas[i]);
        
    // menus
    
    for(int i=0; i<NUM_CAIXAS; ++i)
        destruir_caixa(&caixas[i]);
    
    return 0;
}

For the menus I have this implementation suggestion for you to have a reference of how to use the data structures in a modularized way. There are different ways of doing the menus and this suggestion is not the only right implementation.

int menuPrincipal() 
{
    printf( "\n### MENU PRINCIPAL ###\n"
            "1 - Incluir livro.\n"
            "2 - Incluir revista.\n"
            "3 - Listar todos os livros.\n"
            "4 - Listar todas as revistas.\n"
            "5 - Listar as obras por caixa.\n"
            "6 - Sair.\n"
            "Opcao: ");
    int opcao = 0;
    scanf("%d",&opcao);
    return opcao;
}
int menuSelecionaCaixa()
{
    int id = 0;
    while(1)
    {
        printf( "Qual o id do caixa? (entradas válidas de 1 a %d)\n>> ", NUM_CAIXAS);
        scanf("%d", &id);

        if(id < 1 || id > NUM_CAIXAS)
            printf("Erro! Id de caixa inválido.\n");
        else
        {
            id = id - 1;
            break;
        }
    }
    return id;
}

int main()
{
    //inicializar caixas

    int op = menuPrincipal();
    while(op != 6) 
    {
        switch(op)
        {
        case 1:
            registrarObra(&caixas[menuSelecionaCaixa()], LIVRO);
            break;
        case 2:
            registrarObra(&caixas[menuSelecionaCaixa()], REVISTA);
            break;
        case 3:
            listarLivros(&caixas[menuSelecionaCaixa()]);
            break;
        case 4:
            listarRevistas(&caixas[menuSelecionaCaixa()]);
            break;
        case 5:
            listarObras(&caixas[menuSelecionaCaixa()]);
            break;
        default:
            printf("Erro! Opcão inválida!\n");
            break;
        }

        op = menuPrincipal();
    }

    //destruir caixas
}

The implementation of specific tasks are defined in free functions that have as parameter a pointer to an instance of a box.

void registrarObra(caixa* c, tipo_obra tipo) 
{
    if (tipo == LIVRO) 
        printf("### Incluir Livro ###\n\n");
    else if(tipo == REVISTA)
        printf("### Incluir Revista ###\n\n");
    else 
    {
        printf("Erro! Tipo de obra inválido\n\n");
        return;
    }

    obra *nova_obra = malloc(sizeof(obra));
    nova_obra->tipo = tipo;

    printf("Título da obra: ");
    getchar();
    fgets(nova_obra->titulo, MAX_CARACTERES, stdin);
    nova_obra->titulo[strcspn(nova_obra->titulo, "\r\n")] = 0;

    printf("Autor da obra: ");
    fgets(nova_obra->autor, MAX_CARACTERES, stdin);
    nova_obra->autor[strcspn(nova_obra->autor, "\r\n")] = 0;

    printf("Editora da obra: ");
    fgets(nova_obra->editora, MAX_CARACTERES, stdin);
    nova_obra->editora[strcspn(nova_obra->editora, "\r\n")] = 0;

    printf("Número da edição da obra: ");
    scanf("%d", &(nova_obra->edicao));

    printf("Número ISBN: ");
    scanf("%d", &(nova_obra->isbn));

    printf("Quantidade de exemplares disponíveis: ");
    scanf("%d", &(nova_obra->qtdExemplares));

    printf("Ano de lancamento: ");
    scanf("%d", &(nova_obra->anoLancamento));


    adicionar_obra(c, nova_obra);
    printf("Obra \"%s\" adicionada com sucesso!\n\n", nova_obra->titulo);
}

void listarLivros(caixa* c) 
{
    //implementação
}
void listarRevistas(caixa* c) 
{
    //implementação
}
void listarObras(caixa* c) 
{
    //implementação
}

This modularized implementation helps prevent hacking into the code. The logObra function, for example, does not need to know which box uses a chained list or manage the box pointers. The only responsibility of registering Bra is to receive the user input, create the structure of the work, and pass on the data so that the box performs the insertion. Upcoming implementations must follow the same strategy so that the code is organized and becomes easier to add functionality to the program.

I made the code of that answer available in my bitbucket so that you can have as reference. The program is not finished, all I did was reorganize the code that you posted. I tested this code with the GCC 10.0.1 compiler on Ubuntu 20.04.

  • It shined too much OGRO2077!! Thank you very much!! reading and rereading your C class! Thanks!

  • The add-on feature was wrong. I just corrected it here. Hug! https://bitbucket.org/aviana37/stackoverflow/commits/a36f5ff3711f53ff99a84d1db631f3e7c28b2956

Browser other questions tagged

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