Partage

[Exercices] Venez vous entraîner !

Ce mois: Parseur de fonctions mathématiques

16 janvier 2009 à 19:32:42

C'est clair que c'est plus simple que Vigenère !
A propos, je viens à l'instant d'envoyer avec 24h de retard ma solution pour l'exercice de décembre 2008... Elle dormait dans un de mes dossiers depuis presque 1 mois maintenant :-°
Nanoc, tu as reçu combien de réponses ?
Inkamath on GitHub - Interpréteur d'expressions mathématiques. Reprise du développement en cours.
17 janvier 2009 à 21:17:03

Maintenant que tu le dis, j'avais fait le chiffrement et le déchiffrement sous toutes ses formes, mais j'ai complètement oublié de faire le reste, tant pis pour cette fois.
31 janvier 2009 à 9:47:45

Bonjour,

Je test le problème 1 du projetEuler et la Oh surprise!Mon programme trouve la bonne réponse pour 10,mais quand,fièrement je met 1000,il ne trouve pas la bonne réponse...bon,j'ai utilisé une méthode bourine mais clair a mes yeux.

Donc voici mon prgramme:
#include <iostream>

using namespace std;

int main()
{
    for(;;) {
    int nbMax = 1000, nbMultiple = 0,i=0,resultat=0;

    cout << "nombre Max:" ;
    cin >> nbMax;

    //cout << endl << "multiple de 5:" << endl;
    // nombre de multiple de 5
    for(i=0;;i++) {
        resultat = 5*i;
        if (resultat < nbMax) {
            nbMultiple += resultat;
            //cout << ","<< resultat;
        }
        else break;
    }


    //cout << endl <<"multiple de 3:" << endl;
    //nombre de multiple de 3
    resultat = 0;
    for(i=0;;i++) {
        resultat = 3*i;
        if (resultat < nbMax) {
            nbMultiple += resultat;
            //cout << ","<< resultat;
        }
        else break;
    }

    cout << endl << nbMultiple << endl;

    }
    return EXIT_SUCCESS;
}


Merci d'avance si vous pouvez m'éclairer.

EDIT:Desolé si le post est HS,mais merci pour la réponse aussi^^
31 janvier 2009 à 10:21:38

c'est pas l'endroit pour poser des questions. si tu as un problème, crée un nouveau post sur le forum approprié.
1 février 2009 à 11:43:13

@Dam60 : car avec ta méthode tu comptes deux fois certains nombre comme 15 (3*5), ou 30 (3*2*5), d'après ce que je comprends l'idéal serait de faire un test if avec un ou et des modulos if( ((lenombre%3)==0) || ((lenombre%5)==0)) ;)

</hs>
6 février 2009 à 13:15:45

Solution du mois de décembre



Bonjour tout le monde ! Il est temps que je dévoile une solution pour l'exercice du mois de décembre. Vous avez été 8 à m'envoyer une solution.
Tous les codes reçus fonctionnaient (C'est la première fois !) et parmi ces réponses, je vous propose la solution de iNaKoll qui est le seul à avoir réussi à décoder le texte donné.
Voici la description de son programme ainsi que son code commenté.

Définition (cahier des charges)

But du programme :

- Niveau 1 : chiffrer et déchiffrer un message entré par l'utilisateur à l'aide du chiffre de Vigenère et d'une clé entrée par l'utilisateur
- Niveau 2 : connaissant la taille de la clé, il s'agit de cryptanalyser le message codé afin de déterminer la clé
- Niveau 3 : cryptanalyser le message codé afin de trouver la taille de la clé et se ramener au niveau 2 pour déterminer la clé
- Laisser la possibilité à l'utilisateur de choisir un fichier d'entrée et/ou un fichier de sortie

Structure du programme en 3 parties

1) Entrées/sorties ("parsage" de la ligne de commande, entrées/sorties avec les fichiers)
2) Traitement des données (cryptage, décryptage et/ou cryptanalyse)
3) Programme principal


1) Entrées/sorties

Afin de réaliser cet exercice, je me suis très fortement inspiré de la gestion des paramètres de la ligne de commande qu'a réalisé Chlab_lak pour l'exercice précédent. J'ai cependant apporté quelques petites améliorations ici et là...
Sans plus attendre :
clo.h
#ifndef H_CLOPTION
#define H_CLOPTION

#include <iostream> //std::cout
#include <cstdlib> // strtol
#include <fstream> // std::ifstream, std::ofstream
#include <sstream> // std::ostringstream
#include <string> // std::string
#include <stdexcept> // std::logic_error, std::runtime_error

class CLO
{
    public:

    /* Constructor */
	CLO(int argc, char *argv[])
	: options_flags(0)
	{
		std::string Buf;
		for(int i = 1; i < argc;)
		{
			Buf = argv[i];

			/* Input File*/
			if(Buf == "-i")
			{
				input = ""; // on ignore toute autre entree precedante
				if(Flag(INPUT_FILE))
					throw std::logic_error(
						"Le parametre -i a ete trouve plusieurs fois.");
				
				if(i+1 < argc && argv[i+1][0] != '-')
					input=LoadFromFile(argv[++i]);
				else
					throw std::logic_error(
						"Le nom du fichier d'entree est manquant.");
						
				options_flags |= INPUT_FILE;
			}
			
			/* Output File */
			if(Buf == "-o")
			{
				if(Flag(OUTPUT_FILE))
					throw std::logic_error(
						"Le parametre -o a ete trouve plusieurs fois.");
				if(i+1 < argc && argv[i+1][0] != '-')
					output_filename = argv[++i];
				else
					throw std::logic_error(
						"Le nom du fichier de sortie est manquant.");
				
				options_flags |= OUTPUT_FILE;
			}

			/* CRYPTER */
			else if(Buf == "-c")
			{
				if(Flag(CRYPTER) || Flag(DECRYPTER))
					throw std::logic_error(
						"Les parametres -c et/ou -d ont ete trouves plusieurs fois.");

				if(i+1 < argc && argv[i+1][0] != '-')
					cle = argv[++i];
				else
					throw std::logic_error(
						"La cle de cryptage est manquante.");

				options_flags |= CRYPTER;
			}

			/* DECRYPTER */
			else if(Buf == "-d")
			{
				if(Flag(CRYPTER) || Flag(DECRYPTER))
					throw std::logic_error(
						"Les parametres -c et/ou -d ont ete trouves plusieurs fois.");				
				if((i+1 < argc) && (argv[i+1][0] != '-'))
				{
					
					char* endptr = 0;
					long size = strtol(argv[++i],&endptr,10);
					if(endptr!=argv[i] && size != 0)
					{
						cle.resize(size,0);
						std::cout << "Taille de la cle de decryptage connue : ";
						std::cout << "cryptanalyse des donnees et deduction de la cle." << std::endl;
					}
					else
						cle = argv[i];
				}
				else
				{
					std::cout << "Cle de decryptage et taille inconnue : ";
					std::cout << "cryptanalyse des donnees et deduction de la cle." << std::endl;
				}
			
				options_flags |= DECRYPTER;
			}
			else if(Buf == "-v")
			{
				options_flags |= VERBOSE;
			}
			else if(Buf == "-h")
			{
				options_flags |= AIDE;
			}

			/* Append to input */
			else if(!Flag(INPUT_FILE))
				input += Buf;
				
			++i;
		}

	   /* Check */
	   if(input.empty())
			throw std::logic_error("Le parametre chaine n'a pas ete trouve.");
	   
	   if((options_flags & CRYPTER == 0) && (options_flags & DECRYPTER == 0))
			throw std::logic_error("Aucun parametre -c ou -d trouve.");
	}

