2013-01-21 5 views
-1

텍스트 파일을 읽는 C++ 프로그램을 작성했습니다. 그러나 프로그램에서 단어가 나타나는 횟수를 세고 싶습니다. 예를 들어 출력은 다음과 같이 표시되어야합니다.단어 문자열의 빈도 (즉, 파일 I/O)?

Word Frequency Analysis 

Word   Frequency 
I    1 
don't   1 
know    1 
the    2 
key    1 
to    3 
success   1 
but    1 
key    1 
failure   1 
is    1 
trying   1 
please   1 
everybody  1 

각 단어가 한 번만 나타나는 방식에 유의하십시오. 이 효과를 얻으려면 무엇을해야합니까 ??

I don't know the key to success, but the key to failure is trying to please everybody. 

여기에 지금까지 내 코드입니다 : 여기

텍스트 파일 (즉 BillCosby.txt 이름)입니다. 나는 극단적 인 정신적 장애가 있으며 프로그램에 단어가 나오는 횟수를 읽는 방법을 찾아 낼 수 없습니다.

#include <iostream> 
#include <fstream> 
#include <iomanip> 

const int BUFFER_LENGTH = 256; 
const int NUMBER_OF_STRINGS = 100; 

int numberOfElements = 0; 
char buffer[NUMBER_OF_STRINGS][BUFFER_LENGTH]; 
char * words = buffer[0]; 
int frequency[NUMBER_OF_STRINGS]; 

int StringLength(char * buffer); 
int StringCompare(char * firstString, char * secondString); 

int main(){ 

int isFound = 1; 
int count = 1; 

std::ifstream input("BillCosby.txt"); 

if(input.is_open()) 
{ 
    //Priming read 
    input >> buffer[numberOfElements]; 
    frequency[numberOfElements] = 1; 

while(!input.eof()) 
    { 
    numberOfElements++; 
    input >> buffer[numberOfElements]; 

    for(int i = 0; i < numberOfElements; i++){ 
     isFound = StringCompare(buffer[numberOfElements], buffer[i]); 
      if(isFound == 0) 
       ++count; 
    } 

    frequency[numberOfElements] = count; 


    //frequency[numberOfElements] = 1; 

    count = 1; 
    isFound = 1; 
    } 
    numberOfElements++; 
} 
else 
    std::cout << "File is not open. " << std::endl; 

std::cout << "\n\nWord Frequency Analysis " << std::endl; 
std::cout << "\n" << std::endl; 

std::cout << "Word " << std::setw(25) << "Frequency\n" << std::endl; 

for(int i = 0; i < numberOfElements; i++){ 
    int length = StringLength(buffer[i]); 
    std::cout << buffer[i] << std::setw(25 - length) << frequency[i] << 

std::endl; 
} 



return 0; 
} 

int StringLength(char * buffer){ 
char * characterPointer = buffer; 

while(*characterPointer != '\0'){ 
    characterPointer++; 
} 

return characterPointer - buffer; 
} 

int StringCompare(char * firstString, char * secondString) 
    { 
    while ((*firstString == *secondString || (*firstString == *secondString - 32) ||  

(*firstString - 32 == *secondString)) && (*firstString != '\0')) 
{ 
    firstString++; 
    secondString++; 
} 

if (*firstString > *secondString) 
    return 1; 

else if (*firstString < *secondString) 
    return -1; 

return 0; 
} 
+1

이것에 대한 조사를 해본 적이 있습니까? 매우 일반적인 질문입니다. 그래서 사람들을 위해 숙제하는 것을 좋아하지 않습니다. –

+0

이 질문을'C'로 표시했을 수도 있습니다. 실제 C++ 기능을 사용하고 있지 않습니다. http://codereview.stackexchange.com/questions (부러울 때 질문하지 마십시오. 처음에 수정하려면 여기로 다시 보내주십시오). –

답변

3

한 가지 방법은 (단어로 라인을 분할) 토큰 화하고 C++지도 컨테이너를 사용하는 것입니다. 지도는 단어를 키로, 단어 수를 값으로 사용합니다.

각 토큰에 대해 맵에 추가하고 단어 수를 증가시킵니다. 지도 키는 고유하므로 중복되지 않습니다.

토큰 장치에 stringstream을 사용할 수 있으며 map container reference (incl examples) here을 찾을 수 있습니다.

그리고 걱정하지 마세요, 매일 정신 블록과 좋은 프로그래머 거래 - 그래서 그것에 익숙해 :)

4

프로그램이 읽기 매우 혼란 스럽다. 하지만이 부분은 내게 머물렀다 :

frequency[numberOfElements] = 1; 

(while 회 돌이). 단어가 몇 번 나타나도 상관없이 항상 빈도를 1로 설정한다는 것을 알고 있습니까? 어쩌면 값을 증가시키고 1로 설정하지 않으려 고 한 것입니까?

+0

유일한 정답 (잘 묻는 질문에 대한 답변). –

0

