PsySc0rpi0n Posted April 24, 2013 at 06:59 PM Report #504721 Posted April 24, 2013 at 06:59 PM (edited) Boas novamente... Na última segunda feira estivemos a fazer o seguinte exercício: Escreva um programa que leia valores inteiros positivos e os guarde num ficheiro binário. O fim da introdução é sinalizado pela introdução de um negativo. Depois, o programa deve criar dois ficheiros: um com os nºs pares e outro com os nºs impares. Eu fiz de uma maneira mas acabei por ficar encalhado num loop infinito. Criei algumas funções e nessas funções passei o ponteiro para o FILE. A prof. disse que desconfiava que fosse por estar a passar um file pointer porque não é recomendado fazê-lo. Neste momento não tenho aqui o code comigo mas mais logo ou amanhã já aqui o coloco. Quanto à passagem do file pointer para diversas funções, há mesmo inconvenientes? O loop infinito que obtive foi na função que mostrava o ficheiro onde guardei os números pares e ímpares. É uma função que recebe dois file pointers, para o file dos pares e para o file dos ímpares, e depois lê o file (binário) e apresenta no ecrã os valores lá guardados em cada um dos files. os respectivos fopens estão na função main... Mas amanhã eu coloco o code... Edited April 24, 2013 at 06:59 PM by PsySc0rpi0n Kurt Cobain - Grunge misses you Nissan GT-R - beast killer
pmg Posted April 24, 2013 at 07:10 PM Report #504722 Posted April 24, 2013 at 07:10 PM Nao. Nao ha problema nenhum em passar um ponteiro para FILE: é isso que fazem muitas funcoes declaradas no header <stdio.h>. Assim sem mais informacao, eu aposto que estas a fazer um feof() errado. A maior parte do uso de feof() em programas "basicos" esta errada! O feof() nao serve para verificar se a proxima leitura vai dar erro por nao haver dados. O feof() serve para ajudar a identificar a causa do ultimo erro de leitura; se nao houve erro de leitura, o uso de feof() esta pura e simplesmente errado. Ou seja: o uso correcto de feof() pressupoe que se tenha detectado um erro de leitura antes desse mesmo uso. What have you tried? Não respondo a dúvidas por PM A minha bola de cristal está para compor; deve ficar pronta para a semana. Torna os teus tópicos mais atractivos e legíveis usando a tag CODE para colorir o código!
PsySc0rpi0n Posted April 25, 2013 at 08:31 AM Author Report #504757 Posted April 25, 2013 at 08:31 AM (edited) Bom dia... Então o code é este e obtenho um loop infinito na função LeParesImpares()... E não é o único problema, mas vamos por partes... #include <stdio.h> #include <stdlib.h> void GravaFicheiro(FILE *pfile, int *numeros) { fwrite (numeros, sizeof(int), 1, pfile); } void GravaPar(FILE *pfpar, int *numeros) { fwrite (&numeros, sizeof(int), 1, pfpar); } void GravaImpar(FILE *pfileimpar, int *numeros) { fwrite (&numeros, sizeof(int), 1, pfileimpar); } void LeParesImpares(FILE *fpares, FILE *fimpares) { int numpares, numimpares; while (!(fread(&numpares, sizeof(int), 1, fpares))) printf ("\nNúmeros pares:%d\t", numpares); while (!(fread(&numimpares, sizeof(int), 1, fimpares))) printf("\nImpares:%d\t", numimpares); } int main(void) { int numeros; FILE *pfile, *pfilepar, *pfileimpar; if ((pfile = fopen ("num.dat", "w+b")) == NULL) { printf ("Erro a abrir o ficheiro!\n"); exit (0); } if ((pfilepar = fopen ("par.dat", "w+b")) == NULL) { printf ("Erro a abrir o ficheiro!\n"); exit (1); } if ((pfileimpar = fopen ("impar.dat", "w+b"))== NULL) { printf ("Erro ao abrir ficheiro!\n"); exit (2); } do { printf ("Introduza números inteiros:\n"); printf ("Introduza um número negativo para sair:\n"); scanf ("%d", &numeros); if (numeros >= 0) //fwrite (&numeros, sizeof(int),1,pfile); GravaFicheiro (&pfile, &numeros); if (!(numeros%2)) //fwrite(&numeros, sizeof(int),1,pfilepar); GravaPar (&pfilepar, &numeros); else fwrite (&numeros, sizeof(int),1,pfileimpar); //GravaImpar (&pfileimpar, &numeros); } while (numeros >= 0); LeParesImpares (pfilepar, pfileimpar); fclose(pfile); fclose(pfilepar); fclose(pfileimpar); getchar (); return 0; } Edited April 25, 2013 at 08:32 AM by PsySc0rpi0n Kurt Cobain - Grunge misses you Nissan GT-R - beast killer
pmg Posted April 25, 2013 at 09:01 AM Report #504758 Posted April 25, 2013 at 09:01 AM Primeiro: liga os warnings do teu compilador. Alguns dos valores que passas da funcao main() para as outras funcoes tem o tipo errado. O compilador bem configurado pode-te avisar disso. Sugestao: nao uses o operador ! com o valor devolvido pela funcao fread(). O teu problema da funcao LeParesImpares() é estares constantemente a tentar ler depois do fim do ficheiro. A funcao devolve 0 (zero) e o operador ! torna esse valor verdade e o ciclo nao termina. What have you tried? Não respondo a dúvidas por PM A minha bola de cristal está para compor; deve ficar pronta para a semana. Torna os teus tópicos mais atractivos e legíveis usando a tag CODE para colorir o código!
PsySc0rpi0n Posted April 25, 2013 at 11:00 AM Author Report #504772 Posted April 25, 2013 at 11:00 AM (edited) pmg, o gcc não me dá warnings nenhuns... Que cinfigurações me faltam??? Quanto ao fread, ter ali o !, não é o mesmo que fazer != 0??? Neste momento tenho o code assim: #include <stdio.h> #include <stdlib.h> void GravaFicheiro(FILE *pfile, int *numeros) { fwrite (numeros, sizeof(int), 1, pfile); } void GravaPar(FILE *pfpar, int *numeros) { fwrite (&numeros, sizeof(int), 1, pfpar); } void GravaImpar(FILE *pfileimpar, int *numeros) { fwrite (&numeros, sizeof(int), 1, pfileimpar); } void LeParesImpares(FILE *fpares, FILE *fimpares) { int numpares, numimpares; while (!feof (fpares)) { fread(&numpares, sizeof(int), 1, fpares); printf ("\nNúmeros Pares:%d\t", numpares); } putchar ('\n'); while (!feof (fimpares)) { fread(&numimpares, sizeof(int), 1, fimpares); printf("\nNúmeros Impares:%d\t", numimpares); } putchar ('\n'); } int main(void) { int numeros; FILE *pfile, *pfilepar, *pfileimpar; if ((pfile = fopen ("num.dat", "w+b")) == NULL) { printf ("Erro a abrir o ficheiro!\n"); exit (0); } if ((pfilepar = fopen ("par.dat", "w+b")) == NULL) { printf ("Erro a abrir o ficheiro!\n"); exit (1); } if ((pfileimpar = fopen ("impar.dat", "w+b"))== NULL) { printf ("Erro ao abrir ficheiro!\n"); exit (2); } do { printf ("Introduza números inteiros:\n"); printf ("Introduza um número negativo para sair:\n"); scanf ("%d", &numeros); if (numeros >= 0) fwrite (&numeros, sizeof(int),1,pfile); //GravaFicheiro (&pfile, &numeros); debugging if (!(numeros%2)) fwrite(&numeros, sizeof(int),1,pfilepar); debugging //GravaPar (&pfilepar, &numeros); debugging else fwrite (&numeros, sizeof(int),1,pfileimpar); //GravaImpar (&pfileimpar, &numeros); } while (numeros >= 0); LeParesImpares (pfilepar, pfileimpar); fclose(pfile); fclose(pfilepar); fclose(pfileimpar); getchar (); return 0; } Edited April 25, 2013 at 11:11 AM by PsySc0rpi0n Kurt Cobain - Grunge misses you Nissan GT-R - beast killer
HappyHippyHippo Posted April 25, 2013 at 11:09 AM Report #504774 Posted April 25, 2013 at 11:09 AM pmg, o gcc não me dá warnings nenhuns... Que cinfigurações me faltam??? não sei, mas provavelmente o -Wall, -pedantic, -Werror Quanto ao fread, ter ali o !, não é o mesmo que fazer != 0??? o fread retorna o número de elementos lidos, se pedires para ler 40 elementos e retornar 20, como vai verificar o erro ocorrido com essa comparação ? IRC : sim, é algo que ainda existe >> #p@p Portugol Plus
PsySc0rpi0n Posted April 25, 2013 at 11:12 AM Author Report #504775 Posted April 25, 2013 at 11:12 AM (edited) não sei, mas provavelmente o -Wall, -pedantic, -Werror o fread retorna o número de elementos lidos, se pedires para ler 40 elementos e retornar 20, como vai verificar o erro ocorrido com essa comparação ? Já alterei... Vou testar agora... Acho que tenho essas 3 flags no alias do .bashrc Edited; Adicionei o -Werror mas continua a não dar qualquer warning... Os outros já os tinha... alias agcc='gcc -Wall -Wextra -Werror -pedantic -std=c99 -lm' Edited April 25, 2013 at 11:14 AM by PsySc0rpi0n Kurt Cobain - Grunge misses you Nissan GT-R - beast killer
PsySc0rpi0n Posted April 25, 2013 at 11:23 AM Author Report #504777 Posted April 25, 2013 at 11:23 AM (edited) Ok, já sei o que se passava... Estavam ali uns & a mais mas foi na aula que estivemos a tentar perceber porque não conseguia sair do loop infinito e andámos a inventar... Já retirei e já compilei de novo sem erros... Mas o resultado ainda não é o esperado... Edited April 25, 2013 at 11:24 AM by PsySc0rpi0n Kurt Cobain - Grunge misses you Nissan GT-R - beast killer
HappyHippyHippo Posted April 25, 2013 at 11:29 AM Report #504778 Posted April 25, 2013 at 11:29 AM antes de mais : o que tens não é o pedido no exercício !!! responde a esta questão : onde se encontra o ponteiro interno dos ficheiros quando chamas a função LeParesImpares ? IRC : sim, é algo que ainda existe >> #p@p Portugol Plus
pmg Posted April 25, 2013 at 11:34 AM Report #504779 Posted April 25, 2013 at 11:34 AM Quanto ao fread, ter ali o !, não é o mesmo que fazer != 0??? Nao! Por isso mesmo sugeri que nao usasses o ! A mim faz-me sempre confusao usar o ! com coisas que nao sao "booleanos" if (x) {} /* A */ if (x != 0) {} /* A */ if (!x) {} /* B */ if (x == 0) {} /* B */ if (fread(...) == 1) {} /* nem A nem B */ if (fread(...) != 1) {} /* nem A nem B */ What have you tried? Não respondo a dúvidas por PM A minha bola de cristal está para compor; deve ficar pronta para a semana. Torna os teus tópicos mais atractivos e legíveis usando a tag CODE para colorir o código!
PsySc0rpi0n Posted April 25, 2013 at 11:44 AM Author Report #504780 Posted April 25, 2013 at 11:44 AM (edited) O code neste momento está assim: #include <stdio.h> #include <stdlib.h> void GravaFicheiro(FILE *pfile, int numeros) { fwrite (&numeros, sizeof(int), 1, pfile); } void GravaPar(FILE *pfpar, int numeros) { fwrite (&numeros, sizeof(int), 1, pfpar); } void GravaImpar(FILE *pfileimpar, int numeros) { fwrite (&numeros, sizeof(int), 1, pfileimpar); } void LeParesImpares(FILE *fpares, FILE *fimpares) { int numpares, numimpares; while (!feof(fpares)) { fread(&numpares, sizeof(int), 1, fpares); printf ("\nNúmeros Pares:%d\t", numpares); } putchar ('\n'); while (!feof(fimpares)) { fread(&numimpares, sizeof(int), 1, fimpares); printf("\nNúmeros Impares:%d\t", numimpares); } putchar ('\n'); } int main(void) { int numeros; FILE *pfile, *pfilepar, *pfileimpar; if ((pfile = fopen ("num.dat", "w+b")) == NULL) { printf ("Erro a abrir o ficheiro!\n"); exit (0); } if ((pfilepar = fopen ("par.dat", "w+b")) == NULL) { printf ("Erro a abrir o ficheiro!\n"); exit (1); } if ((pfileimpar = fopen ("impar.dat", "w+b"))== NULL) { printf ("Erro ao abrir ficheiro!\n"); exit (2); } do { printf ("Introduza números inteiros:\n"); printf ("Introduza um número negativo para sair:\n"); scanf ("%d", &numeros); if (numeros >= 0){ //fwrite (&numeros, sizeof(int),1,pfile); GravaFicheiro (pfile, numeros); if (!(numeros%2)) //fwrite(&numeros, sizeof(int),1,pfilepar); GravaPar (pfilepar, numeros); else //fwrite (&numeros, sizeof(int),1,pfileimpar); GravaImpar (pfileimpar, numeros); } } while (numeros >= 0); printf ("Posição do filepointer par %ld\n", ftell(pfilepar)); printf ("Posição do filepointer impar %ld\n", ftell(pfileimpar)); printf ("Posição do filepointer %ld\n", ftell(pfile)); LeParesImpares (pfilepar, pfileimpar); fclose(pfile); fclose(pfilepar); fclose(pfileimpar); getchar (); return 0; } Os file pointers estão: Posição do filepointer par 20 Posição do filepointer impar 20 Posição do filepointer 40 Já está quase perfeito... Só está a repetir o último valor inserido... Faltava o rewind!!! Uma outra questão: qual função usar para colocar o filepointer no início do file? fseek ou rewind? Edited April 25, 2013 at 12:38 PM by PsySc0rpi0n Kurt Cobain - Grunge misses you Nissan GT-R - beast killer
pmg Posted April 25, 2013 at 01:12 PM Report #504784 Posted April 25, 2013 at 01:12 PM Agora tens o erro que eu apostava no principio do thread: erro no uso da funcao feof(); embora o teu codigo nao faca ciclos devido ao erro. Usa o valor de retorno da funcao fread() para saber se deves parar o ciclo ou nao. Usar o feof() para esse efeito esta errado. Uma outra questão: qual função usar para colocar o filepointer no início do file? fseek ou rewind? fseek() com os argumentos correctos é muito, muito parecido com rewind(). What have you tried? Não respondo a dúvidas por PM A minha bola de cristal está para compor; deve ficar pronta para a semana. Torna os teus tópicos mais atractivos e legíveis usando a tag CODE para colorir o código!
PsySc0rpi0n Posted April 25, 2013 at 01:43 PM Author Report #504787 Posted April 25, 2013 at 01:43 PM (edited) Então uso o quê? Assim: while ((fread(&numeros, sizeof(int), 1, fpointer)) !=0) É que não percebi bem como usar o valor de retorno do fread! Edited April 25, 2013 at 01:43 PM by PsySc0rpi0n Kurt Cobain - Grunge misses you Nissan GT-R - beast killer
pmg Posted April 25, 2013 at 02:08 PM Report #504791 Posted April 25, 2013 at 02:08 PM O fread() é assim que funciona: M = fread(A, S, N, F); O fread() vai tentar ler N elementos, cada um com S bytes, de F e mete-los em A. O valor devolvido (M) tem que ser entre 0 (zero) e N. Se correr tudo bem, vai ser N. Se M < N isso quer dizer que o fread() nao conseguiu ler tudo o que lhe foi pedido. A razao de nao ter lido tudo pode ser por erro (falha no disco, falha na rede, tirar a disquete, ...) ou por falta de dados. Nao é possivel determinar, apenas com o fread(), a razao da falha ... e, em programas "basicos", nem sequer é preciso. Portanto, usa o fread() testando com o numero de elementos pedidos while (fread(&numeros, sizeof(int), 1, fpointer) == 1) { /* ... */ } Neste caso especifico, o fread() ou devolve 1 (indicando que esta tudo bem) ou 0 (indicando que nao esta tudo bem). Ao devolver 0 acabas o ciclo. Se te interessar fazer alguma coisa diferente consoante o fread() tenha falhado por falha no disco ou por falta de dados podes usar feof() ou ferror() e prosseguir com a gestao de erros a partir dai. 1 Report What have you tried? Não respondo a dúvidas por PM A minha bola de cristal está para compor; deve ficar pronta para a semana. Torna os teus tópicos mais atractivos e legíveis usando a tag CODE para colorir o código!
PsySc0rpi0n Posted April 25, 2013 at 03:22 PM Author Report #504799 Posted April 25, 2013 at 03:22 PM (edited) Ok... Thanks... Esta explicação é exemplar... Muito obrigado! Outro pormenor é que no while dos números pares, ele não está a respeitar o \t ... Haverá razão para isso? Edited April 25, 2013 at 03:28 PM by PsySc0rpi0n Kurt Cobain - Grunge misses you Nissan GT-R - beast killer
pmg Posted April 25, 2013 at 03:36 PM Report #504802 Posted April 25, 2013 at 03:36 PM (edited) Este while? while (!feof(fpares)) { fread(&numpares, sizeof(int), 1, fpares); printf ("\nNúmeros Pares:%d\t", numpares); } Estas, talvez, a ignorar o efeito do \n? Sugestao: en vez de pores o \n no principio (ou no meio) dos printfs, mete-o no fim. Edited April 25, 2013 at 03:37 PM by pmg What have you tried? Não respondo a dúvidas por PM A minha bola de cristal está para compor; deve ficar pronta para a semana. Torna os teus tópicos mais atractivos e legíveis usando a tag CODE para colorir o código!
PsySc0rpi0n Posted April 25, 2013 at 03:49 PM Author Report #504806 Posted April 25, 2013 at 03:49 PM (edited) Não percebi a tua pergunta mas o que eu pretendia era colocar um espaço antes do primeiro printf dos pares e um antes do primeiro printf dos ímpares para separar a lista dos pares dos ímpares... O code neste momento está assim: #include <stdio.h> #include <stdlib.h> void GravaFicheiro(FILE *pfile, int numeros) { fwrite (&numeros, sizeof(int), 1, pfile); } void GravaPar(FILE *pfpar, int numeros) { fwrite (&numeros, sizeof(int), 1, pfpar); } void GravaImpar(FILE *pfileimpar, int numeros) { fwrite (&numeros, sizeof(int), 1, pfileimpar); } void LeParesImpares(FILE *fpares, FILE *fimpares) { int numpares, numimpares; rewind(fpares); rewind(fimpares); while((fread(&numpares, sizeof(int), 1, fpares)) == 1) printf ("Números Pares:%d\t", numpares); putchar('\n'); while((fread(&numimpares, sizeof(int), 1, fimpares)) == 1) printf("Números Impares:%d\t", numimpares); putchar('\n'); } int main(void) { int numeros; FILE *pfile, *pfilepar, *pfileimpar; if ((pfile = fopen ("num.dat", "w+b")) == NULL) { printf("Erro a abrir o ficheiro!\n"); exit(0); } if ((pfilepar = fopen ("par.dat", "w+b")) == NULL) { printf("Erro a abrir o ficheiro!\n"); exit(1); } if ((pfileimpar = fopen ("impar.dat", "w+b"))== NULL) { printf("Erro ao abrir ficheiro!\n"); exit(2); } do { printf ("Introduza números inteiros:\n"); printf ("Introduza um número negativo para sair:\n"); scanf ("%d", &numeros); if(numeros >= 0){ GravaFicheiro (pfile, numeros); if(!(numeros%2)) GravaPar (pfilepar, numeros); else GravaImpar (pfileimpar, numeros); } } while(numeros >= 0); printf("Posição do filepointer par %ld\n", ftell(pfilepar)); printf("Posição do filepointer impar %ld\n", ftell(pfileimpar)); printf("Posição do filepointer %ld\n", ftell(pfile)); LeParesImpares(pfilepar, pfileimpar); fclose(pfile); fclose(pfilepar); fclose(pfileimpar); getchar(); return 0; } Edited April 25, 2013 at 03:50 PM by PsySc0rpi0n Kurt Cobain - Grunge misses you Nissan GT-R - beast killer
pmg Posted April 25, 2013 at 04:33 PM Report #504809 Posted April 25, 2013 at 04:33 PM Cada putchar('\n') do teu codigo acime termina a linha onde é colocado. Por exemplo "Números Pares:12\tNúmeros Pares:42\t" depois do putchar fica assim "Números Pares:12\tNúmeros Pares:42\t\n" e os numeros impares vem logo a seguir "Números Pares:12\tNúmeros Pares:42\t\nNúmeros Impares:13\t" Em vez de um '\n' mete 2 "Números Pares:12\tNúmeros Pares:42\t\n\nNúmeros Impares:13\t" /* ------------------------------ -> ^^^^ 2 ENTERs */ What have you tried? Não respondo a dúvidas por PM A minha bola de cristal está para compor; deve ficar pronta para a semana. Torna os teus tópicos mais atractivos e legíveis usando a tag CODE para colorir o código!
PsySc0rpi0n Posted April 25, 2013 at 04:42 PM Author Report #504812 Posted April 25, 2013 at 04:42 PM Queres dizer, repetir o puchar('\n'); em cada um dos sítios onde o tenho agora? Kurt Cobain - Grunge misses you Nissan GT-R - beast killer
pmg Posted April 25, 2013 at 04:44 PM Report #504813 Posted April 25, 2013 at 04:44 PM Queres dizer, repetir o puchar('\n'); em cada um dos sítios onde o tenho agora? Experimenta e tira as tuas conclusoes. Acho que nao vai ser bem o que pretendes, mas depressa adaptas o programa para o que queres 🙂 What have you tried? Não respondo a dúvidas por PM A minha bola de cristal está para compor; deve ficar pronta para a semana. Torna os teus tópicos mais atractivos e legíveis usando a tag CODE para colorir o código!
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