	const std::string &Input(void) const
	{
		return input;
	}
	
	const std::string &Cle(void) const
	{
		return cle;
	}
	
	 const std::string &OutputFilename(void) const
	{
		return output_filename;
	}

	unsigned int GetFlags(void) const
	{
		return options_flags;
	}
	
	bool Flag(const int f)
	{
		return ((options_flags & f) != 0);
	}
	
	std::string LoadFromFile(const std::string &Name)
	{
		std::ifstream Ifs(Name.c_str());
		if(!Ifs)
			throw std::runtime_error(
				"Impossible d'ouvrir le fichier en lecture");
		std::ostringstream Oss;
		Oss << Ifs.rdbuf();
		return Oss.str();
	}
		/* Save in a file */
	void SaveInFile(const std::string &Name, const std::string &String)
	{
	    std::ofstream Ofs(Name.c_str());
	    if(!Ofs)
	        throw std::runtime_error("Impossible d'ouvrir le fichier en ecriture");
	    Ofs << String;
	}

	static const int CRYPTER ;
	static const int DECRYPTER;
	static const int AIDE;
	static const int INPUT_FILE;
	static const int OUTPUT_FILE;
	static const int VERBOSE;

    private:
	
	std::string input;
	std::string cle;
	std::string output_filename;
	unsigned int options_flags;
		

};

const int CLO::CRYPTER = 1;
const int CLO::DECRYPTER = 2;
const int CLO::AIDE = 4;
const int CLO::INPUT_FILE = 8;
const int CLO::OUTPUT_FILE = 16;
const int CLO::VERBOSE = 32;

#endif



2) Traitement des données

Sans aucun doute la partie la plus importante !

Fonction crypter :
void vigenere_crypter(const string& input, string& output, const string& cle)
{
	output.resize(input.size(),0);
	for(size_t i=0,j=0; i!=input.size(); ++i)
	{
		if(j==cle.size()) j = 0;
		
		output[i] = toupper(input[i]);
		//if(isupper(output[i])) /* L'utilisation de la fonction isupper ici pose des problèmes avec la gestion des caractères accentués (par exemple 'à') */
		if((output[i] >= 'A') && (output[i] <='Z'))
		{
			output[i] = ((output[i] + cle[j]-2*'A') % 26 + 'A');
			++j;
		}
		else
		{
			output[i] = input[i];
		}
	}
}


Cette fonction prend en paramètres des références sur le message à crypter (input), le message crypté (output) ainsi que sur la clé de cryptage.
La fonction est simple :
1) initialisation du message crypté avec le message en clair
2) mise en majuscule du message crypté
3) substitution des lettres du message par leur équivalent crypté (les autres caractères sont inchangés).

Fonction décrypter :
void vigenere_decrypter(const string& input, string& output, string& cle)
{
	// Si on ne connait pas la clé
	if((cle.size() == 0) || (cle[0] == 0))
	{
		// on la détermine par cryptanalyse
		vigenere_cryptanalyse(input,output,cle);
	}
	string cle_tmp = cle;
	for(size_t j=0; j!=cle_tmp.size(); ++j)
	{
		cle_tmp[j]= 26-(cle_tmp[j] - 'A') + 'A';
	}
	vigenere_crypter(input,output,cle_tmp);
}

Si l'on n'a aucune information sur la clé alors cle.size() == 0
Si on ne connait que la taille de la clé alors cle.size() renvoie la taille de la clé. La clé étant en elle même inconnue, on aura au préalable initialisé la string cle avec les caractères '\0' . Ceci explique donc le test cle[0] == 0 en début de fonction.
Dans ces deux cas, on cryptanalyse le message pour déterminer la clé, c'est le travail de la fonction vigenere_cryptanalyser .
Enfin, une fois la clé connue, on réutilise le code de la fonction vigenere_crypter pour déchiffrer le message.

Fonction cryptanalyser :
void vigenere_cryptanalyse(const string& input, string& output, string& cle)
{
	// Si la taille de la clé n'a pas été donnée, on la calcule
	if(cle.size() == 0)
	cle.resize(calculer_longueur_cle(input),0);
	
	// On fait une analyse de frequence pour trouver la clé
	size_t taille_donnees = 0;
	vector<vector<int> > freqs_input = calculer_frequences(input,taille_donnees,cle.size());
	
	for(size_t i=0; i<cle.size(); ++i)
	{
		/* Methode 1 : décalage par rapport à la plus grande frequence (lettre 'E')*/
		//cle[i]=(max_element(freqs_input[i].begin(),freqs_input[i].end())-freqs_input[i].begin()-'E'+'A')%26+'A');
		
		/* Methode 2 : moindres carrés par rapport au spectre de la langue */
		vector<double> normes;
		for(size_t j=0;j<26;++j)
		{
			vector<double> diff;
			rotate_copy(freqs_input[i].begin(),freqs_input[i].begin()+j,freqs_input[i].end(),std::back_inserter(diff));
			transform(diff.begin(),diff.end(),diff.begin(),bind2nd(divides<double>(),taille_donnees));
			transform(diff.begin(),diff.end(),fr_freqs,diff.begin(),minus<double>());
			transform(diff.begin(),diff.end(),diff.begin(),diff.begin(),multiplies<double>());
			normes.push_back(accumulate(diff.begin(),diff.end(),0.0,plus<double>()));
		}
		cle[i]=min_element(normes.begin(),normes.end())-normes.begin()+'A';
	}
}


Si la taille de la clé est inconnu, on demande à la fonction calculer_longueur_cle de la calculer pour nous.
Une fois la taille connue, on procède à une analyse de fréquences comme pour le chiffre de César afin de déterminer la clé. Je propose deux méthodes de résolution :
1ère méthode : La lettre la plus fréquemment rencontrée dans le message est considérée comme étant un 'E' ce qui permet de déterminer le décalage.
2ème méthode - moindres carrés : on cherche à minimiser la somme des carrés des différences entre les fréquences de références de la langue française et les fréquences observées dans le message. L'erreur minimum est obtenue pour un décalage correspondant à la clé de cryptage.

