Ir ao conteúdo

Posts recomendados

Postado

Olá, estou fazendo um programa para faculdade e tenho que adicionar livros em uma struct e depois imprimir seus dados, eu criei um menu de opções e usei ifs como um switch, um dos ifs é usado para adicionar livros a struct e outro para imprimir os nomes dos livros, porém quando executo o if para imprimir os nomes programa não imprime nada e as vezes sai até caracteres estranhos, já usei vários métodos de limpeza como fflush(stdin), setbuf, fgets porém nada deu certo, quando eu tento imprimir dentro do primeiro if ele imprime corretamente mas no outro não, segue o codigo. obrigado pela atenção.

#include <stdio.h>
#include <locale.h>
#include <stdbool.h>
#include <string.h>

struct livro{
    char titulo[30];
    char autor[30];
    char genero[30];
    int codigo;
    double preco;
};

void mostraTitulos(struct livro x){
    printf("%s\n", x.titulo);
}

main(){
    setlocale(LC_ALL, "portuguese");
    bool loop = true;
    struct livro colecao[50];
    char menu;
    int numLivros = 0;
    int i;
    while(loop){
        printf("Digite I para incluir um livro. \n");
        printf("Digite L para listar o nome de todos os livros. \n");
        printf("Digite A para procurar um livro por autor. \n");
        printf("Digite T para procurar um livro por título. \n");
        printf("Digite M para calcular a média de preço de todos os livros. \n");
        printf("Digite S para sair \n");
        scanf("%s", &menu);
        printf("\n");
        if(menu == 's' || menu == 'S'){
            loop = false;
        }
        if(menu == 'i' || menu == 'I'){
            printf("Digite o título do livro: ");
            scanf("%s", &colecao[numLivros].titulo);
            
            printf("Digite o autor do livro: ");
            scanf("%s", &colecao[numLivros].autor);
            
            printf("Digite o gênero do livro: ");
            scanf("%s", &colecao[numLivros].genero);
            
            printf("Digite o código do livro: ");
            scanf("%i", &colecao[numLivros].codigo);
            
            printf("Digite o preço do livro: ");
            scanf("%lf", &colecao[numLivros].preco);
        
            printf("Livro adicionado.\n");
            numLivros++;
            
        }
        
        if(menu == 'l' || menu == 'L'){
            for(i = 0; i < numLivros; i++){
                mostraTitulos(colecao[i]);
            }
        }
    }
    return 0;
}

 

  • Curtir 1
Postado

Olá!

 

Seu programa não está bom ainda :(

 

O maior problema: está usando uma máscara %s para ler o que imagina ser um único char...

    char menu;

    scanf("%s", &menu);

%s é a especificação para ler uma string e pode ler mais de um char e vai acabar cancelando seu programa mesmo se entrar com 'S' na primeira vez porque vai corromper a memória ao estourar a capacidade do char menu...

 

Sobre scanf()

  • é uma rotina difícil para essas coisas de ler dados do teclado
  • Ela foi escrita para ler entrada formatada. Scan Formatted Input é a origem do nome.
  • Instrua o usuário sobre os formatos de entrada. O formato dos campos. Código é numérico, quantos dígitos? Preço é float, O título pode ter espaços, Não use acentos. Coisas assim.

    Como o cara que está digitando vai adivinhar como vai escrever? Repita os campos que já leu, para ajudar quem está digitando e ajudar você mesmo a testar isso.

     
  • scanf() retorna um valor. Use. É melhor para você. Não entendo porque ninguém ensina isso. Não vejo um único programa aqui usando isso.
  • Leia o que tiver sobrado entre cada leitura via scanf() usando uma máscara de acordo ou um loop com getchar() até achar um '\n' o tal newline.

Não teste seu programa com dados de entrada. Não é espero. Demora um eternidade. Qual a necessidade de, tendo um computador rodando seu programa, ficar parado em frente ao teclado para digitar dados?

 

Se você sabe usar funções porque escreveu só uma onde sequer precisava? Perde muito tempo...
 

Veja esse trecho por exemplo:

struct livro
{
    char   titulo[30];
    char   autor[30];
    char   genero[30];
    int    codigo;
    double preco;
};
typedef struct livro Livro;

int     inclui_livro(Livro l, Livro col[]);
int     lista_livros(Livro col[], int total);
int     busca_autor(char aut[], Livro col[], int total);
int     busca_titulo(char tit[], Livro col[], int total);
float   calcula_media(Livro col[], int total);
int     mostra_titulos(Livro col[], int total);

Se você declarar assim não precisa ler nada para testar o programa. Isso é muito importante. Muito tempo se perde. 

 

Em geral não se usa nomes de variáveis em protótipos. Coloquei algo só para te ajudar a entender. A diferença aqui é que não precisa do menu para testar o programa. Menus e scanf() são um atraso enorme. Coloque isso depois.

 

typedef é só uma maneira de não ter que ficar repetindo struct livro toda hora porque é muito chato.  E usar a primeira letra em maiúscula é só um costume meu.

 

Você sabe usar ponteiros? 

 

Exemplo

 

Só para você ver uma outra maneira: eu começaria o programa por esse aqui que já mostra isso na primeira execução:

    Titulo Livro 1234 000
     Autor Autor ABC 000
    Codigo     41
     Preco  17.34

    Titulo Livro 1234 001
     Autor Autor ABC 001
    Codigo   6500
     Preco 119.24

    Titulo Livro 1234 002
     Autor Autor ABC 002
    Codigo   1478
     Preco 108.62

    Titulo Livro 1234 003
     Autor Autor ABC 003
    Codigo   4464
     Preco   5.45

    Titulo Livro 1234 004
     Autor Autor ABC 004
    Codigo   3281
     Preco  27.61

    Titulo Livro 1234 005
     Autor Autor ABC 005
    Codigo    491
     Preco 145.42

Esse programa

#define _CRT_SECURE_NO_WARNINGS

#include <locale.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct livro {
    char titulo[30];
    char autor[30];
    char genero[30];
    int codigo;
    double preco;
};
typedef struct livro Livro;

