• Revista PROGRAMAR: Já está disponível a edição #53 da revista programar. Faz já o download aqui!

Guest tsenart

Ler uma string do teclado e atribui-la a um membro de um apontador para struct..

25 mensagens neste tópico

Alguem me diz o que é que está mal nesta função????

Como é que eu leio uma string para um membro de um apontador de estrutura?

void introduzir_livro(BIBLIOTECA *ptr)
{
     printf("Cota: "); scanf("%[^\n]", (char*)ptr->livro[ptr->conta].cota); fflush(stdin);
     printf("Autor: "); scanf("%[^\n]", (char*)ptr->livro[ptr->conta].autor); fflush(stdin);
     printf("Titulo: "); scanf("%[^\n]", (char*)ptr->livro[ptr->conta].titulo); fflush(stdin);
     ptr->livro[ptr->conta].estado='L';
     ptr->conta++;
}

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

usa o fgets();

Exacto, mais precisamente:

fgets(ptr->livro[ptr->conta].cota,100,stdin)

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites
void introduzir_livro(BIBLIOTECA *ptr)
{
     printf("Cota: "); fgets(ptr->livro[ptr->conta].cota,100,stdin); fflush(stdin);
     printf("Autor: "); fgets(ptr->livro[ptr->conta].autor,100,stdin); fflush(stdin);
     printf("Titulo: "); fgets(ptr->livro[ptr->conta].titulo,100,stdin); fflush(stdin);
     ptr->livro[ptr->conta].estado='L';
     ptr->conta++;
}

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

exactamente....

nao funciona...

vou postar o codigo do programa todo.

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

#define MAX_LIVROS 200

typedef struct
{
    int dia;
    int mes;
    int ano;
} DATA_M;

typedef struct
{
    char cota[20];
    char autor[40];
    char titulo[60];
    DATA_M data_aquisicao;
    char estado;
} LIVRO;

typedef struct
{
    LIVRO livro[MAX_LIVROS];
    unsigned int conta;
} BIBLIOTECA;


void cls();
void inic(BIBLIOTECA *ptr);
void apresenta_menu();
void introduzir_livro(BIBLIOTECA *ptr);
void alterar_estado(BIBLIOTECA *ptr);
void listar_req(BIBLIOTECA bib);
void listar_cota(BIBLIOTECA bib);
void listar_autor(BIBLIOTECA bib);
void mostrar_tudo(BIBLIOTECA bibl, int j);


void cls()
{
     fflush(stdin);
     system("cls");
}

void inic(BIBLIOTECA *ptr)
{
  int i;
     
     ptr->conta=0;
     for(i=0;i<=MAX_LIVROS;i++)
     {
         strcpy((char *)ptr->livro[i].cota, "NULL");
         strcpy((char *)ptr->livro[i].autor, "NULL");
         strcpy((char *)ptr->livro[i].titulo, "NULL");
         ptr->livro[i].data_aquisicao.dia = 0;
         ptr->livro[i].data_aquisicao.mes = 0;
         ptr->livro[i].data_aquisicao.ano = 0;
         ptr->livro[i].estado = 'O';
     }
}

void apresenta_menu()
{
     printf("\n\t\t\tGestao de uma biblioteca\n");
     printf("\t\t1 - Introduzir um novo livro\n");
     printf("\t\t2 - Alterar o estado de um livro\n");
     printf("\t\t3 - Listar os livros requesitados\n");
     printf("\t\t4 - Listar os livros ordenados pela cota\n");
     printf("\t\t5 - Listar os livros ordenados pelo autor\n");
     printf("\t\t6 - Terminar o programa\n");
}

void introduzir_livro(BIBLIOTECA *ptr)
{ 
     printf("Cota: "); fgets(ptr->livro[ptr->conta].cota, 20, stdin); fflush(stdin);
     printf("Autor: "); fgets(ptr->livro[ptr->conta].autor, 40, stdin); fflush(stdin);
     printf("Titulo: "); fgets(ptr->livro[ptr->conta].titulo, 60, stdin); fflush(stdin);
     ptr->livro[ptr->conta].estado='L';
     ptr->conta++;
}

void alterar_estado(BIBLIOTECA *ptr)
{
char tmp_estado, tmp_cota[20];
int i;
     
     printf("Qual a cota do livro? "); gets(tmp_cota);
     for(i=0;i<=MAX_LIVROS;i++);
     {
         if(strcmp(ptr->livro[i].cota, tmp_cota)==0)
         {
             printf("Novo estado(L - Livre, R - Requesitado, C - Acesso Condicionado): "); tmp_estado = getchar();
             if(toupper(tmp_estado) != 'L' && toupper(tmp_estado) != 'R' && toupper(tmp_estado) != 'C')
             {
                 printf("Estado invalido\n"); 
                 return;
             }
             ptr->livro[i].estado = toupper(tmp_estado);
         }
     }
}