Fonction calculer_longueur_cle :
size_t calculer_longueur_cle(const string& input)
{
	// pour chaque longueur de clé possible
	size_t taille_cle=0;
	double ic=0;
	do 
	{
	    ++taille_cle;
		size_t taille_donnees = 0;
		vector<vector<int> > freqs = calculer_frequences(input,taille_donnees,taille_cle); // on fait une analyse de frequence
		ic=calculer_ic(freqs,taille_donnees,taille_cle); // on calcule l'indice de coincidence
	}while(taille_cle<input.size() && !is_ic_cible(ic));
	// On a trouvé la longueur de la clé
	return taille_cle;
}


Cette fonction calcule pour chaque longueur de clé possible l'indice de coïncidence du message.
Dés qu'un indice de coïncidence proche de celui de la langue française est trouvé, on sait que la longueur de clé actuellement testée est fortement probable et on renvoie cette valeur.

Fonction d'analyse fréquencielle :
vector<vector<int> > calculer_frequences(const string& input, size_t& taille_donnees, size_t taille_cle)
{
	taille_donnees = 0;
	string tmp(input.size(),0);
	vector<vector<int> > freqs(taille_cle, vector<int>(26,0)); // pour chaque caractère de la clé on a 26 fréquences
	for(size_t i=0; i!=input.size(); ++i)
	{
		tmp[i] = toupper(input[i]);
		//if(isupper(tmp[i]))  /* L'utilisation de la fonction isupperici pose des problèmes avec la gestion des caractères accentués (par exemple 'à') */
		if((tmp[i] >= 'A') && (tmp[i] <= 'Z'))
		{
			++freqs[taille_donnees%(taille_cle)][tmp[i]-'A'];
			++taille_donnees;
		}
	}
	taille_donnees/=taille_cle;
	return freqs;
}

Cette fonction calcule pour chaque longueur possible de la clé la fréquence d'apparition des lettres.
Elle est utilisé pour le calcul de l'indice de coïncidence et pour le calcul du décalage de la clé une fois la taille de celle-ci connue.

Fonction de calcul de l'indice de coïncidence :
double calculer_ic(const vector<vector<int> >& freqs, size_t taille_donnees, size_t taille_cle)
{
	double retour = 0;
	for(size_t i=0; i<taille_cle; ++i)
	{
		double ic = 0;
		for(size_t j=0; j<26; ++j)
		{
			ic+=freqs[i][j]*(freqs[i][j]-1);
		}
		ic/=taille_donnees*(taille_donnees-1);
		retour+=ic;
	}
	retour/=taille_cle;
	return retour;
}

Cette fonction permet de calculer l'indice de coïncidence d'un message à partir de son spectre de fréquences (fonction calculer_frequences).

Fonction is_ic_cible :
// renvoie true si 'ic' est proche de 'ic_cible' à 'prec' pourcents près
bool is_ic_cible(double ic, double ic_cible, double prec)
{
	return prec*ic_cible>fabs(ic-ic_cible) || ic>ic_cible;
}

Cette fonction renvoie vrai si l'indice de coïncidence passé en paramètre est proche de l'indice de coïncidence de la langue.
Après quelques essais, je me suis rendu compte qu'un indice de coïncidence élevé bien que très différent de l'indice de coïncidence de référence donne généralement de bons résultats pour le calcul de la longueur de la clé. Ainsi, cette fonction valide tout indice de coïncidence supérieur à l'indice de coïncidence de référence.


Le code complet de la partie traitement :

vigenere.h

#ifndef H_VIGENERE
#define H_VIGENERE

#include <string>
#include <vector>

void pre_traitement_cle(std::string& cle);
void vigenere_crypter(const std::string& input, std::string& output, const std::string& cle);
void vigenere_decrypter(const std::string& input, std::string& output,std::string& cle);
void vigenere_cryptanalyse(const std::string& input, std::string& output,std::string& cle);
std::vector<std::vector<int> > calculer_frequences(const std::string& input, size_t& taille_donnees, size_t taille_cle);
double calculer_ic(const std::vector<std::vector<int> >& freqs, size_t taille_donnees, size_t taille_cle);
size_t calculer_longueur_cle(const std::string& input);
bool is_ic_cible(double ic, double ic_cible = 0.0778, double prec = 0.07);

const double fr_freqs[] = {9.42,1.02,2.64,3.39,15.87,
						 0.95,1.04,0.77,8.41,0.89,
						 0.00,5.34,3.24,7.15,5.14,
						 2.86,1.06,6.46,7.90,7.26,
						 6.24,2.15,0.00,0.30,0.24,0.32};

#endif


vigenere.cpp
#include <iostream>
#include <string>
#include <vector>
#include <algorithm> // find_if
#include <cmath> // fabs
#include <functional> // bind2nd, minus, mult, plus
#include <numeric> // accumulate
#include <cctype> // isalpha

#include "vigenere.h"

using namespace std;

void vigenere_crypter(const string& input, string& output, const string& cle)
{
	output.resize(input.size(),0);
	for(size_t i=0,j=0; i!=input.size(); ++i)
	{
		if(j==cle.size()) j = 0;
		
		output[i] = toupper(input[i]);
		//if(isupper(output[i])) /* L'utilisation de la fonction isupper ici pose des problèmes avec la gestion des caractères accentués (par exemple 'à') */
		if((output[i] >= 'A') && (output[i] <='Z'))
		{
			output[i] = ((output[i] + cle[j]-2*'A') % 26 + 'A');
			++j;
		}
		else
		{
			output[i] = input[i];
		}
	}
}

void vigenere_decrypter(const string& input, string& output, string& cle)
{
	// Si on ne connait pas la clé
	if((cle.size() == 0) || (cle[0] == 0))
	{
		// on cryptanalyse
		vigenere_cryptanalyse(input,output,cle);
	}
	string cle_tmp = cle;
	for(size_t j=0; j!=cle_tmp.size(); ++j)
	{
		cle_tmp[j]= 26-(cle_tmp[j] - 'A') + 'A';
	}
	vigenere_crypter(input,output,cle_tmp);
}

void vigenere_cryptanalyse(const string& input, string& output, string& cle)
{
	// Si la taille de la clé n'a pas été donnée, on la calcule
	if(cle.size() == 0)
	cle.resize(calculer_longueur_cle(input),0);
	
	// On fait une analyse de frequence pour trouver la clé
	size_t taille_donnees = 0;
	vector<vector<int> > freqs_input = calculer_frequences(input,taille_donnees,cle.size());
	
	for(size_t i=0; i<cle.size(); ++i)
	{
		/* Methode 1 : décalage par rapport à la plus grande frequence (lettre 'E')*/
		//cle[i]=(max_element(freqs_input[i].begin(),freqs_input[i].end())-freqs_input[i].begin()-'E'+'A')%26+'A');
		
		/* Methode 2 : moindres carrés par rapport au spectre de la langue */
		vector<double> normes;
		for(size_t j=0;j<26;++j)
		{
			vector<double> diff;
			rotate_copy(freqs_input[i].begin(),freqs_input[i].begin()+j,freqs_input[i].end(),std::back_inserter(diff));
			transform(diff.begin(),diff.end(),diff.begin(),bind2nd(divides<double>(),taille_donnees));
			transform(diff.begin(),diff.end(),fr_freqs,diff.begin(),minus<double>());
			transform(diff.begin(),diff.end(),diff.begin(),diff.begin(),multiplies<double>());
			normes.push_back(accumulate(diff.begin(),diff.end(),0.0,plus<double>()));
		}
		cle[i]=min_element(normes.begin(),normes.end())-normes.begin()+'A';
	}
}

