字符串的词频(即文件I/O)
Word Frequency of a string (i.e. File I/O)?
我写了一个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;
}
- .cpp和.h文件中的模板专用化声明
- 为什么两个不同的未命名名称空间可以共存于一个cpp文件中
- 文本文件中的单词链表
- CMake-按正确顺序将项目与C运行时对象文件链接
- 使用新行和不使用新行读取文件
- 在C++程序中输入的文本文件将不起作用,除非文本被复制和粘贴
- 挂起和取消挂起一个文件DLL
- 如何确定我已使用非编码文件到达 EOF?
- 命名空间中具有.h和.cpp文件的类
- 如何使用ndk-build.cmd构建Android.so文件
- 从包含m行的文件中提取n行,必要时(惰性地)重复该文件
- 读取文件并输入到矢量中
- 在C++中查找文件
- c++库的公共头文件中应该包含什么
- 用c++从输入文件中读取另一行
- Cppcheck生成xml转储文件
- 读取文件的最后一行并输入到链接列表时出错
- 无法编译 rtmidi 测试 cmidiin.cpp 文件, 非法指令
- 词频程序 - 文件输入太大?
- 字符串的词频(即文件I/O)