//int     inclui_livro(Livro);
//int     lista_livros(Livro col[], int total);
//int     busca_autor(char aut[], Livro col[], int total);
//int     busca_titulo(char tit[], Livro col[], int total);
//float   calcula_media(Livro col[], int total);

Livro     fabrica();
int       mostra_titulo(Livro);

int main()
{
    for( int i = 0; i<6; i+=1)
       mostra_titulo(fabrica());
    return 0;
};  // main()

// a cada vez retorna um livro, arrumadinho para testar
Livro   fabrica()
{
    static int n = 0;
    Livro l;
    sprintf(l.titulo, "Livro 1234 %03d", n);
    sprintf(l.autor, "Autor ABC %03d", n);
    sprintf(l.genero, "Genero DEF %03d", n);
    l.codigo = rand() % 10000;
    l.preco = (double)(rand() % 150) + (rand() % 100 / 100.0);
    n = n + 1;
    return l;
};  // fabrica()

// mostra as informações referentes a um titulo
int mostra_titulo(Livro l)
{
    printf("\n");
    printf("%10s %-20s\n", "Titulo", l.titulo);
    printf("%10s %-20s\n", "Autor", l.autor);
    printf("%10s %6d\n", "Codigo", l.codigo);
    printf("%10s %6.2f\n", "Preco", l.preco);
    return 0;
}

Em 10 minutos você começa a testar. Sem ler do teclado porque só atrasa.

Sobre a leitura tem vários tópicos recentes aqui sobre como usar --- ou não usar --- scanf(). Alguns eu escrevi, outros não. Não vou repetir tudo agora. Você pode pesquisar direto no forum por essas coisas.

 

Depois você escreve as rotinas que estão em comentário lá em cima

 

Depois você coloca o menu. Postei um programa completo com menu para um tópico sobre uma playlist na semana passada. Pode servir como exemplo.

 

Com as funções e o menu você termina os testes, apaga a função fábrica() e entrega o trabalho. Ou recebe o cheque.

Escreva de novo com a evolução de seu programa

 

  • Curtir 2
  • 3 semanas depois...
Postado
  Em 13/04/2020 às 03:40, arfneto disse:

Olá!

 