vector<vector<int> > calculer_frequences(const string& input, size_t& taille_donnees, size_t taille_cle)
{
	taille_donnees = 0;
	string tmp(input.size(),0);
	vector<vector<int> > freqs(taille_cle, vector<int>(26,0)); // pour chaque caractère de la clé on a 26 fréquences
	for(size_t i=0; i!=input.size(); ++i)
	{
		tmp[i] = toupper(input[i]);
		//if(isupper(tmp[i]))  /* L'utilisation de la fonction isupperici pose des problèmes avec la gestion des caractères accentués (par exemple 'à') */
		if((tmp[i] >= 'A') && (tmp[i] <= 'Z'))
		{
			++freqs[taille_donnees%(taille_cle)][tmp[i]-'A'];
			++taille_donnees;
		}
	}
	taille_donnees/=taille_cle;
	return freqs;
}

double calculer_ic(const vector<vector<int> >& freqs, size_t taille_donnees, size_t taille_cle)
{
	double retour = 0;
	for(size_t i=0; i<taille_cle; ++i)
	{
		double ic = 0;
		for(size_t j=0; j<26; ++j)
		{
			ic+=freqs[i][j]*(freqs[i][j]-1);
		}
		ic/=taille_donnees*(taille_donnees-1);
		retour+=ic;
	}
	retour/=taille_cle;
	return retour;
}

size_t calculer_longueur_cle(const string& input)
{
	// pour chaque longueur de clé possible
	size_t taille_cle=0;
	double ic=0;
	do 
	{
	    ++taille_cle;
		size_t taille_donnees = 0;
		vector<vector<int> > freqs = calculer_frequences(input,taille_donnees,taille_cle); // on fait une analyse de frequence
		ic=calculer_ic(freqs,taille_donnees,taille_cle); // on calcule l'indice de coincidence
	}while(taille_cle<input.size() && !is_ic_cible(ic));
	// On a trouvé la longueur de la clé
	return taille_cle;
}

void pre_traitement_cle(string& cle)
{
	for(size_t i=0; i!=cle.size(); ++i)
	{
		//if(isalpha(cle[i]) || cle[i] == 0) /* L'utilisation de la fonction isalpha ici pose des problèmes avec la gestion des caractères accentués (par exemple 'à') */
		if(((cle[i] >= 'A') && (cle[i] <= 'z')) || (cle[i] == 0))
		{
			cle[i] = toupper(cle[i]);
		}
		else
		{
			cle[i] = 'A';
		}
	}
}

// renvoie true si 'ic' est proche de 'ic_cible' à 'prec' pourcents près
bool is_ic_cible(double ic, double ic_cible, double prec)
{
	return prec*ic_cible>fabs(ic-ic_cible) || ic>ic_cible;
}


3) Programme principal

main.cpp
#include <iostream>
#include <string>

#include "vigenere.h"
#include "clo.h"

using namespace std;

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

    try
    {
		CLO Options(argc, argv);
		
		string input = Options.Input();
		string output;
		
		string cle = Options.Cle();
		pre_traitement_cle(cle);
		
		if(Options.Flag(CLO::AIDE))
		{			
			cout << Options.LoadFromFile("aide.txt") << endl;
		}
		
		if(Options.Flag(CLO::CRYPTER))
		{
			cout << "Cryptage..." << endl;
			vigenere_crypter(input,output,cle);
		}
		else if(Options.Flag(CLO::DECRYPTER))
		{
			cout << "Decryptage..." << endl;
			vigenere_decrypter(input,output,cle);
		}
		
		if(Options.Flag(CLO::OUTPUT_FILE))
		{			
			Options.SaveInFile(Options.OutputFilename(),output);
			cout << "Sauvegarde effectuee dans : " << Options.OutputFilename() << "." << endl;
		}
		
		cout << "Taille de la cle : " << cle.size() << endl;
		cout << "Cle : " << cle << endl;
		
		if(Options.Flag(CLO::VERBOSE))
		{
			cout << "Output : " << output << endl;
		}
	}
	catch(const std::exception &E)
    {
        std::cout << "\n> Erreur.. " << E.what() << std::endl
                  << "> De...... " << typeid(E).name() << std::endl;

        return 1;
    }
    catch(...)
    {
        std::cout << "\n> Erreur.. Inconnue" << std::endl
                  << "> De...... " << std::endl;

        return 1;
    }


	return 0;
}


Pour finir voici une petite aide pour l'utilisation du programme :
AIDE

> Synopsis : vigenere {[-i] _input_} {{-c _cle_ }|{-d [_cle_]|[_taille_cle_]}} [-o _output_]
> _input_ : chaine de caractere a traiter, a entourer d'apostrophes si possible
> -i : Indique que _input_ est le nom du fichier a traiter
> -o : Permet d'indiquer que _output_ est le fichier de sortie
> -c : Chiffre le texte de _input_ avec _cle_
> -d : Dechiffre le texte de _input_ avec _cle_ ou par cryptanalyse avec ou sans _taille_cle_


Exemples :

Niveau 1 :
E:\cpp\vigenere2>vigenere "JOYEUX NOEL LES ZEROS" -c SDZ -v
Cryptage...
Taille de la cle : 3
Cle : SDZ
Output : BRXWXW FRDD ODK CDJRR

E:\cpp\vigenere2>vigenere "BRXWXW FRDD ODK CDJRR" -d SDZ -v
Decryptage...
Taille de la cle : 3
Cle : SDZ
Output : JOYEUX NOEL LES ZEROS


Ici on crypte (-c) et on décrypte (-d) un message à l'aide de la clé "SDZ".
En absence de fichier de sortie, il est recommandé d'utiliser le mode verbose (-v) afin d'afficher les données traitées (Output).

Niveau 2 :
E:\cpp\vigenere2>vigenere -i aide.txt -c SDZ -v -o aide_c.txt
Cryptage...
Sauvegarde effectuee dans : aide_c.txt.
Taille de la cle : 3
Cle : SDZ
Output :
SLCW

