计算唯一单词的数量(对于此计数,情况无关紧要)

时间:2015-04-25 21:14:14

标签: c++ string vector word-count

嘿,所以我无法弄清楚代码来计算唯一单词的数量。我在psudeocode方面的思考过程是首先制作一个像<dependency> <groupId>org.primefaces</groupId> <artifactId>primefaces</artifactId> <version>5.2</version> </dependency> 之类的向量然后我会让程序读取每一行,所以我会得到类似vector<string> unique_word_list;的东西。对我来说困难的部分是提出代码,我检查向量(数组)以查看字符串是否已经在那里。如果它在那里我只是增加字数(足够简单)但如果它不在那里那么我只是向矢量添加一个新元素。如果有人能帮助我,我真的很感激。我觉得这并不难,但出于某种原因,我想不出用于比较字符串与数组内部的数字以及确定它是否是唯一字的代码。

2 个答案:

答案 0 :(得分:6)

不要使用vector - 使用保持唯一性的容器,例如std::setstd::unordered_set。在添加之前,只需将字符串转换为小写(使用std::tolower):

std::set<std::string> words;
std::string next;
while (file >> next) {
    std::transform(next.begin(), next.end(), next.begin(), std::tolower);
    words.insert(next);
}

std::cout << "We have " << words.size() << " unique words.\n"

答案 1 :(得分:3)

无法帮助自己编写一个利用C ++漂亮库的答案。我这样做,std::set

#include <algorithm>
#include <cctype>
#include <string>
#include <set>
#include <fstream>
#include <iterator>
#include <iostream>

int main()
{
    std::ifstream ifile("test.txt");
    std::istream_iterator<std::string> it{ifile};
    std::set<std::string> uniques;
    std::transform(it, {}, std::inserter(uniques, uniques.begin()), 
        [](std::string str) // make it lower case, so case doesn't matter anymore
        {
            std::transform(str.begin(), str.end(), str.begin(), ::tolower);
            return str; 
        });
    // display the unique elements
    for(auto&& elem: uniques)
        std::cout << elem << " ";

    // display the size:
    std::cout << std::endl << uniques.size();
}

您还可以定义一个新的字符串类型,您可以在其中更改char_traits,以便比较变为不区分大小写。这是你需要的代码(比以前冗长得多,但最终可能会重用它),char_traits重载是从cppreference.com复制/粘贴的:

#include <algorithm>
#include <cctype>
#include <string>
#include <set>
#include <fstream>
#include <iterator>
#include <iostream>

struct ci_char_traits : public std::char_traits<char> {
    static bool eq(char c1, char c2) { return toupper(c1) == toupper(c2); }
    static bool ne(char c1, char c2) { return toupper(c1) != toupper(c2); }
    static bool lt(char c1, char c2) { return toupper(c1) <  toupper(c2); }
    static int compare(const char* s1, const char* s2, size_t n) {
        while ( n-- != 0 ) {
            if ( toupper(*s1) < toupper(*s2) ) return -1;
            if ( toupper(*s1) > toupper(*s2) ) return 1;
            ++s1; ++s2;
        }
        return 0;
    }
    static const char* find(const char* s, int n, char a) {
        while ( n-- > 0 && toupper(*s) != toupper(a) ) {
            ++s;
        }
        return s;
    }
};

using ci_string = std::basic_string<char, ci_char_traits>;

// need to overwrite the insertion and extraction operators, 
// otherwise cannot use them with our new type 
std::ostream& operator<<(std::ostream& os, const ci_string& str) {
    return os.write(str.data(), str.size());
}

std::istream& operator>>(std::istream& os, ci_string& str) {
    std::string tmp;
    os >> tmp;
    str.assign(tmp.data(), tmp.size());
    return os;
}

int main()
{
    std::ifstream ifile("test.txt");
    std::istream_iterator<ci_string> it{ifile};
    std::set<ci_string> uniques(it, {}); // that's it

    // display the unique elements
    for (auto && elem : uniques)
        std::cout << elem << " ";

    // display the size:
    std::cout << std::endl << uniques.size();
}