솔루션의 흐름은 다음과 같이해야합니다 : - 제로 (하나도) 설정 초기 카운트 - - (당신은 분명히 아주 작은 파일이 알아?) 스토리지를 초기화 배열로 단어를 읽어 보시기 바랍니다. 새로운 단어를 얻었 으면 이미 가지고 있는지 확인하십시오. 그렇다면 해당 위치의 카운트에 1을 더하십시오. 그렇지 않으면 단어 목록 ("hey - 새 단어!")에 추가하고 파일 수를 1로 설정하십시오.

공백을주의하십시오. 일치하는 항목인지 확인하십시오 공백이 아닌 문자 만. 지금 당신은 "열쇠"를 두 번 가지고 있습니다. 그게 실수라고 생각해?

행운을 빈다. 그렇게 문법 기호 꼬이지하지만 당신은 요점을 파악하는 공간을 발견하면

#include <iostream> 
#include <map> 
#include <string> 
#include <sstream> 

using namespace std; 

int main() 
{ 
string s = "I don't know the key to success, but the key to failure is trying to please everybody."; 
string word; 
map<string,int> freq; 

for (std::string::iterator it=s.begin(); it!=s.end(); ++it) 
{ 
    if(*it == ' ') 
    { 
     if(freq.find(word) == freq.end()) //First time the word is seen 
     { 
      freq[word] = 1; 
     } 
     else //The word has been seen before 
     { 
      freq[word]++; 
     } 
     word = ""; 
    } 
    else 
    { 
     word.push_back(*it); 
    } 
} 

for (std::map<string,int>::iterator it=freq.begin(); it!=freq.end(); ++it) 
    std::cout << it->first << " => " << it->second << '\n'; 

} 

그것은 중지 :

+1

나는 동의하지 않는다. 올바른 데이터 구조를 사용하면 카운트를 0으로 설정하면 자동으로 실행됩니다. "단어를 배열로 읽어 들이기"는 나쁜 아이디어입니다. 배열은 실제로이 작업을위한 데이터 구조의 좋은 선택이 아닙니다. –

0

는 여기에 내가 codepad.org 테스트 코드 예입니다.

출력

: I => 1

하지만 => 1
하지 => 1
실패 => 1
은 => 1
키 => 2
알고 = > 1
please => 1
성공, => 1 // 쉼표 때문에 이것이 완벽하지 않음에 유의하십시오. 빠른 변화가 이것을 고칠 수 있지만, 나는 당신이 스스로 알아낼 수 있도록 할 것입니다. 시도 => 3

=> 2
=> 1

+1

아직도 많은 수작업을하고 있습니다. –

+0

참고 :지도에서 'operator []'를 통해 요소에 처음 액세스하면 해당 요소가 만들어집니다. 요소의'value' 부분이 0으로 초기화됩니다. 이것은 int가 0으로 초기화된다는 것을 의미합니다. 따라서 처음으로 특별한 경우는 필요하지 않습니다. 키를 분리 할 때마다 '값'을 증가시킵니다. –

+0

여기에 게시 해보십시오. codereview.stackexchange.com/questions –

0

나는하지만, 숙제처럼 많이 보이는 무언가에 대한 직접적인 대답을 게시 할 주저 조금 내가 누군가 경우 확신 해요 이것을 숙제로 바꾸면 중반에 괜찮은 교사/교수가 꽤 심각한 설명을 요구할 것입니다. 그렇게한다면, 조심스럽게 공부하고 모든 부분이 무엇이며 어떻게 작동하는지에 대해 심각하게 질문 할 준비를하는 것이 좋습니다. 작업.

#include <map> 
#include <iostream> 
#include <iterator> 
#include <algorithm> 
#include <string> 
#include <fstream> 
#include <iomanip> 
#include <locale> 
#include <vector> 

struct alpha_only: std::ctype<char> { 
    alpha_only() : std::ctype<char>(get_table()) {} 

    static std::ctype_base::mask const* get_table() { 
     static std::vector<std::ctype_base::mask> 
      rc(std::ctype<char>::table_size,std::ctype_base::space); 
     for (int i=0; i<std::ctype<char>::table_size; i++) 
      if (isalpha(i)) rc[i] = std::ctype_base::alpha; 
     return &rc[0]; 
    } 
}; 

typedef std::pair<std::string, unsigned> count; 

namespace std { 
    std::ostream &operator<<(std::ostream &os, ::count const &c) { 
     return os << std::left << std::setw(25) << c.first 
        << std::setw(10) << c.second; 
    } 
} 

int main() { 
    std::ifstream input("billcosby.txt"); 
    input.imbue(std::locale(std::locale(), new alpha_only())); 

    std::map<std::string, unsigned> words; 

    std::for_each(std::istream_iterator<std::string>(input), 
        std::istream_iterator<std::string>(), 
        [&words](std::string const &w) { ++words[w]; }); 
    std::copy(words.begin(), words.end(), 
       std::ostream_iterator<count>(std::cout, "\n")); 
    return 0; 
}