> VXFROKLR : NLFWQDJH {[-H] _AQOMW_} {{-B _UOD_ }|{-V [_FKW_]|[_WZAOKW_FKW_]}} [-R _NMWOMW_]
> _HFSTL_ : FGSLMW GD UDQSFSWUD S WQSLSWU, Z WQSGXQWU C'SSNKWQGSGWV RA SNKVHTOD
> -A : LMVLPMH PMH _HFSTL_ HRL OD FRL VX EAFGAHQ S WQSLSWU
> -N : HHQEHS V'LMVLPMHQ IXD _GXSHXS_ WVS DH EAFGAHQ VH RGUSAH
> -B : UKHXIQW OD LHWLH CW _LMHXS_ SYDU _FKW_
> -G : CWFGAIEJH KW WDPWD VH _HFSTL_ DUWF _BDH_ NM SZJ FQQSSSQZDBRW DUWF NM VZFV _SSLKDH_BDH_


E:\cpp\vigenere2>vigenere -i aide_c.txt -d 3 -v
Taille de la cle de decryptage connue : cryptanalyse des donnees et deduction de la cle.
Decryptage...
Taille de la cle : 3
Cle : SDZ
Output :
AIDE

> SYNOPSIS : VIGENERE {[-I] _INPUT_} {{-C _CLE_ }|{-D [_CLE_]|[_TAILLE_CLE_]}} [-O _OUTPUT_]
> _INPUT_ : CHAINE DE CARACTERE A TRAITER, A ENTOURER D'APOSTROPHES SI POSSIBLE
> -I : INDIQUE QUE _INPUT_ EST LE NOM DU FICHIER A TRAITER
> -O : PERMET D'INDIQUER QUE _OUTPUT_ EST LE FICHIER DE SORTIE
> -C : CHIFFRE LE TEXTE DE _INPUT_ AVEC _CLE_
> -D : DECHIFFRE LE TEXTE DE _INPUT_ AVEC _CLE_ OU PAR CRYPTANALYSE AVEC OU SANS _TAILLE_CLE_


Cette fois, le message a traiter est contenu dans le fichier indiqué après l'option '-i'.
Les données de sorties (Output) sont sauvegardées dans un fichier en plus d'être affichées dans la console en mode verbose.
Dans un premier temps, on crypte le fichier "aide.txt" avec la clé "SDZ" le resultat est enregistré dans le fichier "aide_c.txt" et est affiché dans la console. Le fichier "aide_c.txt" est ensuite décrypté en donnant au programme la taille de la clé utilisée pour le cryptage (3). La clé est déduite et affichée dans la console par le programme.

Niveau 3 :
E:\cpp\vigenere2>vigenere -i aide_c.txt -d -v
Cle de decryptage et taille inconnue : cryptanalyse des donnees et deduction de la cle.
Decryptage...
Taille de la cle : 3
Cle : SDZ
Output :
AIDE

> SYNOPSIS : VIGENERE {[-I] _INPUT_} {{-C _CLE_ }|{-D [_CLE_]|[_TAILLE_CLE_]}} [-O _OUTPUT_]
> _INPUT_ : CHAINE DE CARACTERE A TRAITER, A ENTOURER D'APOSTROPHES SI POSSIBLE
> -I : INDIQUE QUE _INPUT_ EST LE NOM DU FICHIER A TRAITER
> -O : PERMET D'INDIQUER QUE _OUTPUT_ EST LE FICHIER DE SORTIE
> -C : CHIFFRE LE TEXTE DE _INPUT_ AVEC _CLE_
> -D : DECHIFFRE LE TEXTE DE _INPUT_ AVEC _CLE_ OU PAR CRYPTANALYSE AVEC OU SANS _TAILLE_CLE_


Cette fois le fichier "aide_c.txt" est décrypté par le programme sans que celui-ci ne connaisse la clé utilisée pour le cryptage. La clé est déduite et affichée dans la console par le programme.

