Jump to content
WolfmanZ

Duvida em C

Recommended Posts

WolfmanZ

O trabalho consiste em: comparar as strings e ver contar os caracteres diferentes e se for igual a n imprime e depois volta a meter diferentes=0 e passa para a linha seguinte ate encontrar n_top!

O programa nao me está a fazer bem a soma dos diferentes chega a um e passa logo ao if e nao queria isso!

 while(n_top != counter || n<tam_str){
     n++;
        for(i=0; i<linhas-1; i++){
                 for(k=0; k<2048-tam_str; k++)
                 {
                          for(j=0; j<tam_str; j++){
                                 if(x[i].assinatura[k+j] != asi_bio[j]){
                                                         diferentes++;
                                 }
                          }
                          if(diferentes==n){
                          cont2++;
                          diferentes=0;
                          if(cont2 < n_top-cont+1){
                          printf("\n%s\t ( Distancia %d )\t %d\n",x[i].bi,n,i+1); 
                          i++;
                          }
                 }                                 
        }
    counter=cont+cont2;
    }   

Share this post


Link to post
Share on other sites
Localhost

Bem vindo ao p@p. Provavelmente não estás acostumado às regras do fórum mas antes de mais nada, atenção aos títulos dos tópicos. Títulos como "Ajuda urgente", etc. não são os mais apropriados.

Em relação ao problema, podias explicar um bocado melhor? É que não percebi muito bem qual é o objectivo do programa nem a dúvida em si.


here since 2009

Share this post


Link to post
Share on other sites
Localhost

Ou seja, falta-te practicamente o trabalho todo.

Primeiro tens que pedir o número N. Depois na minha opinião o melhor algoritmo é guardares todas as strings num vector e depois calculares a distância entre a string dada como input e todas essas que já guardaste. Depois disso vais retirando o mínimo dessas distâncias e imprimindo as strings mais próximas. Depois ainda tens que pensar na nota que eles dão de ter que se procurar em substrings mas se conseguires implementar a primeira parte a nota não é muito difícil.


here since 2009

Share this post


Link to post
Share on other sites
WolfmanZ

Tipo eu ja tenho tudo em da pesquisa so falta a parte em que as distancias sao maiores que 0!

as distancias 0 procurei com a funçao strstr!

Share this post


Link to post
Share on other sites
Localhost

Percorres a string caracter a caracter (até encontrares o '\0') e a cada passo verificas se o elemento que estás a percorrer é diferente do que o elemento (na mesma posição) da string dada como input. Se for incrementas um contador.

for (i = 0; code[i]; i++)
   if (code[i] != input[i])
     cur_counter++;


here since 2009

Share this post


Link to post
Share on other sites
WolfmanZ

Percorres a string caracter a caracter (até encontrares o '\0') e a cada passo verificas se o elemento que estás a percorrer é diferente do que o elemento (na mesma posição) da string dada como input. Se for incrementas um contador.

for (i = 0; code[i]; i++)
   if (code[i] != input[i])
     cur_counter++;

isso é o que tenho no codigo em cima!

Share this post


Link to post
Share on other sites
Localhost

Mas depois acho que estás a utilizar mal a variável diferentes. Metes para lá uma variável chamada n que não tem nada a ver com a variável diferentes. Tenta a solução que te disse que assim evitas confusões e o código fica mais limpo. Primeiro calculas a distância entre a string dada e todas as strings que estão no ficheiro e guardas essa distância. Convinha até utilizares uma estrutura para armazenares tudo.


here since 2009

Share this post


Link to post
Share on other sites
WolfmanZ

a variavel n conta os numero de vezes que executa o ciclo while para que é para depois comparar com os diferentes! 

Nao  querendo abusar de ti nao poderias "fazer.me" essa parte é que é sofalta isso e é so ate amanha eu envia.te o que tenho e tu vias mais ao menos!

Share this post


Link to post
Share on other sites
Localhost

Aqui não se fazem trabalhos. Posso-te dar mais ou menos os passos mas te garanto que eu nem ninguém vai fazer isso por ti.

* Lês N;

* Lês a string (vou-lhe chamar S);

* Lês todas as strings do ficheiro para um vector (vou-lhes chamar S');

* Determinas a distância entre S e S'i (para i = 0 até ao final do ficheiro) e guardas num vector;

* Vais retirando o mínimo das distâncias e imprimes a string respectiva no vector de strings.


here since 2009

Share this post


Link to post
Share on other sites
WolfmanZ

enviei.te uma PM com o codigo todo vê e diz.me o que alteravas!

P.S é que nao percebi o que dizes-te

Share this post


Link to post
Share on other sites
thoga31

enviei.te uma PM com o codigo todo vê e diz.me o que alteravas!

P.S é que nao percebi o que dizes-te

Porquê em PM?


Knowledge is free!

Share this post


Link to post
Share on other sites
WolfmanZ

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

typedef struct{
        char bi[9];
        char assinatura[2049];
}PESSOA;


void menu1(PESSOA *x);
void leitura_Ficheiro(PESSOA *x);
void menu2(PESSOA *x, unsigned long int linhas, unsigned long int tam_file);
void pesquisa(PESSOA *x, unsigned long int linhas, unsigned long int tam_file);

int main()
{
    PESSOA *x = NULL;
    menu1(x);
    scanf(" ");
}

void menu1(PESSOA *x)
{
     int i,escolha;
     for(i=0;i<40;i++)
                      printf("*");
                      printf("\n");
                      printf("\nMENU-DANGER_DB\n\n");
     for(i=0;i<40;i++)
                      printf("*");
                      printf("\n");
                      printf("\n1:Leitura de ficheiro\n\n2:Exit\n\n");
     for(i=0;i<40;i++)
                      printf("*");
                      printf("\n");
     
     printf("\nIntroduza o valor correspondente ao que quer fazer no menu:\n\n");
     scanf("%d",&escolha);
     
     switch(escolha){
                     
     case 1:
		leitura_Ficheiro(x);
		break;
     case 2:
		break;
     default:
		printf("\nOpcao inexistente!\n\n");
		menu1(x);
   			break;
     }     
}


void leitura_Ficheiro(PESSOA *x)
{
     FILE *fp;
 char path[200+1];
     unsigned long int tam_file, linhas=0, line=0;
 int i=0;


puts("\nIntroduza o Caminho para o Ficheiro:\n");
scanf("%s", path);

/*Abrir Ficheiro */
fp = fopen(path, "r");

/* Verifica se a abretura foi feita com sucesso */

if (fp == NULL)
    printf("\nImpossivel abrir o ficheiro %s !!\n",path);
else
{
    printf("\nFicheiro %s aberto com sucesso!!!\n\n",path);
    
    
    if(!fseek(fp,0,SEEK_END)){
		tam_file = ftell(fp);
            }

	else{
		printf("\nErro a calcular tamanho do ficheiro...\n\n");
        }  

	linhas=tam_file/2058;	
              
	x = (PESSOA *) malloc(linhas*sizeof(PESSOA));

	if(x == NULL)
		printf("\nErro de memoria...\n\n");

	else{
		rewind(fp);
  
        while(!feof(fp)){
                          fgets(x[line].bi, 9, fp);
                          fgetc(fp);
                          fgets(x[line].assinatura, 2049,fp);
                          fgetc(fp);
                          line++;
                          }   
            
            fclose(fp);   
        }
            menu2(x, line, tam_file);			
		free(x);
	}
}

void menu2(PESSOA *x, unsigned long int linhas, unsigned long int tam_file)
{     
     int i,escolha;
     for(i=0;i<40;i++)
                      printf("*");
                      printf("\n");
                      printf("\nMENU-DANGER_DB\n\n");
     for(i=0;i<40;i++)
                      printf("*");
                      printf("\n");
                      printf("\n1:Leitura de ficheiro\n\n2:Pesquisa de Assinatura Biométrica\n\n3:Exit\n\n");
     for(i=0;i<40;i++)
                      printf("*");
                      printf("\n");
     
     printf("\nIntroduza o valor correspondente ao que quer fazer no menu:\n\n");
     scanf("%d",&escolha);
     
     switch(escolha){
     case 1:
		leitura_Ficheiro(x);
		break;
     case 2:
		pesquisa(x,linhas, tam_file);
		break;
     case 3:
		break;
     default:
		printf("\nOpcao inexistente!\n\n");
		menu2(x,linhas, tam_file);
   			break;
     }     
}

void pesquisa(PESSOA *x, unsigned long int linhas, unsigned long int tam_file)
{
     int n_top, cont=0, cont2=0, counter=0, i, tam_str, j=0, k, n=0;
     char asi_bio[2049], ass[2049];
     int diferentes = 0, dif=0;
     
typedef struct{
        int lines[];
}RESULTADO; 
     
     RESULTADO y;
     fflush(stdin);

 printf("\nQual o n numeros de n-matches:\n");
     scanf("%d", &n_top);
     printf("\nIntroduza um valor:\n");
     scanf("%s", asi_bio);

     for(i=0; i<linhas-1; i++){
     if(strstr(x[i].assinatura,asi_bio)){
     cont++;
     if(cont!=n_top)
     printf("\n %s \t(Distâncias 0)\t%d\n",x[i].bi,i+1);
     else break;
     }
     }
     
     printf("\n%d\n\n",cont);
     
     tam_str=strlen(asi_bio);
     printf("%d",tam_str);
     
     while(n_top != counter || n<tam_str){
     n++;
        for(i=0; i<linhas-1; i++){
                 for(k=0; k<2048-tam_str; k++)
                 {
                          for(j=0; j<tam_str; j++){
                                 if(x[i].assinatura[k+j] != asi_bio[j]){
                                                         diferentes++;
                                 }
                          if(diferentes==n){
                          cont2++;
                          diferentes=0;
                          if(cont2 < n_top-cont+1){
                          printf("\n%s\t ( Distancia %d )\t %d\n",x[i].bi,n,i+1); 
                          i++;
                          }
                          }
                          }
                 }                                 
        }
    counter=cont+cont2;
    }   
    
    printf("\n%d",counter);
                 
     free(x);
}

Isto é como tenho mas preciso de ajuda para fazer a parte da pesquisa por distancias maiores que 0 ! se me podesses mostrar como fazias essa parte agradecia!

Share this post


Link to post
Share on other sites
Diutsu

Tens portanto de fazer 2 coisas, na pesquisa:

- Determinar a distancia minima de cada entrada em relação ao input.

Isto é +- o ciclo for que tens ali com o k=0; k < 2048-tam_str: k++, só que queres determinar a menor "distancia" dentro desta entrada, ou seja tens de usar um contador temporário para determinares a distancia da substring que estás a comparar, enquanto mantens outro com a menor distancia encontrada para a entrada actual. algo como isto :

/* might not compile */
int min_dist(char *entrada, char *teste){
int i, j, dist_act, int min_dist;
int size_of_teste = strlen(teste);
for(i=0; i < 2048-size_of_teste; i ++){ /* todas as substrings possíveis */
dist_act=0; /* contador temporário*/
for(j=0; j < size_of_teste; j++) /* comparar cada substring com a string de teste */
if(entrada[i+j] != teste[j]) dist_act++;
if(dist_act < min_dist) min_dist = dist_act;
}
return min_dist;

não te precisas de preocupar com o caso de a diferença ser 0.

- Determinar quais as entradas que têm as menores distancias, para as poderes apresentar.

Se utilizares uma estrutura (com o BI, a assinatura biométrica, e um campo para a distancia) para guardares cada entrada do input, torna-se relativamente fácil, porque após determinares a "distancia" de cada entrada, é só ordenares as estruturas (qsort do C serve, ou então implementas tu um algoritmo de pesquisa) pela distancia e imprimires as "n" primeiras. Existem alternativas, como é obvio.

Usar a min_dist() é uma boa ideia, facilita a leitura do código.


XX SINFO - Semana Informática

Share this post


Link to post
Share on other sites
Diutsu

Eu diria que o problema no teu código, é estares a misturar a utilização do n com a determinação da menor distancia numa entrada, com a determinação do top-n.

Divide&Conquer.


XX SINFO - Semana Informática

Share this post


Link to post
Share on other sites
WolfmanZ

Nao me consegues fazer essa parte do codigo/pesquisa com base no meu para eu perceber?

Share this post


Link to post
Share on other sites
Diutsu

Qual parte? a de determinar a "distancia" minima para uma entrada? Então é só substituires o for que eu indiquei pela chamada à função com os argumentos que queres e guardares o return num novo campo int distancia que adicionas na estrutura PESSOA, e inicializas, p.e a 2048 ("distancia" máxima).

Ou é a de determinar quais as entradas que queres apresentar?

a) arranjas um maneira de ordenar as entradas (como tens um vector de estruturas, nao recomendo mt, embora seja possivel, o ideial neste caso era teres um vector de ponteiros para estruturas). e dás as n primeiras

:thumbsup: crias um 2º vector (int*) tamanho n, inicializas todas as posições a 0, e vais preenchendo o vector (vec_dist) com os indices de x correspondentes às entradas que têm a menor distancia:

para cada entrada percorres vec_dist
- se distancia_entrada < x[vec_dist[i]].distancia
então todas as posições de vec_dist  superiores a i avançam 1 posição e vec_dist[i] = posicao_entrada

 


XX SINFO - Semana Informática

Share this post


Link to post
Share on other sites
KTachyon

Nas regras do fórum está uma que diz que não se resolvem trabalhos. O objectivo é ajudar, não é fazer.


“There are two ways of constructing a software design: One way is to make it so simple that there are obviously no deficiencies, and the other way is to make it so complicated that there are no obvious deficiencies. The first method is far more difficult.”

-- Tony Hoare

Share this post


Link to post
Share on other sites
WolfmanZ

int min_dist(char *entrada, char *teste){
int i, j, dist_act, int min_dist;
int size_of_teste = strlen(teste);
for(i=0; i < 2048-size_of_teste; i ++){ /* todas as substrings possíveis */
dist_act=0; /* contador temporário*/
for(j=0; j < size_of_teste; j++) /* comparar cada substring com a string de teste */
if(entrada[i+j] != teste[j]) dist_act++;
if(dist_act < min_dist) min_dist = dist_act;
}
return min_dist;

tipo no meu caso ficava assim:

int min_dist(char *x, char *asi_bio, int linhas){
int i, j,k, dist_act, int min_dist;
int size_of_teste = strlen(asi_bio);
for(k=0; k<linhas-1; k++)
for(i=0; i < 2048-size_of_teste; i ++){ /* todas as substrings possíveis */
dist_act=0; /* contador temporário*/
for(j=0; j < size_of_teste; j++) /* comparar cada substring com a string de teste */
if(entrada[i+j] != teste[j]) dist_act++;
if(dist_act < min_dist) min_dist = dist_act;
}
return min_dist

certo?

Share this post


Link to post
Share on other sites
thoga31

O @Baderous não pode estar sempre a colocar-te as tags do GeSHi. É altura de seres tu a colocá-las:

[ code = c ]  [ /code ]  (sem qualquer espaço)

Assim coloca a cor relacionado com a linguagem C.


Knowledge is free!

Share this post


Link to post
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

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