2015-01-28 2 views
0

사용자가 텍스트 파일의 단어 또는 단어 모음의 인스턴스 수를 찾을 수있게 해주는 프로그램을 작성했습니다. 사용자는 명령 행에서이 같은 뭔가를 입력 할 수 있습니다왜 두 단어 계산 방법이 크게 다른가요?

$ ./wordCount Mars TripToMars.txt 

단어 "화성"의 인스턴스의 수를 검색하기 위해 화성 책 여행에서, 또는

$ ./wordCount -f collectionOfSearchWords.txt TripToMars.txt 

를 검색 할 수 collectionOfSearchWords.txt의 개별 행에있는 여러 단어의 인스턴스 수입니다. 용어를 포함하는 것이다,

$ grep -o 'Mars' TripToMars.txt | wc -w 

$ grep -o -w 'Mars' TripToMars.txt | wc -w 

첫 번째 명령은 아무 곳이나 단어의 인스턴스의 수를 찾습니다

프로그램이 정확하다고 보장하기 위해, 나는은 grep 명령을 사용 "Mars", "Marses"등의 구두점을 포함하는 독립 실행 형 단어로 ​​"화성"의 인스턴스 만 찾으면 서 "Marsa", "Marseen", "Marses" 화성? "등.

grep 명령은 모두 책에서 "화성"의 인스턴스 수를 49로 반환합니다.

while 루프에서 코드를 사용할 때 (간단히 말하면 관련 코드 만 포함) 프로그램에서 49를 반환합니다. 굉장합니다!

FILE *textToSearch; 
char *readMode = "r"; 

int count; 
char nextWord[100]; 
char d; 

textToSearch = fopen(argVector[argCount-1], readMode); 
if (textToSearch == NULL) { 
    fprintf(stderr, "Cannot open %s to be searched\n", argVector[argCount-1]); 
    return 1; 
} else { 
    while (fscanf(textToSearch, "%*[^a-zA-Z]"), fscanf(textToSearch, "%80[a-zA-Z]", nextWord) > 0) { 

     // increment the counter if the word is a match 
     if (strcmp(nextWord, argVector[word]) == 0) { 
      count++; 
     } 
    } 
} 

하지만 이전이 while 루프를 대체 할 때, 프로그램은

while (fscanf(textToSearch, "%*[^a-zA-Z]"), fscanf(textToSearch, "%80[a-zA-Z]", nextWord) > 0) {} 

while(1) { 
    d = fscanf(textToSearch, "%s", nextWord); 
    if (d == EOF) break; 
} 
사이의 큰 차이는 무엇 그래서 17

while(1) { 
    d = fscanf(textToSearch, "%s", nextWord); 
    if (d == EOF) break; 

    // increment the counter if the word is a match 
    if (strcmp(nextWord, argVector[word]) == 0) { 
     count++; 
    } 
}  

반환

?

편집는 화성 시도 및 계정 구두점을 후행 경우를위한 17 생산 코드에

if (strcmp(nextWordDict, nextWord) == 0 || 
    strcmp(nextWordDict, strcat(nextWord, ".")) == 0 || 
    strcmp(nextWordDict, strcat(nextWord, "?")) == 0 || 
    strcmp(nextWordDict, strcat(nextWord, "!")) == 0 || 
    strcmp(nextWordDict, strcat(nextWord, ",")) == 0) { 
     count++; 
} 

, 그리고 변화가 없었다 :

는이 코드를 추가했습니다. 아직 17

EDIT2 :

존 볼린저으로

가 제대로 아래 지적 nextWord에 버퍼링 된 문자열이 이미 후행 문장이 때문에이 코드는 아무것도 실시하지 않습니다, 그리고 코드는 더 추가 될 것이다. 이것은 내 생각에 잘못된 생각이다.

+1

Dunno,하지만 쉽게 알 수 있습니다. 단지'fscanf' 이후에'printf ("% s \ n", 다음 단어)'. 출력을 두 파일로 리디렉션하고 파일을 비교하십시오. – user3386109