Enfin, voici ce que donne le programme pour le texte crypté du niveau 3 :
E:\cpp\vigenere2>vigenere -i n3.txt -d -v
Cle de decryptage et taille inconnue : cryptanalyse des donnees et deduction de la cle.
Decryptage...
Taille de la cle : 8
Cle : VIGENERE
Output : TRACELINEGALPALINDROMENEIGEBAGATELLEDIRAHERCULELEBRUTREP
ENTIRCETECRITNEPERECLARCLUPESETROPLISAVICEVERSAPERTECERISEDUNEVE
RITEBANALELEMALSTROMALEPMORTEDULCORECREPEPORTEDECEDESIRBRISEDUNI
OTALIVRESIABOLITESSACRESONTEREINTECORCRUELNOSALBATROSETRELASAUTE
LBATIMIETTEVICEVERSADUJEUQUEFITNACREMEDICALLESELENITERELAPSELLIP
SODALIVREILBATLATURBINEBATLISOLEMERAVALELEVERRESIOBEIDUPERNODEHP
ORTSUOBSEDANTESONATETEINTEEDIVRESSECEREVESEMITPESTEABLAGUERBEHLA
RTSECNASIPEUQUALGEBRESELABOREDELOREVALUEIDIOMEETIREHESITEBATARDR
EPLIELOSNUSIALAGENESECRETEVERBENULALINSTARDECINQOCCISRETSAMINCIS
DRAILLESINEGALESILAVATARESPACECARESSECENOIRBELZEBUTHOILOFFENSETI
RELECHOFITADESERTSALUTSANGROBEETETEFIEVRESADAMRAUQUEILECRITABRUP
TOGREEHCERCUEILLAVENIRTUEFFILEGENIALALARUEMURMURESUDEUNETIREVASE
LINESEPAREELEPEIREGELEERODEHEPMORTELLIATABALAFRENATIVELITIGEREGA
GNERETNEMRESSACILFREMITSESAPENAEHCAVALETIMIDEILNIACESURSAUTHASAR
DREPUTELLEMAGICIENAMORTEMELITUNIGNARELERAPSODELACSEMUMIXAMELAHEP
OCEANONOXOBECHAMELAZUREJACULERTOPAZELECEDREMALABARFAIBLEARSINOEL
EMACULEMANTEIVREGLAUQUEPISLAIRATONESICARTSOURNOISSIMEDICINALELAU
TREGLACEMELBALUNNALERTAINIPOLLENRETETERGERCEREPUDENTENITOBACCOTU
DESIRBRIORIMEEHPROLIXENECROPHORETUFERRESLAVENIRVELUOCRECROMANTNE
RAGELARAVEUGLAIRESEDANTESELZEVIRSTOBSEDENTROMAINEXACTETNEMRODSEL
LESESSAMSONETNIERTEOCALLICAVECANEMCARCENUTROPMINOISREMBUSCADEDER
UPTIVESABABILADMONESTAFILACCRUTETEBLEUQUARIANEEVITATNETATTENTION
EBENIERFACTICERESSORTIDUREELCIGITALPAGAGNOMELEHEROSSELAMENTETROM
PECHOCOLATCELAIDTOTEMORDNILAPLATIRITUELBISCORNUCESACREBEDEAUQUEL
BATCEJESUSPALACEPIEGETORPEDODRUESIAFELLAHTOTNEPEUTNILEBIGARUERBE
ZEFLEUGENISTEENRUTCONSUMADARTSONEPIDEOLIENNEICIROTEHRUTTOIDIDEMG
INELEVERAELUBIFOCALLITHOSETNOTREPATHOSALAHAUTEURDESECSALAMALECEL
UCIDERIONECLATEELLETENUETNABUTITEMMALFAMEDEGREVIDEJULEPMACEDOINE
DAXIOMESSACSEMEDECOLEVENIELAHLEVERBEENIVRENESUCERNIARRETEREHCAJA
MAISLUNABOLIRALEHASARDNUOTTOMANAECHOLARTSUOHTARAZEROBELLEDEBORAH
OSACREPUTEVERTUBLEUQUALITESIVERTUALAPARTTARIFEDECALITRESETNULNAL
UTROPSILSERIADECEBASILICISEUTILAPRIEBONZESSAMARITAINTORAVILAINSM
ONSTRESIDOLATREDNAENSUSREVESEVAPORESARBALETEBETESENNOCEDUTELLIVR
EMORTEMERITUOTRAPUAELFEILLIELOSILLIAJEREMIADELUCIDEPETARDRATETAR
EINETTEBIGLEURCRUELNONACELOTSIFARCISTOIDITOLECOEURLIEDAMONSTREVE
LUANGENIBETESECAPSEUDODELIRETSARINESELLEELACIDARETINABRUTIDENINI
VEDEJANIRELEPHENIXEVEDESABLESECARTENEPEUTEGARERRACINESRADIALESEN
MANALOUBLIFETICHEENARGILEFOUDREPRIXILEDELAGORGONEENROCETOLICORNE
ECARTELEESIRENERUMBABANNIRAMAREDNOSANIEREDEMIMOSAPAYSAGEDOURCQOC
RESOUSIVEDECALEVOLCANROCTAROTCELEDUPERELIVRESSILENEBAVARDREPLIES
URSANULLITENUAJEBELGEIPSEITEBANALELEHCAHYDROMELARIPSALTERIONERRE
ELORELEIFIMARMELADEDEVIREDALADINEDORNOELCRECHELANICITAVERNEGELEE
DESBOLASANTONGIVREFICULEDELANEVAIRONLAPALISSEELUGNOSESSANSORGUEI
LECRUSALESECSALUTSANGIOMETESSICRANEURRUENARCISSETEMOIGNASTULASCE
SELASURCELIEUGROSNASSESONGULEESSILAPALNORIAVENALEDELUCIFERVIGNOT
NASALOBSEDEELEGENREVATICINALEHCERCLEONRODENIDALADERIVEDEDALEMRAM
IFIELEROLEERRENOIRETLASPIRALEMORDYHACHELELANABETIESPIEGLEBEJAUNE
TILLUNASRUSEILPERDRAVABENELISSERVILEREPUDELECTORATCORNACLOVELACE
DEVISUOSERCOQCRUODEGASYAPASOMIMEDEREINASONDERAMARINNABABMURENERI
SEELETRACEENROCILOTECORNEENOGROGALEDELIXIRPERDUOFELIGRANEEHCITEF
ILBUOLANAMNESELAIDARSENICARRERAGETUEPENETRACESELBASEDEVEXINEHPEL
ERINAJEDEVININEDITURBANITERADICALEELLESENIRASTERILEDODUESPACESET
EBINEGNAULEVERTSNOMADEILRUEOCELOTIDIOTSICRAFISTOLECANONLEURCRUEL
GIBETTENIERATETARDRATEPEDICULEDAIMEREJAILLISOLEILLIEFLEAUPARTOUT
IREMETROMERVILLETUDECONNESETEBETELABRASEROPAVESEVERSUSNEANDERTAL
ODISERTSNOMSNIALIVAROTNIATIRAMASSEZNOBEIRPALITUESICILISABECEDAIR
ESLISPORTULANLUNTESERTILACEDEFIRATTRAPALAUTREVISETILAUQUELBUTREV
ETUPERCASOHAROBEDELLEBOREZARATHOUSTRALOHCEANAMOTTOUNDRASAHELARIL
OBANULSIAMAJACHERETERRAINRECUSENERVINEEBREVELHALEINEVELOCEDEMESC
ASSEMOIXADENIODECAMPELUJEDIVERGEDEMAFLAMMETITUBANTEUNETELLEETALC
ENOIREDICULECELAMALASCESEDRUETUAHALASOHTAPERTONTESOHTILLACOFIBUL
EAREVELENIGMEDIDIOTTURHETORICIENNEILOEDIPENOSTRADAMUSNOCTURNEETS
INEGUELFEZEBREURAGIBELINTUEPENTOTHALLEFAISEURDODEPROTEGEIPECALAP
SUSEJECTABLEUQUAEDEBERCASECUNROCSIBLEUTIRITALPALINDROMETOTDIALEC
TALOCOHCEPMORTETNEMALESSOREHELEMONGAGAPLATIGICLEERUDITROSSERECIT
CAFREINEBENOITNETTATENTATIVEENAIRAUQUELBETETURCCALIFATSENOMDALIB
ABASEVITPUREDEDACSUBMERSIONIMPORTUNECRACMENACEVACILLACOETREINTEN
OSMASSESELLESDORMENTETCAXENIAMORTNEDESBOTSRIVEZLESETNADESERIALGU
EVARALEGARENTNAMORCERCOULEVRINEVALSERREFUTEROHPORCENEXILORPHEEMI
ROIRBRISEDUTOCCABOTINETNEDUPERECREGRETETERNELLOPINIATRELANNULABL
EMECALGERTUALELANICIDEMISSIONRUOSTRACISENOTARIALSIPEUQUALGERVIET
NAMELUCAMELEONISRAELBIAFRABALAMERDECELEZAPOTRELUCAJERUZALEMAHCEB
OXONONAECOPEHALEMAXIMUMESCALEDOSPARELERANGINUTILEMETROMANEICIGAM
ELLETUPERDRASAHTUASRUSECAINLIEDIMITELAVACHEANEPASESTIMERFLICASSE
RMENTERENGAGEREGITILEVITANERFALABATAILLETROMPEHEDOREELEGERIEPELE
ERAPESENILESAVERITENUEDUSERUMRUMEURALALAINEGELIFFEUTRINEVALLIEUC
RECHEERGOTPURBATIRCELIEUQUARMADASERVEIFETETEEBORGNASTULASTRESEDA
TIFOHCELERITESNEFFOLIEOHTUBEZLEBRIONECESSERACECAPSERATAVALISELAG
ENISELLIARDSICNIMASTERSICCOQNICEDRATSNILALUNEBREVETERCESENEGALAI
SUNSOLEILPERDRATABETISEHERITEEMOIDIEULAVEROLEDEROBALESERBEGLAUQU
EPISANCESTRALHEBREUGALBAETSEPTIMESEVERECESSERVIDEETNIETETANOSETN
ADESBOUSTROPHEDONREPUDIEBOISERREVELELAVAREMELOSILTABENIBRUTALTAB
LIERVILADIOSPILLESPALERETINELESELLACIDEMERCANTIFEUQUEJUDASREVECI
VETTEIMITABLETUASALERTESORTABLASONLEURCROCETNIERETNOSERCASSETILO
BAISERVILATOINUDESIRBRISEDECEDETROPEPERCEROCLUDETROMPELAMORTSLAM
ELELANABETIREVENUDESIRECETREPASREVECIVASILPORTESEPULCRALCEREPENT
IRCETECRITNEPERTURBELELUCREHARIDELLETAGABEGIENEMORDNILAPLAGENILE
CARTGEORGESPEREC


