-1

我编写了一个读取文本文件的 C++ 程序。但是,我希望程序计算一个单词出现的次数。例如,输出应如下所示:

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

注意每个单词只出现一次。我需要做什么才能达到这个效果??

这是文本文件(即名为 BillCosby.txt):

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

到目前为止,这是我的代码。我有一个极端的精神障碍,无法找到一种方法让程序读取一个单词出现的次数。

#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;
}
4

5 回答 5

4

你的程序读起来很混乱。但这部分对我来说很突出:

frequency[numberOfElements] = 1;

(在while循环中)。您意识到无论单词出现多少次,您总是将频率设置为 1 对吗?也许您的意思是增加值而不是将其设置为 1?

于 2013-01-21T04:20:09.190 回答
3

一种方法是标记化(将行拆分为单词),然后使用 c++ map 容器。该地图将单词作为键,单词计数作为值。

对于每个标记,将其添加到地图中,并增加字数。地图键是唯一的,因此您不会有重复项。

您可以将stringstream用于您的标记器,并且可以在此处找到地图容器参考(包括示例)

别担心,一个优秀的程序员每天都会处理心理障碍——所以要习惯它:)

于 2013-01-21T04:17:34.530 回答
0

解决方案的流程应该是这样的: - 初始化存储(你知道你显然有一个非常小的文件吗?) - 将初始计数设置为零(不是一) - 将单词读入数组。当你得到一个新单词时,看看你是否已经有了它;如果是,则在该位置的计数中加一;如果没有,将其添加到单词列表中(“嘿 - 一个新单词!”)并将其计数设置为 1 - 循环遍历文件中的所有单词

小心空白 - 确保您只匹配非空白字符。现在你有两次“钥匙”。我怀疑这是一个错误?

祝你好运。

于 2013-01-21T04:25:19.147 回答
0

这是我使用 codepad.org 测试的代码示例:

#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';

}

当它找到一个空格时它会停止,所以语法符号会把事情搞砸,但你明白了。

输出:

I => 1
but => 1
don't => 1
failure => 1
is => 1
key => 2
know => 1
please => 1
success, => 1 //注意这并不完美,因为逗号。一个快速的改变可以解决这个问题,我会让你自己解决这个问题。
=> 2
到 => 3
尝试 => 1

于 2013-01-21T04:31:11.353 回答
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;
}
于 2013-01-21T06:00:05.990 回答