tirurir Temat założony przez niniejszego użytkownika |
Wyszukiwanie frazy w pliku - niepoprawny wynik [ROZWIĄZANY] » 2019-02-13 16:44:39 Od paru dni staram się naprawić błędy z programem który ma zliczać ilość wystąpienia danej frazy w tekście. Piszę w C. Program się kompiluje ale niestety wyniki które zwraca odbiegają od prawdy. Najpewniej popełniłem jakiś błąd logiczny i jestem ślepy na swój błąd. Wszelka pomoc bardzo mile widziana :) Jeśli ktoś zechciałby przetestować program u siebie pamiętajcie by utworzyć i wypełnić przykładowym tekstem plik file1.txt i edytować jego ścieżce w linijce nr35 "source = fopen("D:file1.txt", "r");". Kod starałem się pisać od zera tzn nie wykorzystując funkcji takich jak strstr. Znajduje się w nim kilka testów printf, być może okażą się pomocne. ===UWAGA: POPRAWNIE DZIAŁAJĄCY KOD ZNAJDUJE SIĘ NA DRUGIEJ STRONIE WĄTKU. PONIŻEJ POZOSTAWIAM WADLIWY KOD BEZ ZMIAN GDYBY KTOKOLWIEK CZYTAJĄC WĄTEK Z JAKIEGOŚ POWODU ZERKAŁ WŁAŚNIE DO NIEGO=== #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> #include <string.h>
int search( char arr[], int fileLen, char phrase[] ) { int i, matchCount = 0; int count = 0; for( i = 0; i <( fileLen - strlen( phrase ) + 1 ); i++ ) { if( arr[ i ] == phrase[ i % strlen( phrase ) ] ) { matchCount++; if( matchCount ==( strlen( phrase ) ) ) { count++; matchCount = 0; } } } return count; }
int main() { int count = 0; int i = 0; char buf[ 256 ]; char arr[ 512 ]; int fileLen = 512; int length; FILE * source; source = fopen( "D:file1.txt", "r" ); while( fgets( arr, fileLen, source ) != NULL ); printf( "what phrase should i look for?\n\n" ); scanf( "%s", buf ); length = strlen( buf ); printf( "Length of the typed phrase: %d,TEST\n", length ); char * phrase = malloc( sizeof( char ) *( length + 1 ) ); strncpy( phrase, buf, sizeof( phrase ) - 1 ); phrase[ sizeof( phrase ) - 1 ] = '\0'; printf( "You have typed: %s,TEST\n", phrase ); if( length <= fileLen ) { count = search( arr, fileLen, phrase ); printf( "I have found such phrase %d times - TEST\n", search( arr, fileLen, phrase ) ); printf( "I have found such phrase %d times.\n", count ); } else { printf( "The phrase you have entered is longer than number of characters in the source file. Phrase was found 0 times.\n" ); } fclose( source ); system( "pause" ); return 0; } |
|
pekfos |
» 2019-02-13 18:00:27 if( arr[ i ] == phrase[ i % strlen( phrase ) ] )
|
Ten warunek nie ma sensu. Powinno być arr[ i ] == phrase[ matchCount ] i do tego warunku powinno być else które skoryguje wartości i i matchCount. I nie wywołuj bez przerwy strlen(), to nie są darmowe rzeczy.. |
|
tirurir Temat założony przez niniejszego użytkownika |
» 2019-02-13 19:23:20 Racja, rozpisałem sobie poniżej i faktycznie warunek działał troszkę inaczej niż powinien. Przykład: arr = "tekstlorem" phrase = "tekst". długość phrase to 5 arr[0] = "t" phrase [0] = "t" matchCount = 1 count=0 arr[1] = "e" phrase [1] = "e" matchCount = 2 count=0 arr[2] = "k" phrase [2] = "k" matchCount = 3 count=0 arr[3] = "s" phrase [3] = "s" matchCount = 4 count=0 arr[4] = "t" phrase [4] = "t" matchCount = 5, matchCount == strlen(phrase)więc count=1, matchCount = 0 arr[5] = "l" phrase [0] = "t" matchCount = 0 count=1 arr[6] = "o" phrase [0] = "e" matchCount = 0 count=1 arr[7] = "r" phrase [0] = "k" matchCount = 0 count=1 arr[8] = "e" phrase [0] = "s" matchCount = 0 count=1 arr[9] = "m" phrase [0] = "s" matchCount = 0 count=1 Stąd jeśli taki matchCount jest równy długości phrase oraz arr[matchCount] == phrase[matchCount] wtedy zliczone jest jedno powtórzenie frazy w tekście. Widzę teraz, że zapomniałem zerować matchCout gdy pierwszy if się nie zgadza ale niezbyt wiem dlaczego licznik i powinienem zresetować. Kod co prawda nie jeszcze nie działa ale i ma być tylko licznikiem który przeskakuje po całej tablicy arr. Kiedy printowałem w pętli matchCount dostawałem maksymalnie wartość 2, a pytałem o frazę "tekst" dla pliku który zawiera "tekst tekst te" a później lorem ipsum po łacinie i angielsku. Powinien na samym początku mieć ze 2 razy wartość 5 oraz raz wartość 1. Strleny usunę gdy funkcja będzie gotowa, nie chciałem mieć zbyt wielu parametrów ale później wykorzystam po prostu zmienną length która przechowa długość phrase. Wstawiam kod funkcji aby nie było nieporozumień: int search( char arr[], int fileLen, char phrase[] ) { int i, matchCount = 0; int count = 0; for( i = 0; i <( fileLen - strlen( phrase ) + 1 ); i++ ) { if( arr[ i ] == phrase[ matchCount ] ) { matchCount++; if( matchCount ==( strlen( phrase ) ) ) { count++; matchCount = 0; } } else { matchCount = 0; } } return count; }
|
|
pekfos |
» 2019-02-13 20:03:17 ale niezbyt wiem dlaczego licznik i powinienem zresetować |
Jak będziesz szukać "ab" w tekście "aab", to nie znajdziesz. Jak wyzerujesz matchCount z powodu błędnego znaku, to musisz odpowiednio cofnąć i. for( i = 0; i <( fileLen - strlen( phrase ) + 1 ); i++ )
|
Pętla powinna przechodzić po całej tablicy. |
|
tirurir Temat założony przez niniejszego użytkownika |
» 2019-02-13 20:28:31 Pętla... racja, początkowo uznałem, że jeśli fraza ma 5 znaków to nie ma po co ostatnich trzech sprawdzać ale miałem tu na myśli początek frazy i zapomniałem o jej początku. Błąd który opisałeś (tekst ="aab", fraza = "ab") co prawda rozpisuje się tak: tekst [0] = "a" matchCount = 1 tekst [1] = "a" matchCount = 0 tekst [2] = "b" matchCount = 0 Dodanie do dolnego elsa "i--" spowoduje pętle więc utworzyłem warunek który zadziała tylko gdy matchCount nie równał się zero (czyli wcześniejszy znak pasował) ale to niestety nie wystarcza. int search( char arr[], int fileLen, char phrase[] ) { int i, matchCount = 0; int count = 0; for( i = 0; i < fileLen; i++ ) { if( arr[ i ] == phrase[ matchCount ] ) { matchCount++; if( matchCount ==( strlen( phrase ) ) ) { count++; matchCount = 0; } } else { if( matchCount != 0 ) i--; matchCount = 0; } } return count; }
|
|
jankowalski25 |
» 2019-02-13 20:35:51 warunek który zadziała tylko gdy matchCount nie równał się zero |
if( matchCount != 0 ) i--;
matchCount = 0;
|
Nie. Taki kod spowoduje, że matchCount zawsze będzie równe zero. |
|
tirurir Temat założony przez niniejszego użytkownika |
» 2019-02-13 20:46:13 Chyba za szybko staram się to poprawić, a za mało już dostrzegam. Kolejna poprawka spowodowała pętlę. Możliwe, że wrócę do tego jutro ze świeżym okiem. int search( char arr[], int fileLen, char phrase[] ) { int i, matchCount = 0; int count = 0; for( i = 0; i < fileLen; i++ ) { if( arr[ i ] == phrase[ matchCount ] ) { matchCount++; if( matchCount ==( strlen( phrase ) ) ) { count++; matchCount = 0; } } else { if( matchCount != 0 ) { i--; } else { matchCount = 0; } } } return count; }
|
|
jankowalski25 |
» 2019-02-13 20:53:45 Ten kawałek kodu nie robi nic. Równie dobrze mogłoby go nie być. Chyba moja poprzednia odpowiedź nie była zbyt trafna. Chodzi o to, że jeśli już zerujesz matchCount, to musisz odpowiednio cofnąć i (czyli niekoniecznie o jeden). Rozważ przypadek szukania "ababac" wewnątrz "abababac" . |
|
« 1 » 2 |