Ce texte est le plus long palindrome en français créé par Georges Peres.

Bonne chance pour la suite !
Co-auteur du cours de C++. ||| Posez vos questions sur le forum ||| Me contacter.
6 février 2009 à 20:41:29

Effectivement, j'ai bien fait de m'arrêter au niveau 1.

J'aurais jamais eu le temps à consacrer pour étudier comme il faut l'analyse fréquentielle et en faire un algorithme qui tourne avec la table de Vigenere.

Toutefois, je vais prendre le temps de lire ça en détail, ça m'instruira ;)
Surtout qu'il semble y avoir pas mal de STL que je connais pas :p

Bravo au gagnant, et merci à Nanoc pour sa patience ^^

edit : effectivement, j'étais jamais retourné sur http://www.sgi.com/. Comme je suis plus apte qu'avant à comprendre tout ça, je vais pouvoir me régaler :lol:
6 février 2009 à 21:09:33

@Xahell:

Disons que la version de iNaKoll est vraiment une version "de luxe". Il a vraiment poussé à fond le coté cryptanalyse et cheerché un moyen de réaliser le craquage de manière générique.
Du coté du code il a énormément utilisé la STL, ce qui est bien, mais comme toujours non obligatoire. Connaître la STL de fond en comble n'est pas nécessaire pour réussir ces exercices.
Savoir qu'il existe une fonction "find" est très bien, mais pas essentiel, si on ne le savait pas, on peut la reocer sois-même sans problème. Même si ça sera légèrement moins efficace.
Co-auteur du cours de C++. ||| Posez vos questions sur le forum ||| Me contacter.
7 février 2009 à 16:32:59

Salut, je suis nouveau dans les exos de Nanoc, pour envoyer son pogramme à Reponse_Exercice on fait comment, on envoie par mail sur nanoc.sdz@gmail.com ??
7 février 2009 à 16:37:59

Non. On utilise le système de MP du site.
Co-auteur du cours de C++. ||| Posez vos questions sur le forum ||| Me contacter.
7 février 2009 à 16:41:06

Ok donc le code on l'envoie par balise de code alors?
7 février 2009 à 16:49:31

volontiers.
Co-auteur du cours de C++. ||| Posez vos questions sur le forum ||| Me contacter.
17 février 2009 à 22:38:47

Exercice du mois de février 2009



Nom : Chiffres romains
Sujet : algorithmes, chaînes de caractères


Avant de repartir dans la cryptographie, il était temps d'avoir un exercice plus simple.

Vous connaissez certainement les chiffres romains et vous savez certainement que lorsqu'on a pas l'habitude de les utiliser, lire ou écrire un de ces nombres peu être fastidieux.
L'exerice de ce mois va justement résoudre ce problème en vous permettant de réaliser un traducteur chiffres arabes <-> chiffres romains.

Que sont les chiffres romains ?



Les romains utilisaient un système différent du notre pour représenter les chiffres. Ils utilisaient les principes suivants:

Les règles à utiliser varient selon les sources. Pour cet exercice, on prendra les règles précisées ci-dessous.


On utilise les symboles suivants:
  • I = 1
  • V = 5
  • X = 10
  • L = 50
  • C = 100
  • D = 500
  • M = 1000


Règle 1: On arrange ensuite les symboles dans l'ordre décroissant pour former un nombre qui sera lu en additionnant chacune des symboles.

Par exemple 26 peut s'écrire comme XXVI ou XXIIIIII ou encore XVVVI. La première version étant préférée car utilisant moins de symboles.

Règle 2: On peut utilise des soustractions en plaçant un (et uniquement un) symbole de petite valeur juste avant un symbole de plus grande valeur. Le résultat de cette manipulation est alors la différence entre le symbole le plus grand et le plus petit.

Exemple: IV = 5-1 = 4 ou bien CIX = 100 + 10 - 1 = 109

Règle 3: La soustraction ne peut se faire qu'avec les symboles suivants:
  • I devant V ou X
  • X devant L ou C
  • C devant D ou M


Ceci implique que 49 n'est pas IL mais XLIX

Règle 4: Il n'y a pas de nombres plus grands que 4999 dans ce système, ni de nombres plus petits que 1.

Règle 5: On utilise toujours la combinaison de symboles la plus courte.

Donc XXVI au lieu de XVVVI, mais XLIX au lieu de IL sinon on viole la règle 3.

L'exercice



Niveau 1



Comme vous pouvez vous en douter, votre programme devra "traduire" un nombre entier en chiffre romain (valide) et afficher le résultat dans la console.
Il devra également pouvoir traduire les chiffres romains sous forme de strings en nombres entiers.

Si un nombre est non-valide, le programme devra afficher un message d'erreur.

Entrez un nombre romain: XXVII
Votre nombre est: 27
Entrez un chiffre romain: DDXI
Votre chiffre est non-valide
...


Niveau 2



Si le nombre romain entré par l'utilisateur est non-valide, votre programme devra indiquer quelle règle est violée et proposer (si possible) une correction.

Entrez un nombre romain: XXXXI
Votre chiffre est non-valide. Il viole la règle 5: On peut l'écrire de manière plus courte.
Le résultat serait: XLI
Ce qui donne en chiffres arabes: 41


N'hésitez pas à poser des questions si vous en avez !

Vous avez jusqu'au 15 mars pour soumettre vos réponses à Réponse_Exercices.

Bonne chance à tous !

EDIT: Suppression du 0 pour éviter les ambiguités.
Co-auteur du cours de C++. ||| Posez vos questions sur le forum ||| Me contacter.
17 février 2009 à 23:13:54

Tiens, je vais m'essayer à celui là :) .

C'est vraiment une très bonne initiative de proposer des exercices, merci à toi !

Edit : je ne suis pas sur (c'est ne primaire qu'on voit les chiffre romains donc...), mais je crois que le 0 n'existe pas en chiffres romains... à confirmer.

