2
\$\begingroup\$

Previous question:

Counting words in files - follow-up

I have fixed punctuation problems in my previous code by using template, because it is easy to understand and my focus on template mechanism. The same applies for optimizing code.

Source code

//
//program name: WordCounter
//
//usage: C:\>WordCounter.exe test.txt test1.txt 
//

#include <iostream>
#include <iomanip>
#include <fstream>
#include <unordered_map>
#include <string>
#include <vector>
#include <algorithm>
#include <functional>
#include <exception>

template<bool...>
struct BoolSequence
{
};

template<std::make_unsigned<char>::type...>
struct CharSequence
{
};

template<typename T, std::make_unsigned<char>::type C>
struct Contains;

template<std::make_unsigned<char>::type First, std::make_unsigned<char>::type... Cs, std::make_unsigned<char>::type Match>
struct Contains<CharSequence<First, Cs...>, Match>  
    : Contains<CharSequence<Cs...>, Match>
{
};

template<std::make_unsigned<char>::type First, std::make_unsigned<char>::type... Cs>
struct Contains<CharSequence<First, Cs...>, First>
    : std::true_type
{
};

template<std::make_unsigned<char>::type Match>
struct Contains<CharSequence<>, Match>
    : std::false_type
{
};

template<std::make_unsigned<int>::type  I, typename T, typename U>
struct MakeSequence;

template<std::make_unsigned<int>::type I, bool... Bs, typename U>
struct MakeSequence<I, BoolSequence<Bs...>, U>
    : MakeSequence<I - 1, BoolSequence<Contains<U, I - 1>::value, Bs...>, U>
{
};

template<bool... Bs, typename U>
struct MakeSequence<0, BoolSequence<Bs...>, U>
{
    using Type = BoolSequence<Bs...>;
};

template<typename T>
struct BoolASCIITable;

template<bool... Bs>
struct BoolASCIITable<BoolSequence<Bs...>>
{
    bool operator()(const int c) const
    {
        static const bool table[] = { Bs... };
        return table[c];
    }
    using argument_type = char;
};

using Delims = CharSequence<'.', ','>;
using Table = BoolASCIITable<typename MakeSequence<256, BoolSequence<>, Delims>::Type>;
using Words = std::unordered_map<std::string, std::size_t>;

template<typename T>
std::pair<T, T> getToken(T begin, T end)
{
    begin = find_if(begin, end, std::not1(Table{}));
    auto second = find_if(begin, end, Table{});
    return std::make_pair(begin, second);
}


bool loadFromFile(const std::string& fileName, Words& words)
{
    std::ifstream file(fileName);

    if (!file)
    {
        return false;
    }

    for (std::string word; file >> word;)
    {
        auto s = getToken(word.begin(), word.end());
        ++words[std::string(s.first, s.second)];
    }

    return true;
}

template<typename T>
void showResult(const T& begin, const T& end)
{
    std::vector<T> words;

    words.reserve(std::distance(begin, end));

    for (auto i = begin; i != end; ++i)
    {
        words.push_back(i);
    }

    std::sort(words.begin(), words.end(),
        [&](const T& it1, const T& it2)
    {
        return it1->second > it2->second;
    });

    int x = 0;

    for (const auto& i : words)
    {
        if (x++ == 0)
        {
            std::cout << "\nThe most repeated element is: " << i->first << "\n\n";

            std::cout << " Word\tRepeated Times";

            std::cout << '\n' << std::setfill('-') << std::setw(23) << '\n';
        }
        std::cout << ' ' << std::setfill(' ')
            << std::setw(10) << std::left << i->first
            << std::setw(6) << std::internal << i->second << '\n';
    }
}

int main(int argc, char *argv[])
{
    Words words;

    for (int i = 1; i < argc; ++i)
    {
        if (!loadFromFile(argv[i], words))
        {
            std::cerr << "Can't open the file " << argv[i] << '\n';
        }
    }

    showResult(words.begin(), words.end());
}

Resource files

test.txt

File system is huge subject need more work out. file is plain text file
This is some junk words. simple program for words counting in text file. 1 2 3
2 2 2 2
@ % & ^ *
all so good
this test text file

test1.txt

file system second file, test multiple files

Output:

The most repeated element is: file

 Word   Repeated Times
----------------------
 file           6
 2              5
 is             3
 text           3
 system         2
 words          2
 test           2
 need           1
 huge           1
 @              1
 out            1
 subject        1
 %              1
 more           1
 work           1
 plain          1
 This           1
 some           1
 program        1
 junk           1
 File           1
 simple         1
 files          1
 for            1
 counting       1
 in             1
 3              1
 &              1
 multiple       1
 this           1
 ^              1
 *              1
 all            1
 so             1
 good           1
 1              1
 second         1
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.