+0

또한 작업 코드에서이 형식 문자열' "* * [^ a-zA-Z] % 80 [a-zA-Z]"'를 사용하여 두 fscanf를 하나로 결합 할 수 있습니다. 이 글을 쓰면서 버퍼 오버 플로우가 발생할 수도 있습니다. 작동하지 않는 코드의 형식 문자열은 단어 크기를 80으로 제한하기 위해' "% 80s"'이어야합니다. – user3386109

+0

응답 해 주셔서 감사합니다. "% 80s"로 변경하면 같은 결과가 발생합니다. –

답변

1

당신은 당신이 말할 때 잘못된 것을 명령 ...

$ grep -o -w 'Mars' TripToMars.txt | wc -w 

..."화성의 사례 만 독립된 단어로 찾는다", 또는 적어도 그 성명은 맥락에서 오해하기 쉽다. 이 명령은 더 큰 단어의 일부가 아닌 "화성"의 인스턴스를 찾습니다. "단어"는 문자, 숫자 및/또는 밑줄의 연속 문자열로 정의됩니다. 특히, "화성"과 일치하며 구두점이 뒤따라 나오는 곳에 표시됩니다. 구두점은 사용자가 주장하는 것과 충돌합니다.

두 스캔 방법의 차이점은 무엇입니까? 음,이 ...

while (fscanf(textToSearch, "%*[^a-zA-Z]"), 
     fscanf(textToSearch, "%80[a-zA-Z]", nextWord) > 0) { /* ... */ } 

... 스캔 제로 또는 일치하고 입력 오류가 발생하는지, 그 다음 80 개 라틴어 문자의 연속 순서를 검사 여부를 무시 라틴어 문자없는 자 이상, 그 시퀀스를 nextWord 버퍼에 기록한다. 한편

,이 ...

while(1) { 
    d = fscanf(textToSearch, "%s", nextWord); 
    if (d == EOF) break; 
} 

이 ... 공백을 선도 무시하고 nextWord에 공백이 아닌의 다음 연속 된 문자열을 검색합니다.

라틴 문자 또는 공백 문자가 아닌 두 문자는 문자를 무시합니다. 전자는 공백 문자를 무시하고 후자는 공백 문자를 포함하지 않습니다. nextWord. 당신은 화성에가는

에 문자열 "Mars"nextWord, 후자의 미스를 비교합니다.

이름은 "화성"

물이 화성에 있습니까?

인접한 구두점이 비교에 포함되어 있기 때문입니다. 당신의 텍스트는 그것들과 비슷한 많은 구조를 가질 가능성이 높으며, grep 명령은 다른 방법을 보여주지 않습니다.

+0

Oof, grep에 대한 -w 플래그에 대한 잘못된 생각이 있습니다. 저를 위해 고쳐 주셔서 감사합니다. 나는 앞의 구두점을 포함하는 코드를 추가했으며 (위의 편집 참조) 동일한 결과를 얻습니다. –

+1

논리가 뒤로 있습니다. 나는 많은 경우에'nextWord' * 이미 한쪽 또는 양쪽에 구두점이 있다는 것을 가정하고 있습니다. 더 추가하면 일치를 향상시키지 않습니다. 또한,'strcat()'는 왼쪽 인자를 변경하므로 문장 부호 전체를 추가하게됩니다. 그리고 왼쪽의 구두점에 대해서도 걱정할 필요가 있습니다.첫 번째 접근법을 사용하는 것만으로도 효과가 있으며 왜 실제로 원하는 것을 표현할 수 있습니까? –

+0

감사합니다. 나는 그 코드가 무엇을하고 있었는지에 대해 명확하게 생각하고 있지 않았다. 지금은 많은 의미가 있습니다. 첫 번째 방법을 사용하지만 두 번째 기능이 작동하지 않는 이유를 이해하려고했습니다. 그것을 지워 줘서 고마워요 :) –