Petite recherche : 13.1, grand 4 : Pas possible de représenter le chiffre 0 (c'est pas stupide l'explication ^^ )
18 février 2009 à 0:04:21

Oui. Mais pour cet exercice, on dira qu'ils existent.

C'est la même chose que pour les chiffres plus grand que 4999, les romains en utilisaient.
Co-auteur du cours de C++. ||| Posez vos questions sur le forum ||| Me contacter.
18 février 2009 à 0:13:50

Ah me*de, je vois pas du tout comment le mettre le 0... peut être l'ajouter comme simple caractère (rajouter un 0 à la suite du nombre quoi ^^ ).

Enfin, on verra !

Ps : Pourquoi pas plus grand que 4999 o_O ?
18 février 2009 à 0:28:32

Parce que le caractère pour 5000 est usuellement un <math>\(\overline{V}\)</math>. Ce qui n'est pas pratique à faire en console.

Et de toute façon si on a compris le principe de conversion jusqu'à 5000, on l'a compris jusqu'à n'importe quelle limite.
Co-auteur du cours de C++. ||| Posez vos questions sur le forum ||| Me contacter.
18 février 2009 à 10:12:56

Tiens c'est marrant, j'ai fait ça en algo quand j'en faisais... si j'ai un peu de temps jvais essayer de le coder..
18 février 2009 à 12:17:17

tu es sur que la limite n'est pas plutot 3999?
ou alors comment on ecrit 4999 sans utiliser le caractère 5000?
Anonyme
18 février 2009 à 12:59:47

MMMMCMXCIX

Mais en fait, on peut aller plus loin, non ?

9999 : MMMMMMMMMCMXCIX
18 février 2009 à 15:17:16

Bien sûr qu'on peut aller plus loin avec ce système sans introduire de nouveau symbole.

Il fallait bien fixer une limite quelque part et je l'ai mise à 4999 pour qu'il y ait un cas spécial dans votre algo.
Co-auteur du cours de C++. ||| Posez vos questions sur le forum ||| Me contacter.
18 février 2009 à 19:09:04

j'ai bien envie d'essayer
mais ca a l'air quand même super compliqué

on a le droit de faire un switch avec tous les cas possibles ?? :-°
switch (nombre)
{
case 1: 
return I
break;
case 2: 
return II
break;
case 3: 
return III
break;
case 4: 
return IV
break;
}

non je rigole c'est pas le but ^^
18 février 2009 à 21:05:45

Même si ce n'était pas aberrant comme méthode ce n'est pas possible parce que le but c'est de traduire le romain en arabe. Donc ça ne passerait pas dans un switch. (une suite de else if peut-être ... :-° )
18 février 2009 à 21:15:42

Citation : hilnius


On a le droit de faire un switch avec tous les cas possibles ?? :-°

switch (nombre)
{
case 1: 
return I
break;
case 2: 
return II
break;
case 3: 
return III
break;
case 4: 
return IV
break;
}




Disons que si tu me sors un code en méta-programmation qui fait l'équivalent de ton switch pourquoi pas. :-°
Co-auteur du cours de C++. ||| Posez vos questions sur le forum ||| Me contacter.
18 février 2009 à 23:27:12

<hs>

Citation : Nanoc

Citation : hilnius


On a le droit de faire un switch avec tous les cas possibles ?? :-°

switch (nombre)
{
case 1: 
return I
break;
case 2: 
return II
break;
case 3: 
return III
break;
case 4: 
return IV
break;
}




Disons que si tu me sors un code en méta-programmation qui fait l'équivalent de ton switch pourquoi pas. :-°



C'est quoi la... méta-programmation ? J'ai cherché sur Wikipédia et j'ai rien pigé :D

</hs>

Sinon, comment on doit implémenter le concept du 0 ? Parce que j'ai codé une petite fonction, mais je suis pas sur que c'est le but recherché :D .
Enfin, voilà comment je procède :

Citation : Mon implémentation du 0

On a une partie du chiffre convertit en chiffres arabes, et on rajoute un zéro à sa suite (on multiplie par 10... j'y pense, j'ai fait une vingtaine de lignes alors que j'ai juste à multiplier par 10 o_O*cours se suicider pour son intelligence bornée*)

Bon, sérieusement, un exemple :

Étant donné le chiffre romain MDLXO, on commence à le mettre en chiffre arabes... 1000 + 500 + 50 + 10 = 1560... et le O, donc on rajoute un 0 = 15'600.

C'est ça ? (bon, ici, ce n'est pas valide puisque le maximum est 4999 enfin, c'est un exemple :D )



Voilà, j'ai fini mes questions, je vais virer mes lignes de codes en trop et remplacer par une multiplication par 10 :)
18 février 2009 à 23:35:35

Non.. ou enfin, comme je l'ai compris, ce n'est pas ça.

Chaque symbole romain avait une valeur, mais, par exemple, II, ce n'est pas 11 mais 1 + 1 soit 2.

O, c'est donc un caractère qui a 0 comme valeur, soit MDLXO vaut la même chose que MDLX et donc que MDLXO n'est pas valide (puisqu'il y a une façon plus courte de l'écrire).

O représenterait donc tout simplement le nombre 0!...
18 février 2009 à 23:38:57

Mais le nombre 0 n'existe pas chez les romains... ou alors, on ne pourrais l'utiliser que si on met 0... donc, O ne sert à rien... j'ai rien pigé ! (tant pis, je garde ma solution de * 10 en attendant que Nanoc revienne pour donner des précisions quand à ce petit problème ^^ )
Anonyme
18 février 2009 à 23:45:56

Amha, tu devrais virer le zéro Nanoc, il n'existait pas chez les Romains, et ça embrouille presque plus qu'autre chose ;) .
19 février 2009 à 0:39:46

Citation : Mikechaos

Non.. ou enfin, comme je l'ai compris, ce n'est pas ça.

Chaque symbole romain avait une valeur, mais, par exemple, II, ce n'est pas 11 mais 1 + 1 soit 2.

O, c'est donc un caractère qui a 0 comme valeur, soit MDLXO vaut la même chose que MDLX et donc que MDLXO n'est pas valide (puisqu'il y a une façon plus courte de l'écrire).

O représenterait donc tout simplement le nombre 0!...



Correct !

Citation : Cyprien_

Amha, tu devrais virer le zéro Nanoc, il n'existait pas chez les Romains, et ça embrouille presque plus qu'autre chose ;) .



Mouais. Je pensais pas que ça embrouillerait mais vous m'avez convaincu. J'enlève.



Co-auteur du cours de C++. ||| Posez vos questions sur le forum ||| Me contacter.
19 février 2009 à 16:29:16

disons que dans ce cas-là le O sert seulement à représenter 0 et uniquement cette valeur. Elle n'intervient nulle part ailleurs. C'est ce qui tend à "déstabiliser" les gens.