Ir ao conteúdo
  • Cadastre-se

C Como fazer MENU de opções aparecer em todas as telas ?


Artefactho

Posts recomendados

Olá, senhores (as)

sou sprendiz de C e no código abaixo gostaria de saber como fazer para que sempre que o usuário desejar executar as opção 1 ou 2 (exceto 0), o programa deve realizar executar o solicitado e, logo após isso, o programa deve retornar ao menu, dando ao usuário a possibilidade de executar novamente alguma das opções listadas no menu. A outra coisa seria como reportar uma msg de erro caso digite um valor diferente de 1,2 ou 0.

 

#include <stdio.h>
#include <stdlib.h>
#define TAM 05

struct livro
{
    int codigo;
    char autor[30];
    char titulo[50];
    char editora[30];
};
int main()
{
struct livro ficha[TAM];
int busca, i, j, acha, op;
op = 0;
while (op !=5)
{
printf("1 - Inserir um Novo Cadastro\n");
printf("2 - Mostrar todos os cadastros\n");
printf("0 - Encerrar\n");
printf("Digite a opção desejada: ");
scanf("%d", &op);
fflush(stdin);
if (op == 1)
{
system("cls");
for (i=0; i<TAM; i++)
{
printf("Digite o cádigo do livro da posição %d:", i+1 );
scanf("%d", &ficha.codigo);
fflush(stdin);
printf("Digite o título do livro: ");
scanf("%50[^\n]s", &ficha.titulo);
fflush(stdin);
printf("Digite o nome do autor: ");
scanf("%30[^\n]s", &ficha.autor);
fflush(stdin);
printf("Digite o nome da editora: ");
scanf("%30[^\n]s", &ficha.editora);
fflush(stdin);
}
}
else
{
if (op == 2)
{
system("cls");
for (i=0; i<TAM; i++)
{
printf("\nCÓDIGO: %d\n",
ficha.codigo );
printf("TÍTULO: %s\n",
ficha.titulo);
printf("AUTOR: %s\n",
ficha.autor);
/*printf("ÁREA: %s\n", ficha.area);*/
/*printf("ANO: %d\n", ficha.ano);*/
printf("EDITORA: %s\n\n",
ficha.editora);
}
}
else
{
if (op == 3)
{
system("cls");
printf("Digite o código que deseja buscar: ");
scanf ("%d", &busca);
i = 0;
acha = 0;
while ((i < TAM) && (acha == 0))
{
if (ficha.codigo == busca)
acha = 1;
else
i++;
}
if (acha == 1)
{
printf("\nCÓDIGO: %d\n",
ficha.codigo );
printf("TÍTULO: %s\n",
ficha.titulo);
printf("AUTOR: %s\n",
ficha.autor);
printf("EDITORA: %s\n\n",
ficha.editora);
}
else
printf("\n Registro não encontrado");
}
else
{
if (op ==4)
{
system("cls");
for (i=0;i<TAM-1;i++)
{
for (j=i+1;j<TAM;j++)
{
{
ficha = ficha[j];
}
}
}
for (i=0;i<TAM;i++)
{
printf("\n CÓDIGO: %d, TÍTULO:%s\n\n",
ficha.codigo,
ficha.titulo);
}
}
}
}
}
return (0);
}
}

 

  • Obrigado 1
Link para o comentário
Compartilhar em outros sites

@Artefactho      seu código está bom , e para voltar ao menu é desse jeito mesmo que você colocou , um loop while mesmo , mas o que acontece é que você colocou o comando return uma linha antes do ideal , que seria depois do Loop while , e esses if's poderiam ser substituídos por um switch , que os case's dele fariam as comparações de Qual opção foi pedida pelo Usuário , e nesse caso o Default seria a opção Inválida que você pretende colocar nesse código , e seu código com algumas modificações poeria ser assim  :

#include <stdio.h>
#include <windows.h>
#include <stdlib.h>
#define cls system("cls || clear");
#define TAM 01
void saindo();
struct livro
{
    int codigo;
    char autor[30];
    char titulo[50];
    char editora[30];
};
int letras[8][5] ={{15,16,14, 1,30}, /* letra  S */
                   {14,17,31,17,17}, /* letra  A */
                   {14, 4, 4, 4,14}, /* letra  I */
                   {17,25,21,19,17}, /* letra  N */
                   {30,17,17,17,30}, /* letra  D */
                   {14,17,17,17,14}, /* letra  O */
                   { 0, 0, 0, 0, 0}, /* letra    */
                   { 1, 2, 4, 0,16}, /* letra  ! */
                  };
