alphasil Posted June 12, 2012 Report Share Posted June 12, 2012 Oi ppl; Estou a tentar ler um ficheiro e verificar quantos registos tem. (funciona) Testo uma função random (funciona) Depois quero que me vá buscar aquele registo atribuindo ao registo o valor do random (funciona) Agora não me dá é o registo, tenho isso a funcionar noutra função mas nesta não me dá... void gp1_Ques(struct perg *p) { FILE *f; //apontador para ficheiro f=fopen("gp1.dat", "r"); //abertura do ficheiro char buf[5]; int reg=0, qnum=0, random, op; //declaração variáveis int qual, result; //declaração variáveis rewind(f); //retorna a posição corrente do ficheiro para o início srand(time(NULL)); //função random while (fread(p,sizeof *p,1,f)==1) //ciclo de leitura da estrutura perg { reg++; //variavel contadora de registos } if (reg<=0) //condição que verifica se existem registos { printf ("Sem registos"); printf ("Necessario ter registos para jogar..."); return; } else { printf ("TOTAL de perguntas : %d \n",reg); //conta as perguntas printf ("\nO seu score maximo sera : %d\n",reg); //pontuação máxima do jogo qual = reg*(0.75); //contagem minima para passar de fase printf ("\nPara a qualificacao precisa de: %d\n",qual); //total minimo para passar fase //testes para ver se funciona o random random=rand()%reg; //função random printf("\n%d\n", random); reg = random; //atribui a variavel reg o valor de random printf("\n%d\n", reg); } printf("Quer comecar a jogar ?(Sim=1; Nao=0) \n"); fgets(buf, sizeof buf , stdin); sscanf(buf, "%d", &op); if (op==1) { while(fread(p, sizeof *p, 1, f)) { reg++; if (p->id==reg) //condição que verifica de no ficheiro o id é = ao reg { printf("\nPergunta : %s", p->ques); printf("\nOpcao 1 : %s",p->op1); printf("\nOpcao 2 : %s",p->op2); printf("\nOpcao 3 : %s",p->op3); printf("\nOpcao 4 : %s",p->op4); } else { printf("Registo nao existente"); } } /*while (fread(p, sizeof *p,1, f)==1) //{ //printf("Utilizador ligado: %s",jogador); printf ("Resultado : %d",result); qnum++; }*/ } fclose(f); } Nem o registo aparece nem a frase Registo nao existente...por isso deve ser problema de chavetas, não?? Só não vejo é onde... gmc11 Link to comment Share on other sites More sharing options...
bsccara Posted June 12, 2012 Report Share Posted June 12, 2012 Tendo os teus registos um tamanho fixo e sendo a stream 'seekable' podes usar isto para obter o número de registos, que é mais simples e rápido: fseek(f,0,SEEK_END); reg = ftell(f) / sizeof *p; fseek(f,0,SEEK_SET); Link to comment Share on other sites More sharing options...
alphasil Posted June 12, 2012 Author Report Share Posted June 12, 2012 Obrigado if (op==1) { while(fread(p, sizeof *p, 1, f)) { reg++; if (p->id==reg) //condição que verifica de no ficheiro o id é = ao reg { printf("\nPergunta : %s", p->ques); printf("\nOpcao 1 : %s",p->op1); printf("\nOpcao 2 : %s",p->op2); printf("\nOpcao 3 : %s",p->op3); printf("\nOpcao 4 : %s",p->op4); } else { printf("Registo nao existente"); } } Mas estás a dizer para usar em vez disso, ou seja usar a função fseek para posicionar no início e no fim? gmc11 Link to comment Share on other sites More sharing options...
HappyHippyHippo Posted June 12, 2012 Report Share Posted June 12, 2012 sim, o bsscara disse que podes usar o fseek para colocar o ponteiro directamente no fim do ficheiro dizendo assim o seu tamanho. com um tamanho fixo de elementos basta dividires o valor pelo tamanho fixo e teras o número de elementos. depois é só multiplicares o número da resposta que pretendes pelo tamanho fixo para obteres a posição do ficheiro da resposta pretendida. voltas a o fseek para ir directamente para a posição pretendida. nota: int reg=0, qnum=0, random, op; ... while (fread(p,sizeof *p,1,f)==1) { reg++; } if (reg<=0) { A variável reg só terá um valor negativo quando leres MAX_INT + 1 elementos do ficheiro (olha que são mesmo muitos). basta um == 😄 IRC : sim, é algo que ainda existe >> #p@p Portugol Plus Link to comment Share on other sites More sharing options...
alphasil Posted June 12, 2012 Author Report Share Posted June 12, 2012 (edited) Obrigado Tenho é um problema, o último if não me entra Pus uns printf pelo caminho a ver se chegava lá mas não chega if (op==1) { printf("escolheu o sim"); fseek(f,0,SEEK_END); reg = ftell(f) / sizeof *p; fseek(f,0,SEEK_SET); printf("Valor de reg %d", reg); if (p->id==reg) //condição que verifica de no ficheiro o id é = ao reg { A frase aparece-me, ponho a opção 1 e termina o programa... Está alguma mal aqui? Edited June 12, 2012 by alphasil gmc11 Link to comment Share on other sites More sharing options...
HappyHippyHippo Posted June 12, 2012 Report Share Posted June 12, 2012 se te aparece "escolheu o sim" e o "Valor de reg %d" então o p->id != reg IRC : sim, é algo que ainda existe >> #p@p Portugol Plus Link to comment Share on other sites More sharing options...
alphasil Posted June 12, 2012 Author Report Share Posted June 12, 2012 Era um problema do fgets, já está resolvido. A questão é esta, já tenho os valores contados, já tenho o random, já atribui ao novo valor de reg o valor de random, agora quero que vá buscar o id respetivo, por isso não vejo relevância em voltar a contar os registos, percebes? Já tenho isso aqui. printf ("TOTAL de perguntas : %d \n",reg); //conta as perguntas printf ("\nO seu score maximo sera : %d\n",reg); //pontuação máxima do jogo qual = reg*(0.75); //contagem minima para passar de fase printf ("\nPara a qualificacao precisa de: %d\n",qual); //total minimo para passar fase //testes para ver se funciona o random random=rand()%reg; //função random printf("\n%d\n", random); reg = random; //atribui a variavel reg o valor de random printf("\n%d\n", reg); Como já tenho o novo reg atribuido pelo random, agora é só chamar o registo respetivo, estou a ir bem? gmc11 Link to comment Share on other sites More sharing options...
bsccara Posted June 12, 2012 Report Share Posted June 12, 2012 if (op==1) { printf("escolheu o sim"); fseek(f,0,SEEK_END); reg = ftell(f) / sizeof *p; fseek(f,0,SEEK_SET); printf("Valor de reg %d", reg); if (p->id==reg) //condição que verifica de no ficheiro o id é = ao reg { A frase aparece-me, ponho a opção 1 e termina o programa... Está alguma mal aqui? Está, o que o HHH te disse foi para usares o fseek para posicionares o cursor da stream no registo pretendido, não para usar o código que te dei que serve para obter o número de registos no ficheiro. O código que te dei é para usar em vez do que tens a contar registos, no início da função. Portanto no ponto que referes no teu código acima deves fazer 'fseek(f, reg * sizeof *p, SEEK_SET)' e depois fread(...) para ler o registo. Link to comment Share on other sites More sharing options...
alphasil Posted June 12, 2012 Author Report Share Posted June 12, 2012 lol Pois, obrigado, já estava a ver qual era a utilidade de contar 2 vezes os registos.... Vou tentar seguir esse raciocínio Então, percebendo bem o que te estavas a referir, posso contar logo os registos com o fseek e atribuir a variável reg o total, deste modo simplifica mais. gmc11 Link to comment Share on other sites More sharing options...
alphasil Posted June 12, 2012 Author Report Share Posted June 12, 2012 Pelos vistos já está a funcionar, vai-me buscar o registo dado pelo random. A vossa opinião final se faz favor: //Gestão jogo para grupo 1 void gp1_Ques(struct perg *p) { FILE *f; //apontador para ficheiro f=fopen("gp1.dat", "r"); //abertura do ficheiro char buf[5]; int reg=0, qnum=0, random, op; //declaração variáveis int qual, result; //declaração variáveis rewind(f); //retorna a posição corrente do ficheiro para o início srand(time(NULL)); //função random fseek(f, 0, SEEK_END); reg=ftell(f) /sizeof *p; fseek(f, 0 , SEEK_SET); if (reg<=0) //condição que verifica se existem registos { printf ("Sem registos"); printf ("Necessario ter registos para jogar..."); return; } else { printf ("TOTAL de perguntas : %d \n",reg); //conta as perguntas printf ("\nO seu score maximo sera : %d\n",reg); //pontuação máxima do jogo qual = reg*(0.75); //contagem minima para passar de fase printf ("\nPara a qualificacao precisa de: %d\n",qual); //total minimo para passar fase //testes para ver se funciona o random random=rand()%reg; //função random reg = random; //atribui a variavel reg o valor de random } printf("\nQuer comecar a jogar ?(Sim=1; Nao=0) \n"); scanf("%d", &op); if(op==1) { fseek(f, reg * sizeof *p, SEEK_SET); fread(p, sizeof *p, 1, f); printf("\nPergunta : %s", p->ques); printf("\nOpcao 1 : %s",p->op1); printf("\nOpcao 2 : %s",p->op2); printf("\nOpcao 3 : %s",p->op3); printf("\nOpcao 4 : %s",p->op4); } fclose(f); } Podia ficar melhor, mais simples, mais eficaz?' cumps Obrigado gmc11 Link to comment Share on other sites More sharing options...
HappyHippyHippo Posted June 12, 2012 Report Share Posted June 12, 2012 notas para uma melhor programação : 1º - declara à cabeça todas a variáevis (tens um fopen lá pelo meio) 2º - a indentação está +- (pode ser do geshi ... não sei) 3º - separa sempre o código de manipulação de dados do código de apresentação de informação (tens tudo na mesma função) 4º - estás a atribuir o valor aleatório para a variável "reg", desta forma estás a perder a informação de quantas perguntas existem no ficheiro 5º - o processo de abertura e verificação de número de registo devia ser efectuado no início da aplicação eliminando a necessidade de verificação continua 6º - a abertura de ficheiro, o seu manuseamento e fecho deverá ser o mais rápido possível, isto implica saberes à partida o que pretendes do ficheiro para poder chamar a função fclose o mais cedo possível (por isso o ponto 5) assim de cabeça é isso ... pode ser que me lembre e alguma coisa mais tarde IRC : sim, é algo que ainda existe >> #p@p Portugol Plus Link to comment Share on other sites More sharing options...
alphasil Posted June 12, 2012 Author Report Share Posted June 12, 2012 Obrigado mais uma vez Ponto a ponto 1 - Já alterei o lugar do fopen, as variaveis estão todas em cima; 2- Deve ser do geshi (aqui está tudo certinho) 3- Criar uma função que vai chamar os resultados desta manipulação? 4- Criar uma outra variavel (reg1) que vai ser a do random sem mexer na principal que é onde está a contagem dos registos? 5 e 6 - Pôr o FILE *f como global? Obrigado gmc11 Link to comment Share on other sites More sharing options...
HappyHippyHippo Posted June 12, 2012 Report Share Posted June 12, 2012 3- Criar uma função que vai chamar os resultados desta manipulação? o que estou a dizer é teres por exemplo ... um ficheiro .c com o código de manipulação de dados, outro para apresentação de menus e um terceiro só para o main 4- Criar uma outra variavel (reg1) que vai ser a do random sem mexer na principal que é onde está a contagem dos registos? isso já é contigo ... era só um aviso .. 5 e 6 - Pôr o FILE *f como global? epa ... quantas vezes já leste aqui para não usar variáveis globais ?? o que estou a dizer é, quando a aplicação arranca abres o ficheiro, vês quantas perguntas tem e fechas. Depois é só abrir, ler a pergunta e fechar novamente IRC : sim, é algo que ainda existe >> #p@p Portugol Plus Link to comment Share on other sites More sharing options...
alphasil Posted June 12, 2012 Author Report Share Posted June 12, 2012 Ok Vou tentar fazer isso. Muito obrigado, qualquer duvida...volto. Obrigado pela paciência gmc11 Link to comment Share on other sites More sharing options...
alphasil Posted June 12, 2012 Author Report Share Posted June 12, 2012 (edited) Já agora, enquanto estava a verificar uma função surgiu-me esta duvida Se criar vários ficheiros, um para menus, outro para manipulação de ficheiros, a chamada deles para o main é só fazer função()? cumps Edited June 12, 2012 by alphasil gmc11 Link to comment Share on other sites More sharing options...
bsccara Posted June 12, 2012 Report Share Posted June 12, 2012 Sim, mas vais ter de incluir um outro ficheiro (ficheiro de inclusão, com extensão .h) no código com o prótotipo da função (ou declará-lo à mão onde vai ser usada). Podes começar por aqui para perceber a utilização dos ficheiros de inclusão próprios. Link to comment Share on other sites More sharing options...
alphasil Posted June 13, 2012 Author Report Share Posted June 13, 2012 Oi Já pus isso tudo em três ficheiros *.c main , menus e funcoes para além de ter posto um ficheiro *.h com com o protótipo das funçoes, está tudo a funcionar menos esta função que estoira sempre que escolho um (segmentation fault) quando estava num ficheiro único funcionava.. O meu ficheiro h #ifndef FUNC_H_INCLUDED #define FUNC_H_INCLUDED //funções para a gestão das perguntas void ad_perguntas(); void ver_perguntas(); void edit_perguntas(); void remov_perguntas(); void ad_perguntasgp2(); void ver_perguntasgp2(); void edit_perguntasgp2(); void remov_perguntasgp2(); void LeVetor(); void vetorOrdenado(); void bubbleSort(); void ad_perguntasgp4(); void ver_perguntasgp4(); void edit_perguntasgp4(); void remov_perguntasgp4(); //Funçoes de menus void tipoMenu(); void menu_principal(); void menu_ad(); void menu_ad1(); void menu_ad2(); void menu_ad3(); //Função jogo void jogo(); void gp1_Ques(); //registo jogaodres void registo(); int login(); #endif // FUNC_H_INCLUDED A função que estoira é esta int login(struct jogador *u) { char usr1[30], userpass[50]; memset(usr1, 0, 30); memset(userpass, 0, 50); int op; struct jogador j; struct perg p; FILE *f; f=fopen("registos.dat", "r"); if (!f) { printf("Nao existe este ficheiro"); } fseek(f, 0, SEEK_END); fseek(f, 0, SEEK_SET); printf("\nPara jogar tem de estar registado...\n"); printf("\nTem registo ? (1 - Sim / 2 - Nao) \n"); scanf(" %d", &op); getchar(); if(op==1) { fread(u, sizeof *u, 1, f); printf("Introduza o nick \n"); fgets (usr1, 29, stdin); printf("Introduza a sua pass \n"); fgets (userpass, 49, stdin); if (strcmp(usr1,u->nick)==0) { if (strcmp(userpass, u->pass)==0) { gp1_Ques(&p); } } else { printf("Erro no nick ou na pass"); } } if (op==2) { registo(&j); } return 0; } Arrebenta nesta linha quando uso o debug fread(u, sizeof *u, 1, f); Antes de pôr separado funcionava, não percebo por que razão funcionam todas menos esta.. Mestres, que fiz de mal, mais uma vez 😛 Obrigado gmc11 Link to comment Share on other sites More sharing options...
HappyHippyHippo Posted June 13, 2012 Report Share Posted June 13, 2012 os protótipos das funções estão diferentes : //.h int login(); // .c int login(struct jogador *u) os protótipos não é só o tipo de dados que retorna e o nome da função, mas também a lista de argumentos da função IRC : sim, é algo que ainda existe >> #p@p Portugol Plus Link to comment Share on other sites More sharing options...
alphasil Posted June 13, 2012 Author Report Share Posted June 13, 2012 Bom dia; Percebo mas por que razão dão todas menos essa?? Pus os protótipos iguais mas agora dá erro, não compila...tenho uma quantidade de warnings e erros. Compiling: menus.c In file included from D:\2012\c_exe\Projeto Final\menus.c:7:0: D:\2012\c_exe\Projeto Final\/func.h:37:18: warning: 'struct jogador' declared inside parameter list [enabled by default] D:\2012\c_exe\Projeto Final\/func.h:37:18: warning: its scope is only this definition or declaration, which is probably not what you want [enabled by default] D:\2012\c_exe\Projeto Final\menus.c: In function 'jogo': D:\2012\c_exe\Projeto Final\menus.c:88:13: error: too few arguments to function 'login' D:\2012\c_exe\Projeto Final\/func.h:37:5: note: declared here Process terminated with status 1 (0 minutes, 0 seconds) 2 errors, 2 warnings Só pus as funções iguais. Pelo que percebo na função jogo, quando chamo a função login() espera argumentos dentro dos parêntesis, ou seja tenho de usar uma apontador para jogador? cumps gmc11 Link to comment Share on other sites More sharing options...
HappyHippyHippo Posted June 13, 2012 Report Share Posted June 13, 2012 porque as definições das estruturas também são para serem declaradas no .h antes das funções caso contrário, ao compilar o ficheiro .c que não tem as declarações das estruturas não sabe como que elas existem e queixa-se IRC : sim, é algo que ainda existe >> #p@p Portugol Plus Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now