void listar_req(BIBLIOTECA bib)
{
int i;
    
    for(i=0;i<=MAX_LIVROS; i++)
        if(bib.livro[i].estado=='R')
            mostrar_tudo(bib, i);
}


void listar_cota(BIBLIOTECA bib)
{
char tmp_cota[20];
int i;
     
     printf("Qual a cota do livro a procurar? "); gets(tmp_cota);
     for(i=0;i<=MAX_LIVROS;i++);
         if(strcmp(bib.livro[i].cota, tmp_cota)==0)
             mostrar_tudo(bib, i);
}


void listar_autor(BIBLIOTECA bib)
{
  int i;
  char tmp_autor[40];
      
      printf("Qual o nome do autor do livro a procurar? "); gets(tmp_autor);
      for(i=0;i<=MAX_LIVROS;i++)
          if(strcmp(bib.livro[i].autor, tmp_autor)==0)
              mostrar_tudo(bib, i);
}


void mostrar_tudo(BIBLIOTECA bibl,int j)
{
    puts((char *)bibl.livro[j].cota);
    puts((char *)bibl.livro[j].autor);
    puts((char *)bibl.livro[j].titulo);
    printf("%d/%d/%d\n", bibl.livro[j].data_aquisicao.dia, bibl.livro[j].data_aquisicao.mes, bibl.livro[j].data_aquisicao.ano);
    switch(toupper(bibl.livro[j].estado))
    {
        case 'L': puts("LIVRE"); break;
                                                
        case 'R': puts("REQUESITADO"); break;
                                                
        case 'C': puts("ACESSO CONDICIONADO"); break;
                                                
        default: puts("?");
    }
}
             


int main()
{
  int opcao;

    BIBLIOTECA biblioteca;
    inic(&biblioteca);
    while(1)
    {
        apresenta_menu(); printf("\nOpcao-> "); scanf("%d", &opcao); cls();
        
        switch(opcao)
        {
            case 1: introduzir_livro(&biblioteca); cls(); break;
            
            case 2: alterar_estado(&biblioteca); cls(); break;
            
            case 3: listar_req(biblioteca); cls(); break;
            
            case 4: listar_cota(biblioteca); cls(); break;
            
            case 5: listar_autor(biblioteca); cls(); break;
            
            case 6: return 0; 
            
            default: printf("\nOpcao invalida\n"); cls();
        }
    }
return 0;
}
    

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Alguem ajuda?

Eu já perdi algum tempo e não consegui ver o erro... ;)

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Podias começar por corrigir uma coisa que tá a corrompar alguma memória, mesmo que o bug possa não vir daí:

for(i=0;i<=MAX_LIVROS;i++)

para

for(i = 0 ; i < MAX_LIVROS ; i++)

ou

for( i = 0 ; i <= MAX_LIVROS - 1 ; i++)

Já agora, não funciona msm? dá algum erro? ja tentastes ver o que se passa com um debugger? não tenho possibilidades de testar o que quer que seja de momento e o código, apesar de ter umas coisas desnecessarias, deveria de funcionar correctamente...

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Se declaras as funções por cima da função main, não necessitas de usar isto:

void cls();

(...)

void mostrar_tudo(BIBLIOTECA bibl, int j);

Tenta utilizar parenteses nessas estruturas encadeadas. Pode haver algum problema com as precedências de operadores.

PS: o fflush é desnecessário aí pois o fgets lê o \n

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Já agora, não funciona msm? dá algum erro? ja tentastes ver o que se passa com um debugger? não tenho possibilidades de testar o que quer que seja de momento e o código, apesar de ter umas coisas desnecessarias, deveria de funcionar correctamente...

O problema está no correcto acesso à memória quando lemos o primeiro atributo de quando introduzimos um livro, dá Segmentation Fault...

Da maneira que ele tem escusava de usar apontadores, e a forma como define as estruturas se calhar não foi o mais fácil para ele (e para nós).

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

acho que o problema não está no fgets, está no índice do array.

(gdb) run

Starting program: /Users/rcg/prog

Reading symbols for shared libraries . done

                        Gestao de uma biblioteca

                1 - Introduzir um novo livro

                2 - Alterar o estado de um livro

                3 - Listar os livros requesitados

                4 - Listar os livros ordenados pela cota

                5 - Listar os livros ordenados pelo autor

                6 - Terminar o programa

Opcao-> 1