int main()
{
    struct livro ficha[TAM];
    int busca, i, j, acha, op;
    op = 32768;
    while( op != 0 )
    {
        cls
        printf("1 - Inserir um Novo Cadastro\n");
        printf("2 - Mostrar todos os cadastros\n");
        printf("0 - Encerrar\n");
        printf("Digite a opcao desejada: ");
        scanf("%d", &op);
        fflush(stdin);
        if (op == 1)
        {
            system("cls");
            for (i=0; i<TAM; i++)
            {
                printf("Digite o codigo do livro da posicao %d:", i+1 );
                scanf("%d", &ficha[i].codigo);
                fflush(stdin);
                printf("Digite o titulo do livro: ");
                scanf("%50[^\n]s", &ficha[i].titulo);
                fflush(stdin);
                printf("Digite o nome do autor: ");
                scanf("%30[^\n]s", &ficha[i].autor);
                fflush(stdin);
                printf("Digite o nome da editora: ");
                scanf("%30[^\n]s", &ficha[i].editora);
                fflush(stdin);
            }
        }
        else
        {
            if (op == 2)
            {
                system("cls");
                for (i=0; i<TAM; i++)
                {
                    printf("\nCODIGO: %d\n",
                    ficha[i].codigo );
                    printf("TITULO: %s\n",
                    ficha[i].titulo);
                    printf("AUTOR: %s\n",
                    ficha[i].autor);
                    /*printf("ÁREA: %s\n", ficha.area);*/
                    /*printf("ANO: %d\n", ficha.ano);*/
                    printf("EDITORA: %s\n\n",
                    ficha[i].editora);
                }
            }
            else
            {
                if (op == 3)
                {
                    system("cls");
                    printf("Digite o codigo que deseja buscar: ");
                    scanf ("%d", &busca);
                    i = 0;
                    acha = 0;
                    while ((i < TAM) && (acha == 0))
                    {
                        if (ficha[i].codigo == busca)
                            acha = 1;
                        else
                            i++;
                    }
                    if (acha == 1)
                    {
                        printf("\nCODIGO: %d\n",
                        ficha[i].codigo );
                        printf("TITULO: %s\n",
                        ficha[i].titulo);
                        printf("AUTOR: %s\n",
                        ficha[i].autor);
                        printf("EDITORA: %s\n\n",
                        ficha[i].editora);
                    }
                    else
                        printf("\n Registro não encontrado");
                }
                else
                {
                    if (op ==4)
                    {
                        system("cls");
                        for (i=0;i<TAM-1;i++)
                        {
                            for (j=i+1;j<TAM;j++)
                            {
                                {
                                    ficha[i] = ficha[j];
                                }
                            }
                        }
                        for (i=0;i<TAM;i++)
                        {
                            printf("\n CODIGO: %d, TITULO:%s\n\n",
                            ficha[i].codigo,
                            ficha[i].titulo);
                        }
                    }
                    else
                    {
                        if( op != 0 )
                        {
                            printf("\n\t     Opcao Invalida !\n     Espere 3 Segundos para voltar ao Menu\n");
                            Sleep(3000);
                        }
                    }
                }
            }
        }
    }
    saindo();
    printf("\n\n\n\n\n");
    return 65535;
}
void saindo(){
    int w,px,py,x;                            /* variáveis simples                       */
    HANDLE hOut;                              /* controle dos dispositivos do pc         */
    hOut= GetStdHandle(STD_OUTPUT_HANDLE);    /* pega a saída padrão                     */
    CONSOLE_SCREEN_BUFFER_INFO SBInfo;        /* informações sobre a buffer da tela      */
    GetConsoleScreenBufferInfo(hOut, &SBInfo);/* pega a posição do cursor do console     */
    px = SBInfo.dwCursorPosition.X;           /* pX será a posição da coluna do cursor no console */
    py = SBInfo.dwCursorPosition.Y;           /* pY será a posição da linha do cursor no console  */
    int y1=py+10,x1=20,y2=y1,x2=x1,j,i,a,b;    /*y1=linha inicial  y2 para recuperar a linha inicial*/
    for(i=0;i<8;i++){                     /*  sao 8 letras                                    */
        /*textcolor_2(rand()%15,rand()%15);*/
        for(j=0;j<5;j++){                 /*o caractere é de 5 linhas                          */
            x1 = x2;
            a=letras[i][j];               /*pega o numero da 1 linha do caractere              */
            for(b=0;b<5;b++){             /*aqui eh um numero de apenas 8 bits                 */
                //gotoxy_2(x1,y1);
                SetConsoleCursorPosition( GetStdHandle(STD_OUTPUT_HANDLE),(COORD){x1,y1});
                if(a % 2 != 0){           /*se bit 0 igual 1                                   */
                    printf("%c",219);     /*coloca espaço invertido senão coloca espaço normal */
                }
                else{
                    printf(" ");          /*senão coloca espaço normal                         */
                }
                a=a/2;                    /*dividindo numero por 2 desloca os bits para direita*/
                x1--;
                Sleep(10);
            }
            y1++;                   /*muda para proxima linha                                  */
            x1=x2;                  /*volta para a coluna inicial                              */
        }                           /*proxima linha                                            */
        x2=x2+6;                    /*avança 8 colunas posicionando para o prox caract         */
        y1=y2;                      /*volta para linha inicial                                 */
    }                               /*imprimiu o primeiro caractere                            */
}

 

  • Confuso 1
Link para o comentário
Compartilhar em outros sites

2 horas atrás, devair1010 disse:

@Artefactho      seu código está bom , e para voltar ao menu é desse jeito mesmo que você colocou , um loop while mesmo , mas o que acontece é que você colocou o comando return uma linha antes do ideal , que seria depois do Loop while , e esses if's poderiam ser substituídos por um switch , que os case's dele fariam as comparações de Qual opção foi pedida pelo Usuário , e nesse caso o Default seria a opção Inválida que você pretende colocar nesse código , e seu código com algumas modificações poeria ser assim  :


#include <stdio.h>
#include <windows.h>
#include <stdlib.h>
#define cls system("cls || clear");
#define TAM 01
void saindo();
struct livro
{
    int codigo;
    char autor[30];
    char titulo[50];
    char editora[30];
};
int letras[8][5] ={{15,16,14, 1,30}, /* letra  S */
                   {14,17,31,17,17}, /* letra  A */
                   {14, 4, 4, 4,14}, /* letra  I */
                   {17,25,21,19,17}, /* letra  N */
                   {30,17,17,17,30}, /* letra  D */
                   {14,17,17,17,14}, /* letra  O */
                   { 0, 0, 0, 0, 0}, /* letra    */
                   { 1, 2, 4, 0,16}, /* letra  ! */
                  };
