N-PN White-Hat Project
[C++] Frequency Analysis - Version imprimable

+- N-PN White-Hat Project (https://dev.n-pn.fr/forum)
+-- Forum : Programmation (https://dev.n-pn.fr/forum/forumdisplay.php?fid=72)
+--- Forum : Langages compilés (https://dev.n-pn.fr/forum/forumdisplay.php?fid=25)
+--- Sujet : [C++] Frequency Analysis (/showthread.php?tid=1534)



[C++] Frequency Analysis - Fr3ak - 22-09-2011

Bonjour,

Voici une classe d'analyse fréquentielle de flux.

FrequencyAnalysis.cpp

Code PHP :
#include <algorithm>
#include <stdexcept>

#include "FrequencyAnalysis.h"
#include "PrintPair.hpp"
#include "TotalPair.hpp"

using namespace std;

void FrequencyAnalysis::analyze()
{
    
// Set position of the get pointer
    
m_in.seekg(0ios::beg);
    
    
// Get unformatted data from stream while eofbit is not set
    // and check if character is alphabetic using locale
    
while (not m_in.eof()) {
        
int c(m_in.get());
        
        if (
isalpha(c))
            ++
m_stats[static_cast<char>(c)];
    }
}

FrequencyAnalysis::FrequencyAnalysis(istream &in) : m_in(in), m_stats()
{
    
// Check input stream
    
if (not in)
        throw 
runtime_error("FrequencyAnalysis@FrequencyAnalysis: bad in");
}

statsMap FrequencyAnalysis::stats() const
{
    
// Return statistics
    
return m_stats;
}

ostream &operator<<(ostream &outFrequencyAnalysis const &freqAnalysis)
{
    
// Check output stream
    
if (not out)
        throw 
runtime_error("operator<<: bad out");
    
    
// Accumulate total number of occurrences
    // and print statistics for each pair
    // then return output stream
    
statsMap stats(freqAnalysis.stats());
    
unsigned total(accumulate(stats.begin(), stats.end(), 0TotalPair<charunsigned>()));
    
PrintPair<charunsigned> print(outtotal);
    
for_each(stats.begin(), stats.end(), print);
    return 
out;


FrequencyAnalysis.h

Code PHP :
#ifndef FREQUENCY_ANALYSIS_H
#define FREQUENCY_ANALYSIS_H

#include <iostream>
#include <map>

typedef std::map<charunsignedstatsMap;
typedef statsMap::iterator statsIt;

class 
FrequencyAnalysis
{
    
std::istream &m_in;
    
statsMap m_stats;
    
    public:
        
void analyze();
        
FrequencyAnalysis(std::istream &in);
        
statsMap stats() const;
};

std::ostream &operator<<(std::ostream &outFrequencyAnalysis const &freqAnalysis);

#endif 

main.cpp

Code PHP :
#include <fstream>
#include <stdexcept>
#include "FrequencyAnalysis.h"

using namespace std;

int main(int argcchar **argv)
{
    try {
        
// Check count of arguments
        
if (argc != 2)
            throw 
runtime_error("main: bad argc");
        
        
// Open file
        
ifstream file(argv[1]);
        
        
// Check file
        
if (not file)
            throw 
runtime_error("main: bad file");
        
        
// Analyze file
        
FrequencyAnalysis freqAnalysis(file);
        
freqAnalysis.analyze();
        
cout << "Letter\tCount\t%" << endl << freqAnalysis;
    } catch (
exception const &e) {
        
// Print exception
        
cout << e.what() << endl;
    }


Makefile.sh

Code PHP :
#!/bin/bash

g++ *.cpp -pedantic -Wall -Wextra -Wold-style-cast -Woverloaded-virtual 
-Wfloat-equal -Wwrite-strings -Wpointer-arith -Wcast-qual -Wcast-align 
-Wconversion -Wshadow -Weffc++ -Wredundant-decls -Wdouble-promotion 
-Winit-self -Wswitch-default -Wswitch-enum -Wundef -Wlogical-op -Winline 
-Werror -Wfatal-errors -std=c++0x -O2 -s

sstrip a
.out
upx a
.out 

PrintPair.hpp

Code PHP :
#ifndef PRINT_PAIR_HPP
#define PRINT_PAIR_HPP

template<class T1, class T2>
class 
PrintPair
{
    
std::ostream &m_out;
    
T2 m_total;
    
    public:
        
void operator()(std::pair<T1T2> const &x)
        {
            
// Print pair
            
m_out << x.first << "\t" << x.second << "\t" << 100 x.second m_total << "%" << std::endl;
        }
        
        
PrintPair(std::ostream &outT2 total) : m_out(out), m_total(total)
        {
            
// Check output stream
            
if (not out)
                throw 
std::runtime_error("PrintPair@PrintPair: bad out");
            
            
// Check total
            
if (not total)
                throw 
std::runtime_error("PrintPair@PrintPair: bad total");
        }
};

#endif 

TotalPair.hpp

Code PHP :
#ifndef TOTAL_PAIR_HPP
#define TOTAL_PAIR_HPP

template<class T1, class T2>
class 
TotalPair
{
    public:
        
T2 operator()(T2 xstd::pair<T1T2> const &y)
        {
            
// Return accumulated pair
            
return y.second;
        }
};

#endif 



[C++] Frequency Analysis - CyberSee - 23-09-2011

Bravo Fr3ak! Je vais compiler sa demain et voir ce que sa dit. Merci de ta contribution ;-) Rep+20!


[C++] Frequency Analysis - Fr3ak - 24-09-2011

Mise à jour

- Code commenté
- Pour chaque fonction, tous les arguments sont vérifiés et lancent une exception en cas d'erreur
- Utilisation de std::istream au lieu de std::ifstream pour pouvoir analyser directement plus de flux entrants (std::cin, std::istringstream...)
- Utilisation d'un foncteur pour le comptage d'occurrences total
- Utilisation d'un foncteur pour l'affichage des résultats
- Ajout d'un pseudo-Makefile en bash pour compiler le projet (les deux dernières lignes sont optionnelles et nécessistent sstrip + upx)