我必须使用C ++中的数组实现向量,该数组用于计算输入中唯一字的数量。它读取输入,然后将单词添加到包含其计数和唯一单词的结构中,然后将其添加到向量中。我已经成功实现了insert。问题是我无法使插入/递增的唯一字数工作(元素不会添加到向量中)。这是我的代码:
#include <stdio.h>
#include <iostream>
#include <unistd.h>
#include "MyVector.h"
using namespace std;
struct wordCount{
string val;
int count;
};
int main(int argc, char** argv) {
enum { total, unique,individual } mode = total;
for (int c; (c = getopt(argc, argv, "tui")) != EOF;) {
switch(c) {
case 't': mode = total; break;
case 'u': mode = unique; break;
case 'i': mode = individual; break;
}
}
argc += optind;
argv += optind;
string word;
Vector<wordCount> words;
Vector<wordCount>::iterator it;
int count = 0;
while (cin >> word) {
count++;
if(mode == unique || mode == individual){
for(it=words.begin();it != words.end();it++){
if((it-1)->val <= word && it->val >= word){
// Found word, increment its count
if(it->val == word){
it->count++;
break;
}
// Otherwise insert the new unique word
else{
cout << "adding unique word" << endl;
wordCount* wc;
wc = new wordCount;
wc->val = word;
wc->count = 1;
words.insert(it,*wc);
break;
}
}
}
}
}
switch (mode) {
case total: cout << "Total: " << count << endl; break;
case unique: cout << "Unique: " << words.size() << endl; break;
case individual:
for(it=words.begin();it!=words.end();it++){
cout << it->val << ": " << it->count << endl;}
break;
}
}
答案 0 :(得分:2)
如果没有看到你的实施,很难说什么
Vector
。如果我们假设它遵守标准容器
约定(尝试这样做时没有错误):你
从it.begin(), but immediately access
it-1 . That's undefined behavior for a standard container. (I
don't know what it will do with your implementation of
Vector`开始迭代,
但它需要一些棘手的代码才能使它工作。)
在更高的层面上,似乎存在一个基本的不一致:你是 保持矢量排序,但仍然使用线性搜索。如果 你使用线性搜索,没有必要保持 矢量排序;只需使用:
Vector<wordCount>::iterator it = words.begin();
while ( it != words.end() && *it != word ) {
++ it;
}
if ( it == words.end() ) {
// not found, append to end...
} else {
// found, do whatever is appropriate...
}
(虽然我可能会追加到最后,将迭代器恢复到 新插入的元素,并将其视为已被发现)。
或者,如果您要对矢量进行排序,请使用二进制文件 搜索,而不是线性搜索。
在任何一种情况下,将搜索放在单独的函数中。 (如果这
没有做作业,我只说使用std::vector
和其中之一
std::find_if
或std::lower_bound
。)
另外,为什么new
位于最里面else
?更合理
方法是为wordCount
提供构造函数
(将计数设置为0),并执行以下操作:
if ( ! found ) {
it = words.insert( wordCount( word ) );
}
++ it->count;
found
的定义取决于您是否正在使用
二进制搜索与否。就标准而言,这将是
之一:
Vector<wordCount>::iterator it
= std::find_if( words.begin(), words.end(), MatchWord( word );
if ( it == words.end() ) {
it = words.insert( words.end(), wordCount( word ) );
}
++ it-count;
或
Vector<wordCount>::iterator it
= std::lower_bound( words.begin(), words.end(), word, CompareWord() );
if ( it == words.end() || it->val != word ) {
it = words.insert( wordCount( word ) );
++ it->count;
你应该努力寻找类似的东西
一个单独的查找函数,返回end
或
找不到值时插入的位置。
这使各种问题清楚地分开,并避免
代码中过多的嵌套。 (你应该尝试
通常避免break
,而在多重嵌套if
中,它是
完全不可接受 - 你会注意到其中一个
其他人回答错过了他们,并误解了
控制流量因为它。)
答案 1 :(得分:0)
那么,你为什么不使用map
?这正是它的用途,从一件事物映射到另一件事物。在您的情况下,从string
(单词)到int
(出现次数)。或者你必须使用矢量吗?
答案 2 :(得分:0)
尝试使用std :: map。
Counter::Map words;
Counter count(words);
std::for_each(
std::istream_iterator<std::string>(myInStream /*std::cin*/),
std::istream_iterator<std::string>(),
count);
std::copy(
words.begin(),
words.end(),
std::ostream_iterator<Counter::Map::value_type>(myOutStream /*std::cout*/, "\n"));
Counter functor可能看起来像这样
struct Counter
{
typedef std::map<std::string, size_t> Map;
Counter(Map& m) : words(&m) {}
void operator()(const std::string& word)
{
Map::iterator it = words->lower_bound(word);
if (it == words->end() || it->first != word)
words->insert(it, std::make_pair(word, 1));
else
++it->second;
}
Map* words;
};
使用std :: vector
struct CounterVector
{
typedef std::vector<std::pair<std::string, size_t> > Vector;
CounterVector(Vector& m) : words(&m) {}
struct WordEqual
{
const std::string* s;
WordEqual(const std::string& w) : s(&w) {}
bool operator()(Vector::const_reference p) const {
return *s == p.first;}
};
void operator()(const std::string& word)
{
Vector::iterator it = std::find_if(
words->begin(), words->end(), WordEqual(word));
if (it == words->end())
words->push_back(std::make_pair(word,1));
else
++it->second;
}
Vector* words;
};