int main()
{
    struct livro ficha[TAM];
    int busca, i, j, acha, op;
    op = 32768;
    while( op != 0 )
    {
        cls
        printf("1 - Inserir um Novo Cadastro\n");
        printf("2 - Mostrar todos os cadastros\n");
        printf("0 - Encerrar\n");
        printf("Digite a opcao desejada: ");
        scanf("%d", &op);
        fflush(stdin);
        if (op == 1)
        {
            system("cls");
            for (i=0; i<TAM; i++)
            {
                printf("Digite o codigo do livro da posicao %d:", i+1 );
                scanf("%d", &ficha[i].codigo);
                fflush(stdin);
                printf("Digite o titulo do livro: ");
                scanf("%50[^\n]s", &ficha[i].titulo);
                fflush(stdin);
                printf("Digite o nome do autor: ");
                scanf("%30[^\n]s", &ficha[i].autor);
                fflush(stdin);
                printf("Digite o nome da editora: ");
                scanf("%30[^\n]s", &ficha[i].editora);
                fflush(stdin);
            }
        }
        else
        {
            if (op == 2)
            {
                system("cls");
                for (i=0; i<TAM; i++)
                {
                    printf("\nCODIGO: %d\n",
                    ficha[i].codigo );
                    printf("TITULO: %s\n",
                    ficha[i].titulo);
                    printf("AUTOR: %s\n",
                    ficha[i].autor);
                    /*printf("ÁREA: %s\n", ficha.area);*/
                    /*printf("ANO: %d\n", ficha.ano);*/
                    printf("EDITORA: %s\n\n",
                    ficha[i].editora);
                }
            }
            else
            {
                if (op == 3)
                {
                    system("cls");
                    printf("Digite o codigo que deseja buscar: ");
                    scanf ("%d", &busca);
                    i = 0;
                    acha = 0;
                    while ((i < TAM) && (acha == 0))
                    {
                        if (ficha[i].codigo == busca)
                            acha = 1;
                        else
                            i++;
                    }
                    if (acha == 1)
                    {
                        printf("\nCODIGO: %d\n",
                        ficha[i].codigo );
                        printf("TITULO: %s\n",
                        ficha[i].titulo);
                        printf("AUTOR: %s\n",
                        ficha[i].autor);
                        printf("EDITORA: %s\n\n",
                        ficha[i].editora);
                    }
                    else
                        printf("\n Registro não encontrado");
                }
                else
                {
                    if (op ==4)
                    {
                        system("cls");
                        for (i=0;i<TAM-1;i++)
                        {
                            for (j=i+1;j<TAM;j++)
                            {
                                {
                                    ficha[i] = ficha[j];
                                }
                            }
                        }
                        for (i=0;i<TAM;i++)
                        {
                            printf("\n CODIGO: %d, TITULO:%s\n\n",
                            ficha[i].codigo,
                            ficha[i].titulo);
                        }
                    }
                    else
                    {
                        if( op != 0 )
                        {
                            printf("\n\t     Opcao Invalida !\n     Espere 3 Segundos para voltar ao Menu\n");
                            Sleep(3000);
                        }
                    }
                }
            }
        }
    }
    saindo();
    printf("\n\n\n\n\n");
    return 65535;
}
void saindo(){
    int w,px,py,x;                            /* variáveis simples                       */
    HANDLE hOut;                              /* controle dos dispositivos do pc         */
    hOut= GetStdHandle(STD_OUTPUT_HANDLE);    /* pega a saída padrão                     */
    CONSOLE_SCREEN_BUFFER_INFO SBInfo;        /* informações sobre a buffer da tela      */
    GetConsoleScreenBufferInfo(hOut, &SBInfo);/* pega a posição do cursor do console     */
    px = SBInfo.dwCursorPosition.X;           /* pX será a posição da coluna do cursor no console */
    py = SBInfo.dwCursorPosition.Y;           /* pY será a posição da linha do cursor no console  */
    int y1=py+10,x1=20,y2=y1,x2=x1,j,i,a,b;    /*y1=linha inicial  y2 para recuperar a linha inicial*/
    for(i=0;i<8;i++){                     /*  sao 8 letras                                    */
        /*textcolor_2(rand()%15,rand()%15);*/
        for(j=0;j<5;j++){                 /*o caractere é de 5 linhas                          */
            x1 = x2;
            a=letras[i][j];               /*pega o numero da 1 linha do caractere              */
            for(b=0;b<5;b++){             /*aqui eh um numero de apenas 8 bits                 */
                //gotoxy_2(x1,y1);
                SetConsoleCursorPosition( GetStdHandle(STD_OUTPUT_HANDLE),(COORD){x1,y1});
                if(a % 2 != 0){           /*se bit 0 igual 1                                   */
                    printf("%c",219);     /*coloca espaço invertido senão coloca espaço normal */
                }
                else{
                    printf(" ");          /*senão coloca espaço normal                         */
                }
                a=a/2;                    /*dividindo numero por 2 desloca os bits para direita*/
                x1--;
                Sleep(10);
            }
            y1++;                   /*muda para proxima linha                                  */
            x1=x2;                  /*volta para a coluna inicial                              */
        }                           /*proxima linha                                            */
        x2=x2+6;                    /*avança 8 colunas posicionando para o prox caract         */
        y1=y2;                      /*volta para linha inicial                                 */
    }                               /*imprimiu o primeiro caractere                            */
}

 

Obrigado por responder,
ficou legal, pois o menu agora aparece  porém matou a opçaõ 2.
agora ele deixou de ler os dados de entrada da opção 2 . 
 

  • Obrigado 1
Link para o comentário
Compartilhar em outros sites

@Artefactho     é por causa do  cls

