字符串的词频(即文件I/O)

Word Frequency of a string (i.e. File I/O)?

本文关键字:文件 词频 字符串      更新时间:2023-10-16

我写了一个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 << "nnWord Frequency Analysis " << std::endl;
std::cout << "n" << std::endl;
std::cout << "Word " << std::setw(25) << "Frequencyn" << 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 != ''){
    characterPointer++;
}
return characterPointer - buffer;
}
int StringCompare(char * firstString, char * secondString)
   {
    while ((*firstString == *secondString || (*firstString == *secondString - 32) ||    
(*firstString - 32 == *secondString)) && (*firstString != ''))
{
    firstString++;
    secondString++;
}
if (*firstString > *secondString)
    return 1;
else if (*firstString < *secondString)
    return -1;
return 0;
}

你的程序读起来很混乱。但这部分给我留下了深刻的印象:

frequency[numberOfElements] = 1;

(在while循环中)。你意识到你总是把频率设为1不管这个词出现多少次,对吧?也许你的意思是增加值,而不是将其设置为1?

一种方法是标记化(将行分成单词),然后使用c++映射容器。该映射将以单词作为键,并以单词计数作为值。

对于每个标记,将其添加到映射中,并增加单词计数。map键是唯一的,因此不会有重复的。

您可以使用stringstream作为标记器,您可以在这里找到映射容器引用(包括示例)。

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

解决方案流程应该是这样的:-初始化存储(你知道你有一个相当小的文件显然?)-将初始计数设置为0(不是1)-将单词读入数组。当你学到一个新单词时,看看你是否已经学过它;如果是,则在该位置的计数上加1;如果不是,将其添加到单词列表中("嘿——一个新词!")并将其计数设置为1-遍历文件

中的所有单词

小心空格-确保只匹配非空格字符。现在你有两次"钥匙"。我怀疑这是个错误。

好运。

下面是我用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
不要=> 1
失败=> 1
Is => 1
关键字=> 2
知道=> 1
请=> 1
success, => 1//注意,由于逗号的原因,这不是完美的。一个快速的改变可以解决这个问题,我将让你自己找出答案。
The => 2
> 3
尝试=> 1

我有点犹豫要不要直接回答一个看起来很像家庭作业的问题,但我很确定如果有人把这个作为家庭作业,任何一个像样的老师/教授都会要求一些相当严肃的解释,所以如果你这样做了,你最好仔细研究它,准备好回答一些严肃的问题,比如所有的部分是什么以及它们是如何工作的。

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