Breakpoint 1, introduzir_livro (ptr=0xbfff8f8c) at prog.c:70

70           printf("Cota: "); fgets(ptr->livro[ptr->conta].cota, 20, stdin); fflush(stdin);

(gdb) print ptr->conta

$1 = 1314212940

o problema deve estar na função 'inic'.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Podias começar por corrigir uma coisa que tá a corrompar alguma memória, mesmo que o bug possa não vir daí:

for(i=0;i<=MAX_LIVROS;i++)

para

for(i = 0 ; i < MAX_LIVROS ; i++)

ou

for( i = 0 ; i <= MAX_LIVROS - 1 ; i++)

o erro é precisamente esse. na função 'inic', ao executar mais uma iteração "atinge" a posição de memória onde está a variável 'conta', que deixa de ser 0.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Obrigado pessoal... Realmente funciona mas eu nao percebi o porque de nao poderem ser 201 livros em vez de 200....

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

declaraste um array de 200 posições, logo só podes usar 200 posições e não 201.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Ok... este problema está resolvido. Agora surgiu outro.

Quando introduzo um livro a função nao armazena os valores no vector livro[]....

Fiz uns printf's para verificar os conteudos a seguir à função inserir e a cota(e os outros) continuam com NULL(a string com que foram inicializados).

Realmente n sei sair desta. Talvez porque o argumento da funçao introduzir_livro() seja do tipo apontador para BIBLIOTECA e eu estou a introduzir dados num vector do tipo LIVRO.

Mas funciona no inic().....

Any help?

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

É o mesmo que está na pág anterior.... Larguei este projecto. E agora voltei a ele.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Estive a olhar para o teu código e podias começar por alterar algum código, nomeadamente:

  • para usares a função toupper deves colocar o #include <ctype.h>
  • não deves usar a função gets uma vez que é uma função dangerous  :biggrin: Isto porque a função gets não limita de forma alguma o número de caracteres lidos, e isso significa que o array apontado pelo argumento do gets pode não ter exactamente o que o utilizador introduz e pode até muito bem acontecer que a string introduzida pelo utilizador ultrapasse os limites desse array. Usa o fgets em vez do gets da seguinte forma: fgets(apontador para o array, numero maximo de elementos do array, stdin)
  • para usares a função system deves colocar o #include <stdlib.h>
  • usares o system("cls") não é platform-independent porque, por exemplo, em linux não há o comando cls, logo o teu programa vai gerar um erro quando chega à linha do system em linux. Para além disso, um pc a correr o teu programa remotamente não tem acesso ao processador de comandos e falha nesta linha, mesmo que seja num sistema operativo com o comando cls definido. Por isso, acho que não devias usar esta chamada.

Depois destas dicas, deves fazer debug e ver exactamente o que cada variável e cada array de char tem e se é o que realmente queres que o teu programa faça. Assim que tiver mais tempo analiso com mais detalhe o teu código. Espero que tenha ajudado de alguma forma a melhorar o teu código e a atingires os teus objectivos  :)

Continua com o bom trabalho!

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Já vi o printf... Tens 2 problemas na função listar_cota, e um na listar_autor: um é comum às duas, e é por estares a usar um fgets para ler os dados do livro na função inserir, o que guarda o enter no final da linha, e estares a usar nestas duas funções o gets, que não guarda esse enter. O 2º problema da função listar_cota é por teres posto um ';' à frente do for. As funções corrigidas ficam assim:

void listar_cota(BIBLIOTECA bib) {
char tmp_cota[20];
int i;

printf("Qual a cota do livro a procurar? "); fgets(tmp_cota, 20, stdin);
for(i=0;i<=MAX_LIVROS;i++)
	if(strcmp(bib.livro[i].cota, tmp_cota)==0)
		mostrar_tudo(bib, i);
}

void listar_autor(BIBLIOTECA bib)
{
int i;
char tmp_autor[40];

printf("Qual o nome do autor do livro a procurar? "); fgets(tmp_autor, 40, stdin);
for(i=0;i<=MAX_LIVROS;i++)
	if(strcmp(bib.livro[i].autor, tmp_autor)==0)
		mostrar_tudo(bib, i);
}

Já agora, pensa em passar o parâmetro bib como apontador para biblioteca para evitar fazer a cópia da estrutura entre chamadas às funções. E também não vais conseguir ver os resultados no ecrã, porque no switch tens um cls() logo a seguir à chamada a estas funções.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Crie uma conta ou ligue-se para comentar

Só membros podem comentar

Criar nova conta

Registe para ter uma conta na nossa comunidade. É fácil!


Registar nova conta

Entra

Já tem conta? Inicie sessão aqui.


Entrar Agora