fo_11 Posted June 25, 2010 at 12:23 PM Report #336052 Posted June 25, 2010 at 12:23 PM O objectivo do programa será verificar o número de linhas diferentes entre dois ficheiros de texto diferentes e mostrar o numero das linhas que efectivamente são diferentes. O meu problema é no ciclo, nunca termina e não sei o que se passa. #include<stdio.h> #include<stdlib.h> #include<string.h> void CmpLines(FILE *fp_1, FILE *fp_2); int main() { FILE *fp_1,*fp_2; char nome[30]; //inserir nome do ficheiro printf("====1 Ficheiro===\n\n"); do{ printf("Nome ficheiro:"); fgets(nome,30,stdin); fp_1=fopen(nome,"r"); if(fp_1==NULL) printf("Such file does not exist!!!!!\n\n"); }while(fp_1==NULL); printf("\n\n\n====2 Ficheiro====\n\n"); do{ printf("Nome ficheiro:"); fgets(nome,30,stdin); fp_2=fopen(nome,"r"); if(fp_2==NULL) printf("Such file does not exist!!!\n\n"); }while(fp_2==NULL); CmpLines(fp_1,fp_2); fclose(fp_1); fclose(fp_2); system("pause"); return 0; } void CmpLines(FILE *fp_1, FILE *fp_2) { int dif=0,tot_line=0; char s_1[100],s_2[100]; //inicializar s_1,s_2 fgets(s_1,100,fp_1); fgets(s_2,100,fp_2); do{ ++tot_line; //contar o numero de linhas do maior ficheiro if(s_1!=NULL && s_2!=NULL) //só comparamos caso s_1 e s_2 não forem NULL {if(strcmp(s_1,s_2)!=0) {++dif; printf("Linhas diferente==>%d\n",tot_line); } } else //caso um dos ficheirios já tenha terminado as restantes linhas serão diferentes de certeza { ++dif; printf("Linhas diferentes==>%d\n",tot_line); } if(s_1!=NULL) //só efectuamos o fegets se ainda não terminamos a leitura do ficheiro fgets(s_1,100,fp_1); if(s_2!=NULL)//o mesmo ocorre neste linha fgets(s_2,100,fp_2); }while(s_1!=NULL || s_2!=NULL);//enquanto ainda nhão tivermos terminado os dois ficheiros o ciclo não termina, o problema acontece aqui ele nunca tem fim printf("TOTAL LINHAS DIFERENTES==>%d\n\n",tot_line); }
Localhost Posted June 25, 2010 at 12:42 PM Report #336056 Posted June 25, 2010 at 12:42 PM Essa tua função CompLines está confusa. Não precisas de tanta coisa para imprimir quantas linhas são diferentes. Vou-te pôr aqui algo que te pode ajudar: * Loop (enquanto não chegar ao fim de um dos ficheiros. * Ler linha dos dois ficheiros (fgets). * Comparar as duas strings que contêm as linhas (strcmp). * Se forem diferentes incrementar uma variável que vai contêr a quantidade de linhas diferentes. * Imprimir resultado. * Fim. Tens aí algumas verificações que me deixaram confuso. Só mais uma coisa, o loop pode contêr as funções fgets dentro. Algo deste género: while(fgets(...) && fgets(...)) O teu loop é infinito e podes ter a função fgets dentro de loop por esta razão: If the End-of-File is encountered and no characters have been read, the contents of str remain unchanged and a null pointer is returned. here since 2009
fo_11 Posted June 25, 2010 at 12:53 PM Author Report #336057 Posted June 25, 2010 at 12:53 PM Assim está correcto? void CmpLines(FILE *fp_1, FILE *fp_2) { int dif=0,tot_line=0; char s_1[100],s_2[100],*aux_1=NULL,*aux_2=NULL; //inicializar s_1,s_2 aux_1=fgets(s_1,100,fp_1); aux_2=fgets(s_2,100,fp_2); do{ ++tot_line; //contar o numero de linhas do maior ficheiro if(aux_1!=NULL && aux_2!=NULL) //só comparamos caso ainda não chegamos ao fim de nenhum ficheiro é que comparamos {if(strcmp(s_1,s_2)!=0) {++dif; printf("Linhas diferente==>%d\n",tot_line); } } else //caso um dos ficheirios já tenha terminado as restantes linhas serão diferentes de certeza { ++dif; printf("Linhas diferentes==>%d\n",tot_line); } }while( (aux_1=fgets(s_1,100,fp_1))!=NULL || (aux_2=fgets(s_2,100,fp_2))!=NULL);//enquanto ainda não tivermos terminado os dois ficheiros o ciclo não termina, o problema acontece aqui ele nunca tem fim printf("TOTAL LINHAS DIFERENTES==>%d\n\n",tot_line); }
Localhost Posted June 25, 2010 at 01:10 PM Report #336059 Posted June 25, 2010 at 01:10 PM Já experimentaste assim? Acho que isso não está correcto e que continuas a complicar. while(fgets(...) && fgets(...)) { if(!(strcmp(...))) dif++; } printf("Linhas diferentes: %i\n", dif); É mais ou menos isto, atenção que no while o operador lógico que se usa é o && e não o || porque com o || só quando ambas as condições se confirmarem é que ele vai parar. É uma confusão normal. here since 2009
fo_11 Posted June 25, 2010 at 01:56 PM Author Report #336072 Posted June 25, 2010 at 01:56 PM Mas assim não conta todas as linhas diferentes porque quando um dos ficheiros chega ao fim termina o ciclo (acontece quando um dos ficheiros é maior que outro) e só deve terminar quando chegar ao fim dos dois ficheiros.
Localhost Posted June 25, 2010 at 02:12 PM Report #336075 Posted June 25, 2010 at 02:12 PM Pensei que só querias saber o número de linhas diferentes enquanto existisse texto em ambos os ficheiros, sendo assim tens de modificar algumas coisas no código que te dei. Vou pôr aqui um esboço novamente: while(1) { if(ftell(fp_1) != SEEK_END) fgets(...); if(ftell(fp_2) != SEEK_END) fgets(...); if(ftell(fp_1) == SEEK_END) && ftell(fp_2) == SEEK_END) break; if(!(strcmp(...))) aux++; } printf("Linhas diferentes: %i\n", aux); Provavelmente conseguia fazer um código mais bonito mas foi só mesmo para perceberes. here since 2009
fo_11 Posted June 25, 2010 at 08:06 PM Author Report #336133 Posted June 25, 2010 at 08:06 PM okok, pensava que essas funções eram apenas para ficheiros binários... Obrigado pela ajuda penso que já entendi
fo_11 Posted June 25, 2010 at 08:42 PM Author Report #336137 Posted June 25, 2010 at 08:42 PM Não funciona assim... o ciclo continua infinito 😄
Localhost Posted June 25, 2010 at 08:53 PM Report #336138 Posted June 25, 2010 at 08:53 PM Desculpa, provavelmente estava distraído a escrever o post porque fiz ali algumas asneiras no exemplo. Vou-te deixar aqui algo completo para ver se entedes, este está mesmo a funcionar. 😄 #include <stdio.h> #include <string.h> #define SIZE 120 int main(void) { char str1[size],str2[size]; int aux=0; FILE *f1 = fopen("test1.in","r"); FILE *f2 = fopen("test2.in","r"); while(1) { if(!feof(f1)) fgets(str1,SIZE,f1); if(!feof(f2)) fgets(str2,SIZE,f2); if(feof(f1) && feof(f2)) break; if(strcmp(str1,str2)) aux++; } printf("Linhas diferentes: %i\n", aux); return 0; } here since 2009
fo_11 Posted June 26, 2010 at 12:08 AM Author Report #336162 Posted June 26, 2010 at 12:08 AM Já está a funcionar... Deixo aqui o código caso alguem da comunidade encontre a mesma dificuldade: void CmpLines(FILE *fp_1, FILE *fp_2) { int dif=0,tot_line=0; char s_1[100],s_2[100]; while(1) {if(!feof(fp_1)) { fgets(s_1,100,fp_1); StrClear(s_1); } if(!feof(fp_2)) { fgets(s_2,100,fp_2); StrClear(s_2); } if(feof(fp_1) && feof(fp_2)) { break; } ++tot_line; if(strcmp(s_1,s_2)) {++dif; printf("Linha diferente==>%d\n",tot_line); } } printf("TOTAL LINHAS DIFERENTES==>%d\n\n",dif); } void StrClear(char *s) { int i; for(i=0;i<strlen(s);i++) if(s[i]==10 ) //retirar line feed s[i]='\0'; }
Localhost Posted June 26, 2010 at 11:12 AM Report #336177 Posted June 26, 2010 at 11:12 AM Deixo aqui então uma versão melhorada e tu vês a que queres escolher. while(!feof(f1) || !feof(f2)) { fgets(s1,SIZE,f1); fgets(s2,SIZE,f2); if(strcmp(s1,s2)) dif++; } E mais uma vez estás a complicar, não percebo porque é que estás a limpar as strings (até podias usar a função memset) . E depois, mais por uma razão de estética, quando só tens uma instrução num bloco podes não abrir esse próprio bloco, mete um inline que é mais fácil e mais simples de ler. here since 2009
fo_11 Posted June 26, 2010 at 01:30 PM Author Report #336193 Posted June 26, 2010 at 01:30 PM Eu coloco limpar a string devido ao feed line que quando estamos na ultima linha do ficheiro nao existe. Deixo aqui um exemplo para perceberes: Ficheiro 1: Ficheiro 2: João João Carlos Carlos Miguel Miguel Santos Santos António Caso não limpe a string a linhas "Santos" no programa irá dar como diferente pois numa das strings fica "Santos" e na outra (do ficheiro maior) fica "Santos\n" o que faz com que o programa interprete como sendo duas strings distintas o que não é verdade. Em relação "quando só tens uma instrução num bloco podes não abrir esse próprio bloco, mete um inline que é mais fácil e mais simples de ler" eu sei que podemos não colocar {} quando só temos uma linha mas neste caso só coloquei para ter certezas que estava tudo correcto....
fo_11 Posted June 26, 2010 at 01:38 PM Author Report #336196 Posted June 26, 2010 at 01:38 PM Fiz alguns testes ao programa com diferentes escrita e cheguei à conclusão (que poderá não ser a mais correcta) que o código deverá ser o seguinte: void CmpLines(FILE *fp_1, FILE *fp_2) { int dif=0,tot_line=0; char s_1[100],s_2[100]; while(!feof(fp_1) || !feof(fp_2)) {if(!feof(fp_1)) { fgets(s_1,100,fp_1); StrClear(s_1); } if(!feof(fp_2)) { fgets(s_2,100,fp_2); StrClear(s_2); } ++tot_line; if(!feof(fp_1) && !feof(fp_2)) {if(strcmp(s_1,s_2)) {++dif; printf("Linha diferente==>%d\n",tot_line); } } else {++dif; printf("Linha diferente==>%d\n",tot_line); } } printf("TOTAL LINHAS DIFERENTES==>%d\n\n",dif); } void StrClear(char *s) { int i; for(i=0;i<strlen(s);i++) if(s[i]==10 ) //retirar line feed s[i]='\0'; }
Localhost Posted June 26, 2010 at 05:09 PM Report #336216 Posted June 26, 2010 at 05:09 PM Porquê ter whiles e ifs? here since 2009
fo_11 Posted June 26, 2010 at 06:37 PM Author Report #336226 Posted June 26, 2010 at 06:37 PM while==> para continuar a buscar linhas aos ficheiros até estes dois terminarem. if==> para apenas irmos buscar linhas se ainda não tivermos terminado o fciheiro outro if==>só interessa comparar se tiveres algo para comparar. Isto é, um ficheiro é maior que o outro, o mais pequeno termina, logo não faz sentido efectuar fgets a esse ficheiro e como já não vamos buscar mais linhas ficamos com falta de elementos para a comparação logo não nos interessa efectuar o strcmp.
Localhost Posted June 26, 2010 at 07:00 PM Report #336230 Posted June 26, 2010 at 07:00 PM Estás a complicar uma coisa que é simples mas se resulta, pronto. 😄 here since 2009
fo_11 Posted June 26, 2010 at 08:35 PM Author Report #336239 Posted June 26, 2010 at 08:35 PM Sim, funciona mas ainda não percebi como consigo simplificar o código. Já tentei fazer como disseste mas assim ficava com alguns bugs... Será que podias mostrar o código na integra da maneira que estás a pensar para ver onde estou a errar?
Localhost Posted June 26, 2010 at 08:54 PM Report #336241 Posted June 26, 2010 at 08:54 PM Ficava com alguns bugs? Que bugs? Tens de me dizer exactamente o que queres.. Imagina este dois ficheiros: Ficheiro 1: a b c Ficheiro 2: a b e d Aqui, a quantidade de linhas diferentes seria 3 ou 4? here since 2009
fo_11 Posted June 26, 2010 at 09:01 PM Author Report #336243 Posted June 26, 2010 at 09:01 PM Seria quatro... Basicamente o que quero efectivamente fazer é contar as linhas diferentes entre dois ficheiros. Caso um dos ficheiros seja maior existe de facto linhas diferentes pois num existem e no outro ficheiro não... Deu para passar a ideia?
Localhost Posted June 26, 2010 at 09:04 PM Report #336244 Posted June 26, 2010 at 09:04 PM Então não sei que bugs é que este código pode ter: while(!feof(f1) || !feof(f2)) { fgets(s1,SIZE,f1); fgets(s2,SIZE,f2); if(strcmp(s1,s2)) dif++; } Em cada passo no loop podias limpar as duas strings ficando assim: while(!feof(f1) || !feof(f2)) { memset(s1,'\0',SIZE-1); memset(s2,'\0',SIZE-1); fgets(s1,SIZE,f1); fgets(s2,SIZE,f2); if(strcmp(s1,s2)) dif++; } here since 2009
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