Seu programa não está bom ainda :(

 

O maior problema: está usando uma máscara %s para ler o que imagina ser um único char...

    char menu;

    scanf("%s", &menu);

%s é a especificação para ler uma string e pode ler mais de um char e vai acabar cancelando seu programa mesmo se entrar com 'S' na primeira vez porque vai corromper a memória ao estourar a capacidade do char menu...

 

Sobre scanf()

  • é uma rotina difícil para essas coisas de ler dados do teclado
  • Ela foi escrita para ler entrada formatada. Scan Formatted Input é a origem do nome.
  • Instrua o usuário sobre os formatos de entrada. O formato dos campos. Código é numérico, quantos dígitos? Preço é float, O título pode ter espaços, Não use acentos. Coisas assim.

    Como o cara que está digitando vai adivinhar como vai escrever? Repita os campos que já leu, para ajudar quem está digitando e ajudar você mesmo a testar isso.

     
  • scanf() retorna um valor. Use. É melhor para você. Não entendo porque ninguém ensina isso. Não vejo um único programa aqui usando isso.
  • Leia o que tiver sobrado entre cada leitura via scanf() usando uma máscara de acordo ou um loop com getchar() até achar um '\n' o tal newline.

Não teste seu programa com dados de entrada. Não é espero. Demora um eternidade. Qual a necessidade de, tendo um computador rodando seu programa, ficar parado em frente ao teclado para digitar dados?

 

Se você sabe usar funções porque escreveu só uma onde sequer precisava? Perde muito tempo...
 

Veja esse trecho por exemplo:

struct livro
{
    char   titulo[30];
    char   autor[30];
    char   genero[30];
    int    codigo;
    double preco;
};
typedef struct livro Livro;

int     inclui_livro(Livro l, Livro col[]);
int     lista_livros(Livro col[], int total);
int     busca_autor(char aut[], Livro col[], int total);
int     busca_titulo(char tit[], Livro col[], int total);
float   calcula_media(Livro col[], int total);
int     mostra_titulos(Livro col[], int total);

Se você declarar assim não precisa ler nada para testar o programa. Isso é muito importante. Muito tempo se perde. 

 

Em geral não se usa nomes de variáveis em protótipos. Coloquei algo só para te ajudar a entender. A diferença aqui é que não precisa do menu para testar o programa. Menus e scanf() são um atraso enorme. Coloque isso depois.

 

typedef é só uma maneira de não ter que ficar repetindo struct livro toda hora porque é muito chato.  E usar a primeira letra em maiúscula é só um costume meu.

 

Você sabe usar ponteiros? 

 

Exemplo

 

Só para você ver uma outra maneira: eu começaria o programa por esse aqui que já mostra isso na primeira execução:

    Titulo Livro 1234 000
     Autor Autor ABC 000
    Codigo     41
     Preco  17.34

    Titulo Livro 1234 001
     Autor Autor ABC 001
    Codigo   6500
     Preco 119.24

    Titulo Livro 1234 002
     Autor Autor ABC 002
    Codigo   1478
     Preco 108.62

    Titulo Livro 1234 003
     Autor Autor ABC 003
    Codigo   4464
     Preco   5.45

    Titulo Livro 1234 004
     Autor Autor ABC 004
    Codigo   3281
     Preco  27.61

    Titulo Livro 1234 005
     Autor Autor ABC 005
    Codigo    491
     Preco 145.42

Esse programa

#define _CRT_SECURE_NO_WARNINGS

#include <locale.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct livro {
    char titulo[30];
    char autor[30];
    char genero[30];
    int codigo;
    double preco;
};
typedef struct livro Livro;

//int     inclui_livro(Livro);
//int     lista_livros(Livro col[], int total);
//int     busca_autor(char aut[], Livro col[], int total);
//int     busca_titulo(char tit[], Livro col[], int total);
//float   calcula_media(Livro col[], int total);

Livro     fabrica();
int       mostra_titulo(Livro);

int main()
{
    for( int i = 0; i<6; i+=1)
       mostra_titulo(fabrica());
    return 0;
};  // main()

// a cada vez retorna um livro, arrumadinho para testar
Livro   fabrica()
{
    static int n = 0;
    Livro l;
    sprintf(l.titulo, "Livro 1234 %03d", n);
    sprintf(l.autor, "Autor ABC %03d", n);
    sprintf(l.genero, "Genero DEF %03d", n);
    l.codigo = rand() % 10000;
    l.preco = (double)(rand() % 150) + (rand() % 100 / 100.0);
    n = n + 1;
    return l;
};  // fabrica()

// mostra as informações referentes a um titulo
int mostra_titulo(Livro l)
{
    printf("\n");
    printf("%10s %-20s\n", "Titulo", l.titulo);
    printf("%10s %-20s\n", "Autor", l.autor);
    printf("%10s %6d\n", "Codigo", l.codigo);
    printf("%10s %6.2f\n", "Preco", l.preco);
    return 0;
}

Em 10 minutos você começa a testar. Sem ler do teclado porque só atrasa.

Sobre a leitura tem vários tópicos recentes aqui sobre como usar --- ou não usar --- scanf(). Alguns eu escrevi, outros não. Não vou repetir tudo agora. Você pode pesquisar direto no forum por essas coisas.

 

Depois você escreve as rotinas que estão em comentário lá em cima

 

Depois você coloca o menu. Postei um programa completo com menu para um tópico sobre uma playlist na semana passada. Pode servir como exemplo.

 

Com as funções e o menu você termina os testes, apaga a função fábrica() e entrega o trabalho. Ou recebe o cheque.

Escreva de novo com a evolução de seu programa

 

Expandir  

Obrigado por comentar, aprendi bastante e irei tentar aplicar isso nos meus próximos códigos

  • Curtir 1
  • Obrigado 1

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

Mostrar 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

Mostrar mais  
×
×
  • Criar novo...

LANÇAMENTO!

eletronica2025-popup.jpg


CLIQUE AQUI E BAIXE AGORA MESMO!