Pagina 1 di 3 1 2 3 ultimoultimo
Visualizzazione dei risultati da 1 a 10 su 21
  1. #1
    Utente di HTML.it
    Registrato dal
    Feb 2006
    Messaggi
    75

    [C] Algoritmo di ricerca in un file

    Salve, dovrei scrivere una funzione che ha come parametri un file e una stringa. Legge il file e ritorna il numero di occorrenze della stringa nel file. La particolarità è che in una stessa parola la stringa va contata al più una volta.
    Ad esempio se il file di testo ha il seguente contenuto:
    codice:
     AbcdAb
     Abd
    e la stringa da ricercare è "ab", la funzione deve ritornare 2.
    Qualcuno può aiutarmi ? Grazie

  2. #2
    Ci sono diversi algoritmi, il piu semplice è quello a forza bruta ma è il meno elegante. Leggi qui http://www.dit.unitn.it/~montreso/as...ngmatching.pdf

  3. #3
    Utente di HTML.it
    Registrato dal
    Feb 2006
    Messaggi
    75
    si ok , ma come si implementa tutto ciò in C ?

  4. #4
    Utente di HTML.it
    Registrato dal
    Feb 2006
    Messaggi
    75
    Nessuno mi può dare una mano

  5. #5
    Ok ma il difficile non è l'implementazione, il difficile è capire l'algoritmo.

    una possibile implementazione dell'algoritmo a forza bruta.. con la variante di saltare a fine riga dopo ogni match

    Codice PHP:
    #include <stdio.h>
    #define SKIP_LINE(in) while (!feof(in) && fgetc(in) != '\n');

    int ContaOccorrenze(FILE in, const char match) {
        
    //algoritmo a forza bruta
        
    int nocc=0;
        const 
    char pmatch match;
        
        while (!
    feof(in))    {        
            if (*
    pmatch == '\\0'
            {
                ++
    nocc;
                
    pmatch match;
                
    SKIP_LINE(in)
            }
            
            if (
    fgetc(in) == *pmatch)
                
    pmatch++;
            else
                
    pmatch match;
        }
        return 
    nocc;



  6. #6
    Utente di HTML.it
    Registrato dal
    Feb 2006
    Messaggi
    75
    Scusami, mi pare di capire che questa funzione incrementa il contatore "nocc" ogniqualvolta trova una nuova riga, mentre quando è verificata la condizione (fgetc(in) == *pmatch) non lo fa...
    l'ho testato ed effettivamente mi ritorna il numero delle righe presenti nel file letto.
    chiedo delucidazioni...

  7. #7
    Con piacere: in realta controlla che *pmatch='\0' ovvero che tutti i caratteri in input abbiano matchato la stringa match.

    Comunque ho trovato un errore leggendo la tua domanda...

    Quando trova un no-match deve arretrare il file di input di N posizioni e riiniziare a leggere da li ti invio la versione correggiuta tra 20 secondi.

  8. #8
    Ciao,

    Una delle tecniche più veloci consiste nell'utilizzare un automa a stati finiti(che non comporta backtracking) e un albero di ricerca binaria.
    Il codice seguente effettua una ricerca nel file "romanzo.txt" che contiene il romanzo "I Viceré" di Federico De Roberto e che puoi scaricare da qui:

    http://www.liberliber.it/biblioteca/...erto/index.htm

    e trova le dieci parole (con lunghezza > 10 caratteri) più frequenti.

    Sulla mia macchina:
    codice:
    AMD Athlon(tm) 64 X2
    Dual Core Processor 4800+
    2.50 GHz
    896 MB di RAM
    Ottengo questi tempi:


    Questo è il codice:
    codice:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <malloc.h>
    #include <time.h>
    #include <ctype.h>
    
    #define MAX_STACK 1024
    
    typedef enum tagStati
    {
    	S_ERROR_OPEN_FILE = -2,
    	S_ERROR = -1,
    	S0 = 0,
    	S1
    } Stati;
    
    typedef struct tagTree
    {
    	char *parola;
    	int count;
    	struct tagTree *left;
    	struct tagTree *right;
    } Tree;
    
    typedef struct tagList
    {
    	char *parola;
    	int count;
    	struct tagList *next;
    } List;
    
    Tree *NewNode(char *info);
    Tree *InsertNode(Tree *node, char *key);
    void FreeTree(Tree *head);
    
    List *ListNewNode(char *info, int count);
    void ListInsertNode(List **head, List *newNode);
    void FreeList(List **head);
    
    void InOrder(Tree *head, List **a, int nMax);
    
    Stati DFA(char *szFileName, Tree **pTree);
    
    List *ListNewNode(char *info, int count)
    {
    	List *r;
    	int len;
    
    	r = (List *) malloc(sizeof(List));
    
    	if( !r )
    	{
    		printf("Memoria insufficiente.\n");
    		return NULL;
    	}
    
    	len = strlen(info);
    	r->parola = (char*)malloc(len*sizeof(char) + 1);
    	if( !r->parola )
    	{
    		printf("Memoria insufficiente.\n");
    		return NULL;
    	}
    
    	strcpy(r->parola, info);
    	r->count = count;
    	r->next = NULL;
    
    	return r;
    }
    
    void ListInsertNode(List **head, List *newNode)
    {
    	List *current = *head;
    
    	if ( *head == NULL ||
    		(*head)->count <= newNode->count )
    	{
    		newNode->next = *head;
    		*head = newNode;
    	}
    	else
    	{
    		while ( current->next != NULL &&
    				current->next->count > newNode->count )
    		{
    			current = current->next;
    		}
    		newNode->next = current->next;
    		current->next = newNode;
    	}
    }
    
    void FreeList(List** head)
    {
    	List *current = *head;
    	List *next;
    
    	while ( current != NULL )
    	{
    		next = current->next;
    		free(current->parola);
    		free(current);
    		current = next;
    	}
    	
    	*head = NULL;
    }
    
    Tree *NewNode(char* info)
    {
    	Tree *r;
    	int len;
    
    	r = (Tree *) malloc(sizeof(Tree));
    
    	if( !r )
    	{
    		printf("Memoria insufficiente.\n");
    		return NULL;
    	}
    
    	len = strlen(info);
    	r->parola = (char*)malloc(len*sizeof(char) + 1);
    	if( !r->parola )
    	{
    		printf("Memoria insufficiente.\n");
    		return NULL;
    	}
    
    	strcpy(r->parola, info);
    	r->count = 1;
    	r->left = NULL;
    	r->right = NULL;
    
    	return r;
    }
    
    Tree *InsertNode(Tree *node, char *key)
    {
    	Tree *pRadice = NULL;
    	int nRes;
    
    	if( !node )
    	{
    		node = NewNode(key);
    		return node;
    	}
    
    	pRadice = node;
    	
    	while( 1 )
    	{
    		nRes = strcmp(key, node->parola);
    
    		if ( nRes < 0 )
    		{
    			if ( !node->left )
    			{
    				node->left = NewNode(key);
    				break;
    			}
    			node = node->left;
    		}
    		else if ( nRes > 0 )
    		{
    			if ( !node->right )
    			{
    				node->right = NewNode(key);
    				break;
    			}
    			node = node->right;
    		}
    		else // Trovato
    		{
    			node->count++;
    			break;
    		}
    	}
    
    	node = pRadice;
    
    	return node;
    }
    
    void FreeTree(Tree *head)
    {
    	Tree *temp1, *temp2;
    
    	Tree *stack[MAX_STACK];
    	int top;
    
    	top = 0;
     
    	if ( !head )
    		return;
    
    	temp1 = temp2 = head;
    
    	while ( temp1 != NULL )
    	{
    		for(; temp1->left != NULL; temp1 = temp1->left)
    			stack[top++] = temp1;
    
    		while ( (temp1 != NULL) && (temp1->right == NULL || temp1->right == temp2) )
    		{
    			temp2 = temp1;
    			free(temp2->parola);
    			free(temp2);
    			if ( top == 0 )
    				return;
    			temp1 = stack[--top];
    		}
    
    		stack[top++] = temp1;
    		temp1 = temp1->right;
    	}
    }
    
    void InOrder(Tree *head, List **a, int nMax)
    {
    	int k = 0;
    	Tree *temp;
    
    	List *listNode;
    	List *tempListNode;
    	List *tempListNodePrev;
    
    	Tree *stack[MAX_STACK];
    	int top;
    	top = -1;
    
    	if ( !head )
    		return;
    
    	temp = head;
    
    	while ( 1 )
    	{
    		if ( temp != NULL )
    		{
    			if ( top < MAX_STACK ) 
    			{
    				stack[++top] = temp; // Push
    				temp = temp->left;
    			}
    			else
    			{
    				printf("Errore: lo stack e' pieno.\n");
    				return;
    			}
    		}
    		else
    		{
    			if ( top >= 0 )
    			{
    				temp = stack[top--]; // Pop 
    
    				if ( k < nMax )
    				{
    					listNode = ListNewNode(temp->parola, temp->count);
    					ListInsertNode(a, listNode);
    				}
    				else
    				{
    					listNode = ListNewNode(temp->parola, temp->count);
    					ListInsertNode(a, listNode);
    
    					tempListNode = tempListNodePrev = *a;
    					while ( tempListNode->next != NULL )
    					{
    						tempListNodePrev = tempListNode;
    						tempListNode = tempListNode->next;
    					}
    					tempListNodePrev->next = NULL;
    					free(tempListNode);					
    				}
    
    				k++;
    
    				temp = temp->right;
    			}
    			else
    			{
    				break;
    			}
    		}
    	}
    }
    
    Stati DFA(char *szFileName, Tree **pTree)
    {
    	Stati stato = S0;
    	FILE *fp;
    	char *buffer;
    	char szTemp[256];
    	char c;
    	int numread = 0;
    	int k = 0;
    	int x = 0;
    	int dimFile = 0;
    	fpos_t pos;
    
    	fp = fopen(szFileName, "rb");
    	if ( fp == NULL )
    		return S_ERROR_OPEN_FILE;
    
    	if ( fseek(fp, 0, SEEK_END) )
    		return -1;
    
    	if( fgetpos(fp, &pos) != 0 )
    		return -1;
    
    	dimFile = (int)pos;
    
    	if ( fseek(fp, 0, SEEK_SET) )
    		return -1;
    
    	buffer = (char*)malloc(sizeof(char)*dimFile + 1);
    	if ( !buffer )
    	{
    		printf("Errore nell'allocazione della memoria.");
    		fclose(fp);
    		return -1;
    	}
    
    	numread = fread(buffer,
    					sizeof(char),
    					dimFile,
    					fp);
    	if ( numread != dimFile )
    	{
    		fclose(fp);
    		return -1;
    	}
    	*(buffer + numread + 1) = '\0';
    
    	while ( k < dimFile )
    	{
    		c = *(buffer + k++);
    
    		switch (stato)
    		{
    		case S0:
    			if ( isalnum(c) || c == 'è' || c == 'é' || c == 'ì' || c == 'à' || c == 'ù' || c == 'ò' )
    			{
    				*(szTemp + x++) = c;
    				stato = S1;
    			}
    			else
    			{
    				stato = S0;
    			}
    			break;
    
    		case S1:
    			if ( isalnum(c) || c == 'è' || c == 'é' || c == 'ì' || c == 'à' || c == 'ù' || c == 'ò' )
    			{
    				*(szTemp + x++) = c;
    				stato = S1;
    			}
    			else
    			{
    				*(szTemp + x) = '\0';
    				x = 0;
    
    				if ( strlen(szTemp) > 10 )
    				{
    					*pTree = InsertNode(*pTree, szTemp);
    					if ( *pTree == NULL )
    						return S_ERROR;
    				}
    
    				stato = S0;
    			}
    			break;
    		}
    	}
    
    	free(buffer);
    
    	if ( fp )
    		fclose(fp);
    
    	return stato;
    }
    
    int main()
    {
    	Tree * p = NULL;
    	List *a = NULL;
    	List *t = NULL;
    	Stati stato;
    
    	clock_t c_start, c_end;
    
    	char *szNomeFile = "romanzo.txt";
    	int nMax = 10;
    
    	c_start = clock();
    
    	stato = DFA(szNomeFile, &p);
    
    	if ( stato == S0 || stato == S1 )
    	{
    		InOrder(p, &a, nMax);
    
    		printf("\nParola -> Occorrenze\n\n");
    
    		t = a;
    		while ( t != NULL )
    		{
    			printf("%s -> %d\n", t->parola, t->count);
    			t = t->next;
    		}
    
    		FreeTree(p);
    		FreeList(&a);
    	}
    
    	c_end = clock();
    
    	printf("\n\nTempo impiegato -> %5.5f secondi\n", (double)(c_end - c_start) / CLOCKS_PER_SEC);
    
    	return 0;
    }
    É un pochino più lungo di quello proposto da Andrea ; è il prezzo da pagare per una soluzione efficiente(in termini di velocità di esecuzione).

    Puoi modificarlo facilmente per adattarlo al tuo problema(in modo, cioè, che trovi il numero di occorrenze della sola parola specificata in input).


  9. #9
    Utente di HTML.it
    Registrato dal
    Feb 2006
    Messaggi
    75
    Un pochino più lungo dici VVoVe: ??? A parte gli scherzi ti ringrazio moltissimo per lo sforzo. Ora vedrò di studiarmelo.

  10. #10
    Originariamente inviato da dexter86
    Un pochino più lungo dici VVoVe: ??? A parte gli scherzi ti ringrazio moltissimo per lo sforzo. Ora vedrò di studiarmelo.
    Si, leggermente

    questo è il codice modificato per il tuo problema:

    codice:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <malloc.h>
    #include <time.h>
    #include <ctype.h>
    
    typedef enum tagStati
    {
    	S_ERROR_OPEN_FILE = -2,
    	S_ERROR = -1,
    	S0 = 0,
    	S1
    } Stati;
    
    Stati DFA(char *szFileName, const char *parola, int *occorrenze)
    {
    	Stati stato = S0;
    	FILE *fp;
    	char *buffer;
    	char szTemp[256];
    	char c;
    	int numread = 0;
    	int k = 0;
    	int x = 0;
    	int dimFile = 0;
    	fpos_t pos;
    
    	*occorrenze = 0;
    
    	fp = fopen(szFileName, "rb");
    	if ( fp == NULL )
    		return S_ERROR_OPEN_FILE;
    
    	if ( fseek(fp, 0, SEEK_END) )
    		return -1;
    
    	if( fgetpos(fp, &pos) != 0 )
    		return -1;
    
    	dimFile = (int)pos;
    
    	if ( fseek(fp, 0, SEEK_SET) )
    		return -1;
    
    	buffer = (char*)malloc(sizeof(char)*dimFile + 1);
    	if ( !buffer )
    	{
    		printf("Errore nell'allocazione della memoria.");
    		fclose(fp);
    		return -1;
    	}
    
    	numread = fread(buffer,
    					sizeof(char),
    					dimFile,
    					fp);
    	if ( numread != dimFile )
    	{
    		fclose(fp);
    		return -1;
    	}
    	*(buffer + numread + 1) = '\0';
    
    	while ( k < dimFile )
    	{
    		c = *(buffer + k++);
    
    		switch (stato)
    		{
    		case S0:
    			if ( isalnum(c) || c == 'è' || c == 'é' || c == 'ì' || c == 'à' || c == 'ù' || c == 'ò' )
    			{
    				*(szTemp + x++) = c;
    				stato = S1;
    			}
    			else
    			{
    				stato = S0;
    			}
    			break;
    
    		case S1:
    			if ( isalnum(c) || c == 'è' || c == 'é' || c == 'ì' || c == 'à' || c == 'ù' || c == 'ò' )
    			{
    				*(szTemp + x++) = c;
    				stato = S1;
    			}
    			else
    			{
    				*(szTemp + x) = '\0';
    				x = 0;
    
    				if ( strcmp(szTemp, parola) == 0 )
    					(*occorrenze)++;
    
    				stato = S0;
    			}
    			break;
    		}
    	}
    
    	free(buffer);
    
    	if ( fp )
    		fclose(fp);
    
    	return stato;
    }
    
    int main()
    {
    	Stati stato;
    
    	clock_t c_start, c_end;
    
    	//char *parola = "principessa";
    	//char *parola = "primogenito";
    	char *parola = "rivoluzione";
    	int occorrenze;
    
    	char *szNomeFile = "romanzo.txt";
    
    	c_start = clock();
    
    	stato = DFA(szNomeFile, parola, &occorrenze);
    
    	if ( stato == S0 || stato == S1 )
    	{
    		if ( occorrenze > 0 )
    			printf("\n\nSono state trovate %d occorrenze della parola %s\n\n", occorrenze, parola);
    		else
    			printf("\n\nNessuna occorrenza della parola %s\n\n", parola);
    	}
    	else
    	{
    		printf("\nL'automa ha restituito un errore.\n");
    	}
    
    	c_end = clock();
    
    	printf("\n\nTempo impiegato -> %5.5f secondi\n", (double)(c_end - c_start) / CLOCKS_PER_SEC);
    
    	return 0;
    }
    È un pochino più corto rispetto al precedente in quanto non c'è bisogno di usare l'albero binario e le relative funzioni.
    Sulla mia macchina(provando sempre sul file indicato nel post precedente) vola: 0,00000 secondi

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2024 vBulletin Solutions, Inc. All rights reserved.