2015-07-27 6 views
5

Tak więc próbowałem znaleźć rozwiązanie tego problemu, ale mogę tylko znaleźć posty, w których brakuje nowego wiersza lub bajtu null w jednym z ciągów. Jestem prawie pewien, że tak nie jest.c - Strcmp nie zwraca 0 dla równych ciągów znaków

Korzystam z poniższej funkcji, aby porównać słowo z plikiem zawierającym listę słów z jednym słowem w każdym wierszu (słownik w funkcji). Oto kod:

int isWord(char * word,char * dictionary){ 
    FILE *fp; 
    fp = fopen(dictionary,"r"); 
    if(fp == NULL){ 
    printf("error: dictionary cannot be opened\n"); 
    return 0; 
    } 
    if(strlen(word)>17){ 
    printf("error: word cannot be >16 characters\n"); 
    return 0; 
    } 
    char longWord[18]; 
    strcpy(longWord,word); 
    strcat(longWord,"\n"); 
    char readValue[50] = "a\n"; 
    while (fgets(readValue,50,fp) != NULL && strcmp(readValue,longWord) != 0){ 
    printf("r:%sw:%s%d\n",readValue,longWord,strcmp(longWord,readValue));//this line is in for debugging 
    } 
    if(strcmp(readValue,longWord) == 0){ 
    return 1; 
    } 
    else{ 
    return 0; 
    } 
} 

Kod kompiluje bez błędów, a funkcja odczytuje plik słownika grzywny i wydrukuje listę słów, które pojawiają się tam. Problem, który mam, polega na tym, że nawet jeśli dwa ciągi są identyczne, strcmp nie zwraca wartości 0, więc funkcja zwróci wartość false dla dowolnego wejścia.

np uzyskać:

r:zymoscope 
w:zymoscope 
-3 

Jakieś pomysły? Czuję, że brakuje mi czegoś oczywistego, ale nie mogłem znaleźć niczego w moich wyszukiwaniach.

+8

Przypuszczam, że jesteś na komputerze z systemem Windows, które już odczytać pliku z zakończeń linii CRLF, i że nie oczyściłeś dokładnie końcówek. Istnieje różnica 3 między wartością "\ r" i "\ n" w wielu (większości) zestawach kodów. Ciekawe, że masz jedną 'printf()', drukującą wszystkie te dane, ale bez '\ n' w ciągu formatującym. Polegasz na nowych danych w danych, co wydaje się mało prawdopodobne. (Napisz funkcję drukowania bajtów w łańcuchu na heksach, wywołaj ją w każdym ciągu, zauważ różnicę.) –

+0

Twoja kontrola długości również zakłada pojedynczy '\ n', możesz być wyłączony o jeden, jeśli' \ r \ n 'jest używany – Basic

+3

Twój plik nigdy nie jest zamknięty. Wykonaj wszystkie możliwe kontrole * przed * otwarciem pliku. Zamknij po zakończeniu (lub w przypadku błędów). –

Odpowiedz

5

Widzę, że dodajesz newline do ciągów testowych, aby spróbować rozwiązać problem z zatrzymaniem końca linii w numerze fgets(). Znacznie lepiej to naprawić u źródła. Możesz usunąć wszystkie końcowe rzeczy w ten sposób, natychmiast po odczytaniu z pliku.

readValue [ strcspn(readValue, "\r\n") ] = '\0'; // remove trailing newline etc 
+2

Dodam, że jest to całkowicie bezpieczne dla zakończonego ciągu "\ 0". Jeśli nie ma żadnego końca linii, 'strcspn()' zwraca długość łańcucha, tym samym nieszkodliwie nadpisując "\ 0", które już było. –

4

Ciąg znaków, który czytasz zawiera znaki końcowe, a więc nie jest taki sam, jak ciąg, z którym go porównujesz.

Usuń końcowy znak nowej linii (i CR, jeśli tam jest); wtedy nie trzeba dodawać żadnego nowego wiersza lub powrót karetki do łańcucha porównywanych:

int isWord(char *word, char *dictionary){ 
    FILE *fp; 
    fp = fopen(dictionary, "r"); 
    if (fp == NULL){ 
    fprintf(stderr, "error: dictionary cannot be opened\n"); 
    return 0; 
    } 
    if (strlen(word) > 16){ 
    fprintf(stderr, "error: word cannot be >16 characters\n"); 
    return 0; 
    } 
    char readValue[50]; 
    while (fgets(readValue, 50, fp) != NULL){ 
    char *ep = &readValue[strlen(readValue)-1]; 

    while (*ep == '\n' || *ep == '\r'){ 
     *ep-- = '\0'; 
    } 
    if (strcmp(readValue, word) == 0){ 
     return 1; 
    } 
    } 
    return 0; 
} 
+1

Uwaga: 'readValue [strlen (readValue) -1]' może spowodować niezdefiniowane zachowanie/błąd w rzadkiej sytuacji, w której pierwszy odczyt znaku jest pusty. Sprawdzanie, czy długość łańcucha jest większa od 0, jest jednym ze sposobów naprawienia tego. – chux

+1

'while (* ep == '\ n' || * ep == '\ r') {* ep-- = '\ 0'; } * ep-- = '\ 0'; 'jest problemem, gdy' readValue' jest '" \ n "' lub '" \ r \ n "'. – chux

+0

I chociaż był zbyt grzeczny, by to powiedzieć, odpowiedź @ chux nie pozwala uniknąć obu tych problemów (chociaż można by argumentować, by przedwcześnie zatrzymywać się na linii wejściowej z CR w środku, oddzielnie od zakończenia linii CRLF lub LF). A potrzeba zrobienia osobnej operacji 'strlen()' jest powodem do preferowania funkcji POSIX ['getline()'] (http://pubs.opengroup.org/onlinepubs/9699919799/functions/getline.html) 'fgets()'; zwraca długość odczytanych danych, co (między innymi) pozwala na odczytanie poprzednich wiodących bajtów zerowych, jeśli uznasz to za pożądane. –

Powiązane problemy