Jump to content

Ciclo infinito


fo_11
 Share

Recommended Posts

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);
}
Link to comment
Share on other sites

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

Link to comment
Share on other sites

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);
}
Link to comment
Share on other sites

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

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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

Link to comment
Share on other sites

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

Link to comment
Share on other sites

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';
}
Link to comment
Share on other sites

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

Link to comment
Share on other sites

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

Link to comment
Share on other sites

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';
}
Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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?

Link to comment
Share on other sites

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?

Link to comment
Share on other sites

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

Link to comment
Share on other sites

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 account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
×
  • Create New...

Important Information

By using this site you accept our Terms of Use and Privacy Policy. We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.