while( op != 0 )
    {
        cls  // esse aqui
        printf("1 - Inserir um Novo Cadastro\n");
        printf("2 - Mostrar todos os cadastros\n");
        printf("0 - Encerrar\n");
        printf("Digite a opcao desejada: ");
        fflush(stdin);
    

 delete ele e tudo estará funcionando como antes . ou coloque um comando para esperar para ver o que foi escrito no printf , e pode ser esse getch ;

#include <conio.h>
else
{
    if (op == 2)
    {
        system("cls");
        for (i=0; i<TAM; i++)
        {
            printf("\nCODIGO: %d\n",
            ficha[i].codigo );
            printf("TITULO: %s\n",
            ficha[i].titulo);
            printf("AUTOR: %s\n",
            ficha[i].autor);
            /*printf("ÁREA: %s\n", ficha.area);*/
            /*printf("ANO: %d\n", ficha.ano);*/
            printf("EDITORA: %s\n\n",
            ficha[i].editora);
            getch();
       }
  }
  else
  {

 

  • Curtir 1
Link para o comentário
Compartilhar em outros sites

Mano, sou um velho de 40 anos aprendendo a programar, entrei para a faculdade "tarde" creio que nunca é tarde pra aprender.

valeu Irmão. (tenho 40 mas digito que nem um mulecote kkkkk;
 

 
#include <stdio.h>
int main ()
{
   printf ("Obrigado devair1010\n Ajudou Muito!\n ");
   return (0);
}

 

  • Curtir 1
  • Amei 1
Link para o comentário
Compartilhar em outros sites

Uma dica de ouro é faça uma maquina virtual de linux, você vai ver que fica mais fácil testar programas em c no linux do que no windows. fora que você não corre o risco de estragar o sistema principal.

 

Um exemplo de menu diferente.

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

/* Constantes */
#define T_NOME_AUTOR 30
#define T_NOME_TITULO 255
#define T_NOME_EDITORA 30

#define Q_OPCOES_PRINCIPAIS 3
#define Q_OPCOES_CADASTROS 3

#define Q_LIVROS 30

const char *OPCOES_PRINCIPAIS[]={"Inserir um novo cadastro",
                                 "Mostrar todos os cadastros",
                                 "Encerrar"};

const char *OPCOES_CADASTROS[]={"Ver todos os livros cadastrados",
                                "Ver livro por indice",
                                "Voltar"};

enum constante_logica {NAO=0, SIM};

/* Definições */
struct informacoes_livro
{
   int codigo;
   char autor[T_NOME_AUTOR];
   char titulo[T_NOME_TITULO];
   char editora[T_NOME_EDITORA];
   float preco;
};

int
menuOpcoes(const char *opções[],
           unsigned short quantidade, 
           enum constante_logica aceitar_qualquer_valor);

void
cadastraLivro(struct informacoes_livro *l);


int main(void) {
   struct informacoes_livro livros[Q_LIVROS];
   unsigned short cont, indice_livros = 0;
   enum constante_logica continua = SIM;
   do {
      /* Menu principal */
      switch (menuOpcoes(OPCOES_PRINCIPAIS, Q_OPCOES_PRINCIPAIS, NAO)) {
         case 0:
            cadastraLivro(&livros[indice_livros]);
            ++indice_livros;
            break;

         case 1:
            /* Menu para ver os livros */
            switch (menuOpcoes(OPCOES_CADASTROS, Q_OPCOES_CADASTROS, NAO)) {
               case 0:
                  if (indice_livros) {
                     for (cont = 0; cont < indice_livros; cont++)
                     {
                        printf("\n------------ Livro:%i ------------", cont);
                        printf("\nCodigo:\t%i",livros[cont].codigo);
                        printf("\nAutor:\t%s",livros[cont].autor);
                        printf("\nNome:\t%s",livros[cont].titulo);
                        printf("\nEditora:\t%s",livros[cont].editora);
                        putchar('\n');
                     }
                  } else {
                     printf("\nNao ha livros cadastrados.");
                     printf("\n\nPressione enter para continua.");
                     getchar();
                  }
               break;

               case 1:
                  printf("\nDigite a posicao do livro:\t");
                  scanf("%hu%*c",&cont);
                  if (cont < indice_livros) {
                     printf("\n------------ Livro:%i ------------", cont);
                     printf("\nCodigo:\t%i",livros[cont].codigo);
                     printf("\nAutor:\t%s",livros[cont].autor);
                     printf("\nNome:\t%s",livros[cont].titulo);
                     printf("\nEditora:\t%s",livros[cont].editora);
                     putchar('\n');
                  } else {
                     printf("\nIndice invalido!\n");
                  }
                  printf("\n\nPressione enter para continua.");
                  getchar();
            }
            break;

         case 2:
            continua = NAO;
            break;
      }
   } while (continua);
   return(0);
}

int
menuOpcoes(const char *opções[],
           unsigned short quantidade, 
           enum constante_logica aceitar_qualquer_valor)
{
   int cont;
   int aux;

   do {
      /* Mostra as opções */
      for (cont = 0; cont < quantidade; cont++)
         printf("%i - %s\n", cont, opções[cont]);

      /* Pega a opção */
      printf("\n:");
      scanf("%i%*c",&aux);
      if (aceitar_qualquer_valor) {
         return(aux);
      } else {
         if (aux < 0 || aux >= quantidade) {
            printf("\nOpcao invalida\nTente novamente!\n\n");
            getchar();
         } else {
            return(aux);
         }
      }
   } while (!aceitar_qualquer_valor && (aux < 0 || aux >= quantidade));

   return(0);
}

void
cadastraLivro(struct informacoes_livro *l) {
   char opcao;

   /* Pega o codigo do livro */
   do {
      printf("\nDigite o codigo do livro:");
      scanf("%i%*c",&l->codigo);
      printf("\nAs informações a seguir estão corretas?\n%i\nS\\N?\n:",l->codigo);
      scanf("%c%*c", &opcao);
         if (toupper(opcao) == 'N')
            printf("Coloque as informações novamente!");
   } while (toupper(opcao) == 'N');


   /* Pega o nome do livro */
   do {
      printf("\nDigite o nome do livro:");
      fgets(l->titulo, T_NOME_TITULO, stdin);
      printf("\nAs informações a seguir estão corretas?\n%s\nS\\N?\n:",l->titulo);
      scanf("%c%*c", &opcao);
         if (toupper(opcao) == 'N')
            printf("Coloque as informações novamente!");
   } while (toupper(opcao) == 'N');

   /* Pega o nome do autor do livro */
   do {
      printf("\nDigite o nome do autor do livro:");
      fgets(l->autor, T_NOME_AUTOR, stdin);
      printf("\nAs informações a seguir estão corretas?\n%s\nS\\N?\n:",l->autor);
      scanf("%c%*c", &opcao);
         if (toupper(opcao) == 'N')
            printf("Coloque as informações novamente!");
   } while (toupper(opcao) == 'N');

   /* Pega o nome da editora do livro */
   do {
      printf("\nDigite o nome da editora do livro:");
      fgets(l->editora, T_NOME_EDITORA, stdin);
      printf("\nAs informações a seguir estão corretas?\n%s\nS\\N?\n:",l->editora);
      scanf("%c%*c", &opcao);
         if (toupper(opcao) == 'N')
            printf("Coloque as informações novamente!");
   } while (toupper(opcao) == 'N');

}

É só um exemplo, então ainda falta muita coisa.

 

Outra coisa muito importante é não utilize

system();	/* Quebra a seguraça do sistema */
fflush();	/* Quebra a seguraça do sistema */
getch();	/* Só é valído no BorlandC/DOS */

as funções acima são equivalentes a praticar bruxaria em C, uma hora vai dar errado e pra consertar e pior.

Então se tiver um problema com o console é melhor tentar descobrir como resolver ao invés de contornar.

  • Curtir 2
Link para o comentário
Compartilhar em outros sites

21 horas atrás, Artefactho disse:

Mano, sou um velho de 40 anos aprendendo a programar, entrei para a faculdade "tarde" creio que nunca é tarde pra aprender

 

Nem tão velho para aprender :) Tem razão.


Escreva seu programa sempre em torno dos dados.

Isso vai te levar a entender melhor o programa, antes mesmo de começar a escrever código.

 

Entenda que os exercícios típicos para iniciantes e os problemas típicos para profissionais não são assim muito variados. São abstrações de problemas práticos e não tem muito o que mudar. Um relatório pode ser sintético ou analítico, envolver dinheiro ou genes e será um relatório. Um balanço é um balanço. Dados são assim, informação e estrutura.
 

De volta ao seu programa:
 

Você tem essa estrutura

typedef struct
{
    int     codigo;
    char    autor[20];
    char    titulo[20];
    char    editora[20];

}   Livro;

Eu diminui os tamanhos em relação ao seu programa original por uma razão que vai ficar clara a seguir: vou te mostrar uma alteração no seu código como exemplo do que eu estou te falando.  Mas pode esquecer em seguida se não achar importante, claro.

Como está começando agora com essas coisas deve ser uma boa hora para ver isso, antes de contrair as manias típicas dos autores e professores. Entenda que seus dados não são exatamente o Livro.

 

Usei uma convenção como vê acima, um typedef que é uma definição de tipo em que você dá um nome para a estrutura e depois pode declarar coisas como

Livro  um;
Livro  loja[10];
Livro* ponteiro_para_livro;

E assim fica mais fácil de ler. E não precisa repetir o tal struct a toda hora. 


Mas entenda que você trabalha com uma coleção de livros. E tem que saber quantos tem. E tem um máximo de livros. Então algo assim 

typedef struct
{
    int     N;
    Livro   obra[_TAM_];

}   Acervo;

Seria bem representativo de seu problema: um acervo é o seu material de trabalho nesse enunciado. Na prática se usaria algo assim

typedef struct
{
    int     capacidade;
    int     total;
    Livro** obras;

}   Acervo;

E teria tudo aí dentro: o MAX de Livro, o total atualizado e um ponteiro para um vetor de obras. No futuro vai usar assim porque aí fica mais flexível: pode ter um número qualquer de obras alocadas dinamicamente. Para esse programa não é importante.
 

Escreva funções

A essa altura já deve ter aprendido que você pode pegar blocos de código e dar um nome e passar uns argumentos e isso é uma função. Uma função em C sempre retorna algo e você deve usar isso. Em geral é um desperdício e muitas vezes um erro não retornar nada. Existe um tipo, void, que é para sinalizar esse "nada". Evite usar.

 

Escreva vários programas

Ninguém vai te culpar por escrever seu programa aos poucos. Em especial se ele ficar pronto em 30 minutos. Mas se você escrever um grande programa de 3.000 linhas e que funciona bem ainda assim vão te culpar se levou a semana toda pra fazer. Ou o mês todo.

 

Use dados de teste e não leia nada do teclado

Não use menus ou leia do teclado antes de ter a lógica pronta e testada. Só vai perder seu tempo.

 

Exemplo

Você está tratando os tais livros. Acho que já entendeu que é mais simples tratar a coleção de livros. Isso se chama container em C++ ou coleção em java, mas a ídéia é a mesma: juntar as coisas embaixo de um nome só, com propriedades e código se possível.

 

Em C é muito fácil declarar e inicializar estruturas:
 

Esse exemplo

typedef struct
{
    int     codigo;
    char    autor[20];
    char    titulo[20];
    char    editora[20];

}   Livro;

typedef struct
{
    int     N;
    Livro   obra[_TAM_];

}   Acervo;

Declarando e preenchendo uma estrutura com 5 livros

 

    Acervo      loja =
    {
        .N = 5, // teste com 5 livros

        .obra[0] =
        { 1, "Autor 1", "Titulo34343 4", "Editora 34"},

        .obra[1] =
        {
            .codigo = 324,
            .autor = "autor 324",
            .titulo = "titulo 434434",
            .editora = "editora para 324"
        },

        .obra[2] = { 1002, "Autor 1002", "Titulo34343 4", "Editora 34"},
        .obra[3] = { 1003, "Autor 1003", "Titulo34343 4", "Editora 34"},
        .obra[4] = { 1004, "Autor 1004", "Titulo34343 4", "Editora 34"}
    };

Acho que aqui já entendeu como é mais produtivo. Você pode colocar os valores na sequência em que foi declarado, ou colocar valores nos campos pelo nome, mesmo que seja um vetor, como é o caso dos N livros aqui. E não precisa nem preencher todos.

A função mostra()

A primeira função que você escreve para TODOS esses programas de cadastros e listas e estruturas de dados é a que mostra os dados na tela um a um. Algo assim

 

int     mostra_obras(Acervo* ficha)
{
    system("cls");
    printf("\n\nAcervo com %d de %d obras\n\n", ficha->N, _TAM_);

    printf("%10s    %20s    %20s    %20s\n\n",
        "Codigo", "Autor", "Titulo", "Editora");
    for (int i = 0; i < ficha->N; i++)
        printf("%10d    %20s    %20s    %20s\n\n",
            ficha->obra[i].codigo,
            ficha->obra[i].autor,
            ficha->obra[i].titulo,
            ficha->obra[i].editora);
    printf("\nTecle ENTER para retornar "); fgetc(stdin);
    return 0;
};  // mostra_obras()

A função recebe um ponteiro para um Acervo, onde tem N Livro, e mostra um a um na tela. Então já pode escrever um programa que junta a declaração e essa função. 
 

Como mostrar os dados sem perder tempo


Usando o próprio editor do IDE você digita um gabarito:

    codigo                   autor                   titulo                  editora  
0123456789    01234567890123456789     01234567890123456789     01234567890123456789  
0123456789    01234567890123456789     01234567890123456789     01234567890123456789  
0123456789    01234567890123456789     01234567890123456789     01234567890123456789  
0123456789    01234567890123456789     01234567890123456789     01234567890123456789  


E aí copia direto para o código". Veja esses comandos

    printf("%10s    %20s    %20s    %20s\n\n",
        "Codigo", "Autor", "Titulo", "Editora");
    for (int i = 0; i < ficha->N; i++)
        printf("%10d    %20s    %20s    %20s\n\n",

E já sabe que vai sair tudo alinhado.
 

Eis o "programa"

int     main()
{
    Acervo      loja =    {
        .N = 5, // teste com 5 livros
        .obra[0] =
        { 1, "Autor 1", "Titulo34343 4", "Editora 34"},
        .obra[1] =
        {
            .codigo = 324,
            .autor = "autor 324",
            .titulo = "titulo 434434",
            .editora = "editora para 324"
        },
        .obra[2] = { 1002, "Autor 1002", "Titulo34343 4", "Editora 34"},
        .obra[3] = { 1003, "Autor 1003", "Titulo34343 4", "Editora 34"},
        .obra[4] = { 1004, "Autor 1004", "Titulo34343 4", "Editora 34"}
    };
    mostra_obras(&loja);
    return (0);
};  // main()

Só tem uma linha. Veja o que sai na tela:

gab.png.58f76a94984d7aacadeed85a7910efb7.png
 

De volta ao seu programa


Seu programa não está muito bom. Em especial já deve ter revisto e entendido que:

  • faltam os índices quando você tenta acessar ficha em seu programa
  • o programa está muito longo e difícil de ler pela falta de funções
  • a leitura tem problemas pelo uso de scanf() para ler do teclado. Em alguns casos ficam letras a serem consumidas do teclado e interferem na leitura dos próximos campos
  • fflush() de stdin não está definido e não devia ser usado. fflush() só se aplica a arquivos de saída.
  • scanf() retorna um valor, um int. E você não está tratando. Só que esse int diz quantos valores foram lidos e você às vezes queria ler um e não lê nenhum. Como não testa seu programa segue adiante... E aí já era.

Confirme se entendeu e eu posto o resto do seu programa, reorganizado.

@devair1010

Escrever as letras em 5x5 com um vetor assim talvez seja muito trabalhoso para o resultado.

saindo.png.bd393d7fc34d10f2b032dd094368c586.png


Voltando aos anos 80 e às impressoras matriciais e com um olho no Windows veja essa tela

tela.png.14ad2ef53f764a1bbc0ab2de7a37394f.png


Está usando caracteres monospace, claro, todos com a mesma largura. A fonte Courier New é dessa época das impressoras matriciais. Veja na tela do Windows que as letras tem 10x18 pixels. Muitas das impressoras tinham 9 agulhas e imprimiam as letras em 7x9 pontos. Talvez tivesse melhor resultado imitando isso. que é do tempo em que conio.h era novidade. E pode usar um alfabeto menor e desenhar menos símbolos, como apenas os dígitos e as maiúsculas e alguma pontuação. E gravar o alfabeto todo em um vetor já inicializado com o próprio código da letra, mais uma vez imitando o que se fazia nos '80: as impressoras é que tinham as letras. Você só mandava o código. Teve uma discussão aqui sobre como embutir código assim em variáveis semanas atrás. E fica muito rápido.No fundo é um vetor em que cada posição é um vetor de "agulhas" que mostra os pontos que vão estar "acesos" para desenhar a letra. E o código da letra é o índice no vetor. Era como a gente fazia nas impressoras. No firmware.

  • Obrigado 1
Link para o comentário
Compartilhar em outros sites

@arfneto      obrigado ,  e teria algum comando para aumentar o tamanho dos  caracteres no console ? , que modificasse apenas alguns caracteres ? , já tentei acessar a memória para descobrir onde são guardados os bytes que formam os caracteres , mas descobri que na linguagem  c , nem mesmo com ponteiro , não se pode acessar a memória diretamente ,  então o vetor é o que mais me parece melhor para isso .

Link para o comentário
Compartilhar em outros sites

6 minutos atrás, devair1010 disse:

e teria algum comando para aumentar o tamanho dos  caracteres no console ? , que modificasse apenas alguns caracteres ?

 

A console do windows também pode ser acessada em pixel, e você pode "desenhar" qualquer fonte nela.

Usando a janela no modo texto não. Pode mudar a fonte dinamicamente, acho que já postei isso, mas afeta todos os caracteres.

 

8 minutos atrás, devair1010 disse:

já tentei acessar a memória para descobrir onde são guardados os bytes que formam os caracteres

 

Eles não ficam em bytes. O que está gravado lá --- CONSOLE_SCREEN_BUFFER_INFOEX e não o que está em CONSOLE_FONT_INFOEX ---  são os caracteres e seus atributos, em vetores separados. Por padrão tem 9001 linhas de buffer. Mas não são os bytes que formam os caracteres. São a representação deles, o código. O que vai ser mostrado é a fonte e fica em outro lugar. Pode acessar a partir de 

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Fonts

no registro eu acho.

 

23 minutos atrás, devair1010 disse:

mas descobri que na linguagem  c , nem mesmo com ponteiro , não se pode acessar a memória diretamente

 

Você pode acessar a memória diretamente. apenas o acesso é controlado, de modo a garantir a segurança dos processos e a estabilidade do sistema. Em geral você não tem acesso a espaço de endereçamento de outros processos.
 

28 minutos atrás, devair1010 disse:

então o vetor é o que mais me parece melhor para isso

 

Não. Trata-se da mesma coisa. Um vetor em seu processo é só isso: uma área de memória a partir de um endereço.

  • Obrigado 1
Link para o comentário
Compartilhar em outros sites

Em 27/08/2020 às 05:55, Artefactho disse:

A outra coisa seria como reportar uma msg de erro caso digite um valor diferente de 1,2 ou 0.

 

Em geral um menu oferece umas opções ao usuário, lê um valor de resposta e devolve para a aplicação tratar.

Muitos sistemas tem isso integrado. O Windows pode ter um menu associado a qualquer janela. E o menu pode ter teclas associadas a certas funções, atalhos. O DOS tinha um menu de erro integrado clássico: mostrava uma mensagem e as opções: Abort, Retry, Ignore?

 

Então você pode usar uma função, na mesma linha do post anterior. Pode ser algo simples ou complexo. Muitas vezes, por flexibilidade, o menu é lido do disco. Ou de um arquivo especial, como XML ou .ini como nos anos 90.

 

A ideia é evitar que seja preciso compilar o programa só porque mudou o menu, por exemplo. O menu clássico para os programas de estudo em C é algo como vou mostrar abaixo, mas também pode ser uma tabela de funções que associa direto a opção do menu com a resposta, eliminando o processo de seleção que geralmente é uma série de if ou um switch
 

Eis uma função dessas, com o código do seu programa:

int     menu()
{
    int ch = 0; // para ler a linha toda
    int op = -1;
    int invalida = 1; // so 0 eh falso

    system("cls");
    while( invalida )
    {
        printf("\n\nMenu:\n\n");
        printf("1 - Inserir um Novo Cadastro\n");
        printf("2 - Mostrar todos os cadastros\n");
        printf("0 - Encerrar\n");

        printf("\nDigite a opção desejada: ");
        scanf(" %d", &op);
        while (((ch = fgetc(stdin)) != '\n') && (!feof(stdin)));

        invalida = (op < 0) || (op > 2); // 0 1 2 validos
        //if(invalida){}; // opcao invalida

    } while (invalida);
    return op;
}

A lógica resolve o que você queria:

  • a função retorna um int que é a opção digitada
  • o loop é até conseguir uma opção válida. Mostra "todo" o menu de novo porque não achei relevante tratar só a leitura. É só um exemplo afinal.
  • Depois da leitura, se a opção não for válida, tem um if() onde você pode inserir o código para tratar o caso de opção inválida, e está comentado.
  • o loop 
            while (((ch = fgetc(stdin)) != '\n') && (!feof(stdin)));
    serve para ler todos os caracteres até o fim da linha, para evitar que interfiram na sequência do programa. É uma maneira portável e mais segura que fflush(stdin) que como eu expliquei não é definida para arquivos de entrada.E sua finalidade é outra.
     

De volta ao programa, copiei seu código para essas funções

	int     inserir_livro(Livro*, Acervo*);
	Livro   le_um_livro();
	int     menu();
	int     mostra_obras(Acervo*);

E isso torna a vida bem mais simples.

  • 	mostra_obras(Acervo*);

    Nesse caso se pode passar apenas o endereço da variável que tem o acervo, de modo que fica fácil por exemplo usar várias coleções de livros no mesmo programa, e dentro do acervo já tem o total de livros. E se precisar mudar o formato dos livros ou do layout na tela não precisa mudar nada nos argumentos. Isso é ago como o conceito de encapsulamento, presente em outras linguagens como java e C++

  • 	int     inserir_livro(Livro*, Acervo*);

    Nesse caso tem o sentido usual, inserir um livro no acervo. A vantagem é passar o endereço de um Livro de de um Acervo, assim funciona sem ter que mudar nada se mudar o layout da estrutura de livro ou do acervo, para coisas como mudar o acervo para usar alocação dinâmica ou incluir novos campos no livro, como o código ISBN por exemplo

Veja uma implementação como pode ser simples:

int     inserir_livro(Livro* livro, Acervo* ficha)
{
    // ficha.N tem a primeira posicao livre
    printf("Acervo com %d de %d obras\n\n", ficha->N + 1, _TAM_);
    if (ficha->N == _TAM_) return -1; // acervo lotado
    ficha->obra[ficha->N] = *livro;
    ficha->N += 1; 
    return 0;
};  // inserir_livro();

Assim é muito mais seguro e flexível do que ler todos os livros dentro do loop em main() com os campos e os printf() todos misturados à lógica do programa. E assim se isola a lógica e dados, um modelo comum de  programação e que leva a menos erros e mais flexibilidade na manutenção.

 

E como a estrutura já tem dentro dela o total de livros em uso e o vetor de Livro, e a capacidade é nesse exemplo uma constante global, falta só o livro mesmo. E ele vem como parâmetro então é o que basta.

  • 	Livro   le_um_livro() 

    Para que isso?

A razão é separar inserir_livro() de ler um livro a partir do teclado, porque assim fica mais fácil de testar o programa e terminar tudo.
 

Citação

Não é sério achar que alguém vai digitar 4 campos por livro para vários livros toda vez que for testar o programa. Vai ser muito tempo perdido a toa.

 

Na prática não se usaria assim: le_um_livro() iria alocar memória e cria uma estrutura Livro e retornar o endereço. E na hora de inserir no acervo essa memória seria liberada. Mas não quero complicar isso agora. Apenas quero mostrar a maneira de escrever o código de modo iterativo e seguro

 

Exemplo: criando uns Livro:

    Livro exemplo = {
        0, "Autor exemplo",
        "Titulo exemplo", "Editora exemplo"
    };
    for (int i = 0; i < _TAM_ - 2; i += 1)
    {   // insere uns livros
        exemplo.codigo = 1000 + i;
        inserir_livro(&exemplo, &loja);
    };  // for()

Esse trecho de programa criar livros no acervo, deixando apenas 2 livres para testar o programa. Colocando isso no início do programa já dá pra testar com o cadastro quase cheio. Sem digitar nada.

 

Um loop de teste

 

Com o seu código, ligeiramente alterado

    while ( (op = menu()) != _op_sair_)
    {
        switch (op)
        {
        case _op_insere_:
            um_livro = le_um_livro();
            inserir_livro(&um_livro, &loja);
            break;
        case _op_mostra_:
            mostra_obras(&loja);
            break;
        default:
            break;
        };
    }   // while()
    return (0);

O que mudou?

o loop chama o menu e pega a opção digitada, em op. O switch() trata a opção. Ao receber a opção sair o programa termina. Nada mais.
 

Só que lendo o código assim já dá pra entender o que faz. E se precisar mudar algo muda só nas funções, que podem estar em outros arquivos ou a cargo de outros caras. E não precisa mudar nada em main(). O mesmo vale para se precisar mudar o menu. 
 

Se acrescentar opções apenas se inclui aí a opção nova. Totalmente redundante mas usei uns #define

#define _op_insere_   1
#define _op_mostra_   2
#define _op_sair_     0

 

para as opções porque assim não é preciso criar uma tabela mental que  p0$$@ de comando é 1 ou 2 ou opção 8 ou sei lá :) 

 

Veja o código para inserir como é simples:

            um_livro = le_um_livro();
            inserir_livro(&um_livro, &loja);

Lê um livro do teclado e insere em seguida. Se resolver ler os livros de outro jeito já tem um ponto exato onde alterar as cosias. É mais produtivo assim.

 

O programa de exemplo co,mpleto

Spoiler

#define _op_insere_   1
#define _op_mostra_   2
#define _op_sair_     0
#define _TAM_        10

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

typedef struct
{
    int     codigo;
    char    autor[20];
    char    titulo[20];
    char    editora[20];

}   Livro;

typedef struct
{
    int     N;
    Livro   obra[_TAM_];

}   Acervo;

int     inserir_livro(Livro*, Acervo*);
Livro   le_um_livro();
int     menu();
int     mostra_obras(Acervo*);

int     main()
{
    Livro       um_livro;
    Acervo      loja;
    loja        .N = 0;
    int         op = 0;

    Livro exemplo = {
        0, "Autor exemplo",
        "Titulo exemplo", "Editora exemplo"
    };
    for (int i = 0; i < _TAM_ - 2; i += 1)
    {   // insere uns livros
        exemplo.codigo = 1000 + i;
        inserir_livro(&exemplo, &loja);
    };  // for()

    while ( (op = menu()) != _op_sair_)
    {
        switch (op)
        {
        case _op_insere_:
            um_livro = le_um_livro();
            inserir_livro(&um_livro, &loja);
            break;
        case _op_mostra_:
            mostra_obras(&loja);
            break;
        default:
            break;
        };
    }   // while()
    return (0);
};  // main()

int     inserir_livro(Livro* livro, Acervo* ficha)
{
    // ficha.N tem a primeira posicao livre
    printf("Acervo com %d de %d obras\n\n", ficha->N + 1, _TAM_);
    if (ficha->N == _TAM_) return -1; // acervo lotado
    ficha->obra[ficha->N] = *livro;
    ficha->N += 1; 
    return 0;
};  // inserir_livro();

Livro   le_um_livro()
{
    int ch; // para ler o resto da linha;
    Livro livro;

    printf("\nDigite o codigo do livro: ");
    scanf("%d", &livro.codigo);
    while (((ch = fgetc(stdin)) != '\n') && (!feof(stdin)));

    printf("Digite o título do livro: ");
    scanf("%20[^\n]s", &livro.titulo);
    while (((ch = fgetc(stdin)) != '\n') && (!feof(stdin)));

    printf("Digite o nome do autor: ");
    scanf("%20[^\n]s", &livro.autor);
    while (((ch = fgetc(stdin)) != '\n') && (!feof(stdin)));

    printf("Digite o nome da editora: ");
    scanf("%20[^\n]s", &livro.editora);
    while (((ch = fgetc(stdin)) != '\n') && (!feof(stdin)));
    return livro;
};  // inserir_livro();

int     menu()
{
    int ch = 0; // para ler a linha toda
    int op = -1;
    int invalida = 1; // so 0 eh falso

    system("cls");
    while( invalida )
    {
        printf("\n\nMenu:\n\n");
        printf("1 - Inserir um Novo Cadastro\n");
        printf("2 - Mostrar todos os cadastros\n");
        printf("0 - Encerrar\n");

        printf("\nDigite a opção desejada: ");
        scanf(" %d", &op);
        while (((ch = fgetc(stdin)) != '\n') && (!feof(stdin)));

        invalida = (op < 0) || (op > 2); // 0 1 2 validos
        //if(invalida){}; // opcao invalida

    } while (invalida);
    return op;
}

int     mostra_obras(Acervo* ficha)
{
    system("cls");
    printf("\n\nAcervo com %d de %d obras\n\n", ficha->N, _TAM_);

    printf("%10s    %20s    %20s    %20s\n\n",
        "Codigo", "Autor", "Titulo", "Editora");
    for (int i = 0; i < ficha->N; i++)
        printf("%10d    %20s    %20s    %20s\n\n",
            ficha->obra[i].codigo,
            ficha->obra[i].autor,
            ficha->obra[i].titulo,
            ficha->obra[i].editora);
    printf("\nTecle ENTER para retornar "); fgetc(stdin);
    return 0;
};  // mostra_obras()

 

 

Não é um modelo de nada. É só um exemplo de como pode resolver esse tipo de problema de um modo mecânico e seguro.

  • Curtir 1
Link para o comentário
Compartilhar em outros sites

@KXSY  Obrigado pelo seu tempo e ajuda.   fui testar e ta dando uns erros mas vou ver como corrijo isso e depois te passo feedback. obrigado 

 

image.thumb.png.f6d275b212b078f832d337abd04d4226.pngimage.thumb.png.a3b8a7ad7683a65613347d3117e67335.png

adicionado 11 minutos depois

@arfneto Muito Bom, obrigado pela explicação e pelo code, vou testar.,  algumas coisa ainda não estão muito claras para mim  no que diz respeito a performance, segurança e eficiência em C.
O começo parece ser duro mas o legal e que to ralando pra começar a codar sozinho.
Creio que com tudo que você apresentou e suficiente para melhorar minha base, não consigo acrescetar nada pela falta de know how mas de fato o conteúdo e a didática apresentada  somou muito.
Obrigado

 

  • Curtir 1
Link para o comentário
Compartilhar em outros sites

Os princípios do que escrevi não são ideia minha mas sim práticas recomendadas --- ou determinadas---  por quem está pagando ou ensinando --- há décadas. Mas no geral levam a mais resultado em menos tempo.

 

Evite usar funções que retornam void: em geral é no mínimo um desperdício e muitas vezes um erro mesmo.

 

trecho.png.db5336bb727284063bad2d89a2d35654.png

 

Em geral esses erros vem de você ter copiado código de outro editor. São caracteres de controle que estão no meio do texto. Edite antes com o bloco de notas no Windows por exemplo. E aí veja se aparece algo estranho. 

E para tirar dúvidas faça o simples: redigite uma linha e veja se o erro some.

  • Curtir 1
Link para o comentário
Compartilhar em outros sites

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