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

时间:2013-01-21 04:10:50

标签: c++ memory-management file-io

我写了一个读取文本文件的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;
}

5 个答案:

答案 0 :(得分:4)

你的程序很难阅读。但这一部分向我伸出了道:

frequency[numberOfElements] = 1;

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

答案 1 :(得分:3)

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

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

您可以使用stringstream作为标记生成器,然后找到map container reference (incl examples) here

不用担心,一个优秀的程序员每天处理心理障碍 - 所以要习惯它:)

答案 2 :(得分:0)

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

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

祝你好运。

答案 3 :(得分: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 =&gt; 1
但是=&gt; 1
不要=&gt; 1
失败=&gt; 1
是=&gt; 1
key =&gt; 2
know =&gt; 1
请=&gt; 1
成功,=&gt; 1 //请注意,由于逗号,这并不完美。快速改变可以解决这个问题,我会让你自己解决这个问题 =&gt; 2
to =&gt; 3
尝试=&gt; 1

答案 4 :(得分: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;
}
相关问题