Bonjour <img src="/bundles/tinymce/vendor/tiny_mce/plugins/emotions/img/langue.png" alt=":p" class="smilies"><br>
Voilà : je voudrais faire un programme qui m'écrit toutes les suites de lettres possibles entre AAAAA et ZZZZZ, et qu'il stocke chaque suite dans un fichier.<br><br>
Sauf qu'il faut que mon programme soit le plus rapide possible. J'ai donc faire une boucle qui incrémente la variable nb, qui contient le nombre à transformer de base 10 à base 26. Je fais donc la conversion et j'obtiens donc 6 nombres entre 0 (A) et 25 (Z). Je voudrais donc écrire dans un fichier cette lettre. Je pourrais faire 26 tests pour savoir quel est cette lettre (Si lettre = 0, écrire A, si lettre = 1, ecrire B... Mais je trouve ça un peu long, et un peu bourrin.<br><br>
Je voudrais donc ajouter 65 à ce nombre, puis écrire dans mon fichier le code ascii de la lettre :<br>
A=65<br>
B=66<br>
...<br>
Ce qui ferait que je n'aurais pas de tests à effectuer.<br><br>
Comment faire ?<br><br>
Merci d'avance <img src="/bundles/tinymce/vendor/tiny_mce/plugins/emotions/img/hihi.png" alt="^^" class="smilies"><br><br>
--EDIT--<br>
Oupss... J'ai posté trop vite.<br><br>
J'arrive à faire ce que je veux faire via un tableau de char... :<br><pre class="brush: cpp;">char a=66;
cout << a << endl;
</pre><br>
Désolé pour le dérangement !Le 29 septembre 2010 à 9:32:43
Bonjour
Voilà : je voudrais faire un programme qui m'écrit toutes les suites de lettres possibles entre AAAAA et ZZZZZ, et qu'il stocke chaque suite dans un fichier.
Sauf qu'il faut que mon programme soit le plus rapide possible. J'ai donc faire une boucle qui incrémente la variable nb, qui contient le nombre à transformer de base 10 à base 26. Je fais donc la conversion et j'obtiens donc 6 nombres entre 0 (A) et 25 (Z). Je voudrais donc écrire dans un fichier cette lettre. Je pourrais faire 26 tests pour savoir quel est cette lettre (Si lettre = 0, écrire A, si lettre = 1, ecrire B... Mais je trouve ça un peu long, et un peu bourrin.
Je voudrais donc ajouter 65 à ce nombre, puis écrire dans mon fichier le code ascii de la lettre :
A=65
B=66
...
Ce qui ferait que je n'aurais pas de tests à effectuer.
Comment faire ?
Merci d'avance
--EDIT--
Oupss... J'ai posté trop vite.
J'arrive à faire ce que je veux faire via un tableau de char... :
L'obfuscation ? C'est quoi le rapport ? Ce n'est pas dissimuler une information sous une masse de fausses ?<br><br>
En fait comme je veux avoir 6 caractères, for (char c='A' ; c<='Z' ; ++c) ne me permet pas de le faire. Sauf si on peut faire for ([inconnu] c='AAAAAA' ; c<='ZZZZZZ' ; ++c)<br><br>
Est-ce possible ? Si oui comment ?<br><br>
Merci d'avance <img src="/bundles/tinymce/vendor/tiny_mce/plugins/emotions/img/hihi.png" alt="^^" class="smilies"><br><br>
--EDIT--<br>
Je pourrais utiliser ta technique en imbriquant ces conditions... Je vais regarder. Mais si vous avez une solution pour le faire directement pour optimiser le code, je suis prenant !<br>Le 29 septembre 2010 à 14:25:38
L'obfuscation ? C'est quoi le rapport ? Ce n'est pas dissimuler une information sous une masse de fausses ?
En fait comme je veux avoir 6 caractères, for (char c='A' ; c<='Z' ; ++c) ne me permet pas de le faire. Sauf si on peut faire for ([inconnu] c='AAAAAA' ; c<='ZZZZZZ' ; ++c)
Est-ce possible ? Si oui comment ?
Merci d'avance
--EDIT--
Je pourrais utiliser ta technique en imbriquant ces conditions... Je vais regarder. Mais si vous avez une solution pour le faire directement pour optimiser le code, je suis prenant !
Obfusquer, c'est écrire 65 au lieu de 'A'. 65 est une constante magique que tout le monde ne connaitra pas par coeur, et en plus c'est un nombre. 'A', ben ... c'est un caractère. C'est sémantiquement très fort et sans le moindre doute quant à nos intention. Et en plus, c'est facile à maintenir.<br><br>
Tu devras réaliser 26^6 itérations. Donc, avoir 6 boucles imbriquées est la solution canonique.<br>
Tu pourras très certainement l'émuler avec un curseur à déplacer, mais de nouveau, ce sera de l'obfuscation : un code plus compliqué, incompréhensible au premier abord, et certainement plus lent par la même occasion.Le 29 septembre 2010 à 14:36:11
Obfusquer, c'est écrire 65 au lieu de 'A'. 65 est une constante magique que tout le monde ne connaitra pas par coeur, et en plus c'est un nombre. 'A', ben ... c'est un caractère. C'est sémantiquement très fort et sans le moindre doute quant à nos intention. Et en plus, c'est facile à maintenir.
Tu devras réaliser 26^6 itérations. Donc, avoir 6 boucles imbriquées est la solution canonique.
Tu pourras très certainement l'émuler avec un curseur à déplacer, mais de nouveau, ce sera de l'obfuscation : un code plus compliqué, incompréhensible au premier abord, et certainement plus lent par la même occasion.
Mon but n'est pas de cacher mon code... Juste qu'il soit le plus rapide possible.<br><br>
Et à quoi servirait le curseur ? Je n'ai pas compris...<br><br>
Et comment concaténer char et string ? J'ai fait :<br><pre class="brush: cpp;">char a='A';
char b='B';
string chaine2 = a+b;
cout << chaine2 << endl;
</pre><br>
Et j'ai une erreur :<br><pre class="brush: plain;">main.cpp:42: error: invalid conversion from ‘int’ to ‘const char*’
main.cpp:42: error: initializing argument 1 of ‘std::basic_string<_CharT, _Traits, _Alloc>::basic_string(const _CharT*, const _Alloc&) [with _CharT = char, _Traits = std::char_traits<char>, _Alloc = std::allocator<char>]’</pre><br><br>
Comment faire ?Le 29 septembre 2010 à 14:44:11
Mon but n'est pas de cacher mon code... Juste qu'il soit le plus rapide possible.
Et à quoi servirait le curseur ? Je n'ai pas compris...
Et comment concaténer char et string ? J'ai fait :
Je vais essayer ce que tu as mis, mais entre temps j'ai trouvé <a href="http://carl.seleborg.free.fr/cpp/cours/chap2/strings.html">ça</a> (en bas : conversion depuis d'autres types.)<br>
Ce qui me donne à la fin ce code qui marche plutôt bien :<br><pre class="brush: cpp;">for(char lettre1='A'; lettre1<='Z'; lettre1++)
{
for(char lettre2='A'; lettre2<='Z'; lettre2++)
{
for(char lettre3='A'; lettre3<='Z'; lettre3++)
{
for(char lettre4='A'; lettre4<='Z'; lettre4++)
{
strstream s;
s << lettre1 << lettre2 << lettre3 << lettre4 << endl;
string s2 = s.str(); // conversion en string
cout << s.str(); // affichage
}
}
}
}
</pre><br><br>
J'essaye ton code et je te redis !<br><br>
--EDIT--<br>
Je viens de l'essayer et il plante :<br><pre class="brush: cpp;">char a='A';
char b='B';
string test = string(a)+b;
cout << test << endl;
</pre><br><pre class="brush: plain;">main.cpp:51: error: invalid conversion from ‘char’ to ‘const char*’
main.cpp:51: error: initializing argument 1 of ‘std::basic_string<_CharT, _Traits, _Alloc>::basic_string(const _CharT*, const _Alloc&) [with _CharT = char, _Traits = std::char_traits<char>, _Alloc = std::allocator<char>]’</pre><br>
J'ai essayé plusieurs syntaxes de string(a)+b, mais rien... (string(a+b), string(a)+string(b)...)<br><br>
Une idée ?<br><br>
Note : j'aimerais trouver une autre méthode que celle que j'ai trouvée car à la compilation j'ai un message qui me dit que cette librairie va être remplacée... Donc si vous connaissez celle qui la remplace, dites le moi <img src="/bundles/tinymce/vendor/tiny_mce/plugins/emotions/img/hihi.png" alt="^^" class="smilies"><br><pre class="brush: plain;">/usr/include/c++/4.3/backward/backward_warning.h:33:2: warning: #warning This file includes at least one deprecated or antiquated header which may be removed without further notice at a future date. Please use a non-deprecated interface with equivalent functionality instead. For a listing of replacement headers and interfaces, consult the file backward_warning.h. To disable this warning use -Wno-deprecated.</pre><br><br>
Merci d'avance <img src="/bundles/tinymce/vendor/tiny_mce/plugins/emotions/img/hihi.png" alt="^^" class="smilies"><br><br>
--EDIT2--<br>
#include <sstream> (stringstream) à l'air d'être mieux acceptée. Après, si vous avez des informations sur le technique de lmghs dites le moi <img src="/bundles/tinymce/vendor/tiny_mce/plugins/emotions/img/hihi.png" alt="^^" class="smilies"><br><br>
Et merci beaucoup lmghs pour l'aide que tu m'as apporté !Le 29 septembre 2010 à 15:17:38
Je vais essayer ce que tu as mis, mais entre temps j'ai trouvé ça (en bas : conversion depuis d'autres types.)
Ce qui me donne à la fin ce code qui marche plutôt bien :
J'ai essayé plusieurs syntaxes de string(a)+b, mais rien... (string(a+b), string(a)+string(b)...)
Une idée ?
Note : j'aimerais trouver une autre méthode que celle que j'ai trouvée car à la compilation j'ai un message qui me dit que cette librairie va être remplacée... Donc si vous connaissez celle qui la remplace, dites le moi
/usr/include/c++/4.3/backward/backward_warning.h:33:2: warning: #warning This file includes at least one deprecated or antiquated header which may be removed without further notice at a future date. Please use a non-deprecated interface with equivalent functionality instead. For a listing of replacement headers and interfaces, consult the file backward_warning.h. To disable this warning use -Wno-deprecated.
Merci d'avance
--EDIT2--
#include <sstream> (stringstream) à l'air d'être mieux acceptée. Après, si vous avez des informations sur le technique de lmghs dites le moi
Et merci beaucoup lmghs pour l'aide que tu m'as apporté !
Tiens. C'est vrai.<br>
Il fallait utiliser string(1,a).<br><br>
Autre façon (non testée): <br><pre class="brush: cpp;">string res(6 /*, ' ' ?*/);
res[0] = 'A';
for (char & a = res[0] ; a <= 'Z' ; ++a) {
res[1] = 'A';
for (char & b = res[1] ; b <= 'Z' ; ++b) {
res[2] = 'A';
....
res[5] = 'A';
for (char & f = res[5] ; f <= 'Z' ; ++f) {
cout << res;
}
...
}
}
</pre><br>Le 29 septembre 2010 à 15:47:53
Tiens. C'est vrai.
Il fallait utiliser string(1,a).
Autre façon (non testée):
string res(6 /*, ' ' ?*/);
res[0] = 'A';
for (char & a = res[0] ; a <= 'Z' ; ++a) {
res[1] = 'A';
for (char & b = res[1] ; b <= 'Z' ; ++b) {
res[2] = 'A';
....
res[5] = 'A';
for (char & f = res[5] ; f <= 'Z' ; ++f) {
cout << res;
}
...
}
}
Merci beaucoup lmghs pour ton aide <img src="/bundles/tinymce/vendor/tiny_mce/plugins/emotions/img/hihi.png" alt="^^" class="smilies"> Ca marche !<br>
Voilà le fichier final :<br><pre class="brush: cpp;">#include <iostream>
#include <math.h>
#include <string.h>
#include <sstream>
#include <fstream>
using namespace std;
int main()
{
ofstream fichier("/home/leo/Desktop/programmation/BIOS/bigdico", ios::out | ios::trunc); //déclaration du flux et ouverture du fichier
if(fichier) // si l'ouverture a réussi
{
// instructions
for(char lettre1='A'; lettre1<='Z'; lettre1++)
{
for(char lettre2='A'; lettre2<='Z'; lettre2++)
{
for(char lettre3='A'; lettre3<='Z'; lettre3++)
{
for(char lettre4='A'; lettre4<='Z'; lettre4++)
{
for(char lettre5='A'; lettre5<='Z'; lettre5++)
{
for(char lettre6='A'; lettre6<='Z'; lettre6++)
{
stringstream s;
s << lettre1 << lettre2 << lettre3 << lettre4 << lettre5 << lettre6 << endl;
string s2 = s.str(); // conversion en string
cout << s2; // affichage
fichier << s2;
}
}
}
}
}
}
fichier.close(); // on referme le fichier
}
else
cerr << "Erreur à l'ouverture !" << endl;
return 0;
}
</pre><br><br>
Bon, il faut pas être pressé... (en 8mn il a à peine fini le A pour première lettre.) et si mes calculs sont bon (bon, je les ai fait à 22h hier soir, donc il sont peux être faux) il prendra environ 1.2Go...<br><br>
Par contre, peux-tu expliquer à quoi correspond les param. de string(1,a) ? A quoi correspond le 1 ? il faut donc faire string(1,a)+string(1,b) si j'ai bien compris.<br><br>
Et pourrais-tu m'expliquer comment fonctionne ton 2eme programme ? Je ne comprend même pas la première ligne : 6 /*, ' ' ?*/. Les /* */ sont juste des commentaires où ils font parti intégrale de la chaine ? Et à quoi correspond le 6 ? Et pourquoi est-ce que tu considère res comme un tableau ? J'avoue que je suis un peu perdu...Le 29 septembre 2010 à 16:07:17
Merci beaucoup lmghs pour ton aide Ca marche !
Voilà le fichier final :
Bon, il faut pas être pressé... (en 8mn il a à peine fini le A pour première lettre.) et si mes calculs sont bon (bon, je les ai fait à 22h hier soir, donc il sont peux être faux) il prendra environ 1.2Go...
Par contre, peux-tu expliquer à quoi correspond les param. de string(1,a) ? A quoi correspond le 1 ? il faut donc faire string(1,a)+string(1,b) si j'ai bien compris.
Et pourrais-tu m'expliquer comment fonctionne ton 2eme programme ? Je ne comprend même pas la première ligne : 6 /*, ' ' ?*/. Les /* */ sont juste des commentaires où ils font parti intégrale de la chaine ? Et à quoi correspond le 6 ? Et pourquoi est-ce que tu considère res comme un tableau ? J'avoue que je suis un peu perdu...
string(1,' ') fait appel à la 8e surcharge: <a href="http://dinkumware.com/manuals/?manual=compleat&page=string2.html#basic_string::basic_string">http://dinkumware.com/manuals/?manual= [...] :basic_string</a><br>
Et donc "string(1, a) + b" suffit. <br><br>
Les commentaires, correspondent à un doute de ma part. Je n'ai pas l'impression qu'il existe une surcharge du constructeur qui ne prennent qu'un seul argument => string(6, 'A') ira très bien.<br>
Le 6 sert à dire que la chaine fera donc 6 caractères. Et std::string met à disposition un opérateur d'accès indexé qui renvoie une référence vers le n-ième caractère demandé.<br>
J'aurai tout aussi bien pu écrire: "for ( res[0] = 'A' ; res[0] <= 'Z' ; ++res[0])" six fois.<br>
Cela évite de construire une chaine à chaque itération.<br><br>
Accessoirement, le fichier fera plutôt entre 2 et 2.3 Go (26^6 * (6+1 +1 si format dos) / 1024 /1024 -> 2062/23xx)Le 29 septembre 2010 à 16:30:15
Les commentaires, correspondent à un doute de ma part. Je n'ai pas l'impression qu'il existe une surcharge du constructeur qui ne prennent qu'un seul argument => string(6, 'A') ira très bien.
Le 6 sert à dire que la chaine fera donc 6 caractères. Et std::string met à disposition un opérateur d'accès indexé qui renvoie une référence vers le n-ième caractère demandé.
J'aurai tout aussi bien pu écrire: "for ( res[0] = 'A' ; res[0] <= 'Z' ; ++res[0])" six fois.
Cela évite de construire une chaine à chaque itération.
Accessoirement, le fichier fera plutôt entre 2 et 2.3 Go (26^6 * (6+1 +1 si format dos) / 1024 /1024 -> 2062/23xx)
Oh nonnnnnnn !!! Je viens de m'apercevoir après 2h45 que ce n'était pas des lettre majuscules, mais minuscules !!!!!<br><br>
Est-ce que vous connaissez une technique pour RAPIDEMENT passer un fichier de 1,7Go (j'ai arrété à la 1ere lettre V) de majuscule à minuscule ?Le 29 septembre 2010 à 18:41:37
Oh nonnnnnnn !!! Je viens de m'apercevoir après 2h45 que ce n'était pas des lettre majuscules, mais minuscules !!!!!
Est-ce que vous connaissez une technique pour RAPIDEMENT passer un fichier de 1,7Go (j'ai arrété à la 1ere lettre V) de majuscule à minuscule ?
Tu pense ?<br>
Bon ben je ferais peut-être ça demain si j'ai le temps...<br><br>
Merci beaucoup pour ton aide. Je vous redis si il y a du nouveau.Le 29 septembre 2010 à 19:14:23
Tu pense ?
Bon ben je ferais peut-être ça demain si j'ai le temps...
Merci beaucoup pour ton aide. Je vous redis si il y a du nouveau.
<p><strong>Citation : lmghs</strong></p><blockquote>Obfusquer, c'est écrire 65 au lieu de 'A'. 65 est une constante magique que tout le monde ne connaitra pas par coeur, et en plus c'est un nombre. 'A', ben ... c'est un caractère. C'est sémantiquement très fort et sans le moindre doute quant à nos intention. Et en plus, c'est facile à maintenir.<br><br>
Tu devras réaliser 26^6 itérations. Donc, avoir 6 boucles imbriquées est la solution canonique.<br>
Tu pourras très certainement l'émuler avec un curseur à déplacer, mais de nouveau, ce sera de l'obfuscation : un code plus compliqué, incompréhensible au premier abord, et certainement plus lent par la même occasion.</blockquote><br>
Il me semble aussi que c'est une histoire de portabilité, une machine pouvant posséder une table ASCII différente.Le 30 septembre 2010 à 6:50:04
Citation : lmghs
Obfusquer, c'est écrire 65 au lieu de 'A'. 65 est une constante magique que tout le monde ne connaitra pas par coeur, et en plus c'est un nombre. 'A', ben ... c'est un caractère. C'est sémantiquement très fort et sans le moindre doute quant à nos intention. Et en plus, c'est facile à maintenir.
Tu devras réaliser 26^6 itérations. Donc, avoir 6 boucles imbriquées est la solution canonique.
Tu pourras très certainement l'émuler avec un curseur à déplacer, mais de nouveau, ce sera de l'obfuscation : un code plus compliqué, incompréhensible au premier abord, et certainement plus lent par la même occasion.
Il me semble aussi que c'est une histoire de portabilité, une machine pouvant posséder une table ASCII différente.
Que c'est moche toutes ces boucles imbriquées.<br><pre class="brush: cpp;">void inscrire_liste_chaines(std::ostream & out) /* tous les flux d'écriture héritent de ostream (si je ne me trompe pas) */
{
#define N 6 /* définit le nombre de caractères à mettre */
char tab[N + 1]; /* un tableau pour retenir la combinaison actuelle */
/* on remplit ce tableau */
for(unsigned int i = 0;i<N;i++)
tab[i] = 'a';
tab[N] = '\0';
/* on fait la boucle jusqu'à ce que le premier caractère ne soit plus une majuscule */
while(tab[0] <= 'z')
{
/* on affiche dans n'importe quel flux la chaine */
out << tab << std::endl;
/* on incrémente le dernier caractère */
tab[N-1]++;
/* si on a un caractère supérieur à Z, on le fait revenir à A en augmentant la taille du précédent */
for(unsigned int i = N-1;i > 0;i--)
{
if(tab[i] > 'z')
{
tab[i] = 'a';
tab[i-1]++;
}
else
break;
}
}
#undef N
}
</pre><br>
On aura même la liste dans l'ordre croissant.<br>
Si on veut afficher la liste dans plusieurs flux, il suffit de modifier très légèrement la fonction.<br><br>
EDIT : modification du code pour avoir des minuscules.<br>
Et n'oublie pas qu'il est plus rapide d'écrire dans un fichier que d'écrire dans std::cout (car ça doit être affiché à l'écran immédiatement).<br>
Petite info : en 5 minutes qu'il tourne chez moi, il a rempli près de 300 Mio.Le 30 septembre 2010 à 7:05:45
Que c'est moche toutes ces boucles imbriquées.
void inscrire_liste_chaines(std::ostream & out) /* tous les flux d'écriture héritent de ostream (si je ne me trompe pas) */
{
#define N 6 /* définit le nombre de caractères à mettre */
char tab[N + 1]; /* un tableau pour retenir la combinaison actuelle */
/* on remplit ce tableau */
for(unsigned int i = 0;i<N;i++)
tab[i] = 'a';
tab[N] = '\0';
/* on fait la boucle jusqu'à ce que le premier caractère ne soit plus une majuscule */
while(tab[0] <= 'z')
{
/* on affiche dans n'importe quel flux la chaine */
out << tab << std::endl;
/* on incrémente le dernier caractère */
tab[N-1]++;
/* si on a un caractère supérieur à Z, on le fait revenir à A en augmentant la taille du précédent */
for(unsigned int i = N-1;i > 0;i--)
{
if(tab[i] > 'z')
{
tab[i] = 'a';
tab[i-1]++;
}
else
break;
}
}
#undef N
}
On aura même la liste dans l'ordre croissant.
Si on veut afficher la liste dans plusieurs flux, il suffit de modifier très légèrement la fonction.
EDIT : modification du code pour avoir des minuscules.
Et n'oublie pas qu'il est plus rapide d'écrire dans un fichier que d'écrire dans std::cout (car ça doit être affiché à l'écran immédiatement).
Petite info : en 5 minutes qu'il tourne chez moi, il a rempli près de 300 Mio.
Moche mouais. Pas évident.<br>
Tout le monde ne va pas rentrer dedans aussi facilement. De plus, je ne serai pas surpris de constater un petit avantage de rapidité pour la version à 6 boucles.<br><br>
PS: const, c'est bien.Le 30 septembre 2010 à 8:48:58
Moche mouais. Pas évident.
Tout le monde ne va pas rentrer dedans aussi facilement. De plus, je ne serai pas surpris de constater un petit avantage de rapidité pour la version à 6 boucles.
Euh ca serait pas pour bruteforcer un mot de passe ton code?<br><br>
Pour info <br>
26^6 = 308 915 776 <br>
52^6 = 19 770 609 664Le 30 septembre 2010 à 12:43:27
Euh ca serait pas pour bruteforcer un mot de passe ton code?
Pour info
26^6 = 308 915 776
52^6 = 19 770 609 664
Les réinitialisations et incrémentations sont cachées dans les boucles for. Si on regarde, on verra que je fais exactement les mêmes opérations. Par ailleurs, je remplis le tampon en prenant 6 caractères à la fois.<br>
Par ailleurs, et je l'ai déjà dit, l'opération la plus coûteuse est la mise dans un flux de chaque donnée. Il serait donc bon d'optimiser cette fonction pour le résultat attendu.<br>
Je pourrais donc réécrire la ligne :<br><pre class="brush: cpp;">out << tab << std::endl;
</pre><br>
en écrivant :<br><pre class="brush: cpp;">out.write(tab,N + 1);
</pre><br>
Evidemment, il faudra avoir modifié la case tab[N] en '\n' au lieu de '\0' (write écrit les N + 1 premiers caractères de tab, sans vérification de '\0').<br><br>
Pour ceux qui n'auraient pas suivi :<br><pre class="brush: cpp;">void inscrire_liste_chaines(std::ostream & out) /* tous les flux d'écriture héritent de ostream (si je ne me trompe pas) */
{
unsigned int const N = 6; /* définit le nombre de caractères à mettre */
char tab[N + 1]; /* un tableau pour retenir la combinaison actuelle */
/* on remplit ce tableau */
for(unsigned int i = 0;i<N;i++)
tab[i] = 'a';
tab[N] = '\n';
/* on fait la boucle jusqu'à ce que le premier caractère ne soit plus une majuscule */
while(tab[0] <= 'z')
{
/* on affiche dans n'importe quel flux la chaine */
out.write(tab,N+1);
/* on incrémente le dernier caractère */
tab[N-1]++;
/* si on a un caractère supérieur à Z, on le fait revenir à A en augmentant la taille du précédent */
for(unsigned int i = N-1;i > 0;i--)
{
if(tab[i] > 'z')
{
tab[i] = 'a';
tab[i-1]++;
}
else
break;
}
}
}
</pre><br>
Je vais tester sous peu pour voir si l'exécution est plus rapide. (pour information, ma première exécution a duré environ 2 164 secondes)<br><br>
EDIT pour le message plus haut : pourquoi voit-on tout de suite une tentative de piratage quand quelque chose s'y rapproche ?<br>
Imaginons que je veuille coder un cryptage RSA. On va tout de suite me dire "c'est pour faire l'attaque par le milieu ?". Ca n'aurait absolument aucun sens.<br><br>
EDIT : savoir ce qui prend le plus de temps de calculs permet d'améliorer nettement la vitesse d'exécution : 512 secondes (moins de 10 minutes) au lieu de 2 164 (environ 35 minutes).Le 30 septembre 2010 à 12:47:41
Les réinitialisations et incrémentations sont cachées dans les boucles for. Si on regarde, on verra que je fais exactement les mêmes opérations. Par ailleurs, je remplis le tampon en prenant 6 caractères à la fois.
Par ailleurs, et je l'ai déjà dit, l'opération la plus coûteuse est la mise dans un flux de chaque donnée. Il serait donc bon d'optimiser cette fonction pour le résultat attendu.
Je pourrais donc réécrire la ligne :
out << tab << std::endl;
en écrivant :
out.write(tab,N + 1);
Evidemment, il faudra avoir modifié la case tab[N] en '\n' au lieu de '\0' (write écrit les N + 1 premiers caractères de tab, sans vérification de '\0').
Pour ceux qui n'auraient pas suivi :
void inscrire_liste_chaines(std::ostream & out) /* tous les flux d'écriture héritent de ostream (si je ne me trompe pas) */
{
unsigned int const N = 6; /* définit le nombre de caractères à mettre */
char tab[N + 1]; /* un tableau pour retenir la combinaison actuelle */
/* on remplit ce tableau */
for(unsigned int i = 0;i<N;i++)
tab[i] = 'a';
tab[N] = '\n';
/* on fait la boucle jusqu'à ce que le premier caractère ne soit plus une majuscule */
while(tab[0] <= 'z')
{
/* on affiche dans n'importe quel flux la chaine */
out.write(tab,N+1);
/* on incrémente le dernier caractère */
tab[N-1]++;
/* si on a un caractère supérieur à Z, on le fait revenir à A en augmentant la taille du précédent */
for(unsigned int i = N-1;i > 0;i--)
{
if(tab[i] > 'z')
{
tab[i] = 'a';
tab[i-1]++;
}
else
break;
}
}
}
Je vais tester sous peu pour voir si l'exécution est plus rapide. (pour information, ma première exécution a duré environ 2 164 secondes)
EDIT pour le message plus haut : pourquoi voit-on tout de suite une tentative de piratage quand quelque chose s'y rapproche ?
Imaginons que je veuille coder un cryptage RSA. On va tout de suite me dire "c'est pour faire l'attaque par le milieu ?". Ca n'aurait absolument aucun sens.
EDIT : savoir ce qui prend le plus de temps de calculs permet d'améliorer nettement la vitesse d'exécution : 512 secondes (moins de 10 minutes) au lieu de 2 164 (environ 35 minutes).
<p><strong>Citation : Alienore</strong></p><blockquote>Les réinitialisations et incrémentations sont cachées dans les boucles for. Si on regarde, on verra que je fais exactement les mêmes opérations. Par ailleurs, je remplis le tampon en prenant 6 caractères à la fois.<br>
Par ailleurs, et je l'ai déjà dit, l'opération la plus coûteuse est la mise dans un flux de chaque donnée. Il serait donc bon d'optimiser cette fonction pour le résultat attendu.<br>
Je pourrais donc réécrire la ligne :<br><br><pre class="brush: cpp;">out << tab << std::endl;
</pre>
<br><br>
en écrivant :<br><br><pre class="brush: cpp;">out.write(tab,N + 1);
</pre>
<br><br>
Evidemment, il faudra avoir modifié la case tab[N] en '\n' au lieu de '\0' (write écrit les N + 1 premiers caractères de tab, sans vérification de '\0').<br><br>
Pour ceux qui n'auraient pas suivi :<br><br><pre class="brush: cpp;">void inscrire_liste_chaines(std::ostream & out) /* tous les flux d'écriture héritent de ostream (si je ne me trompe pas) */
{
unsigned int const N = 6; /* définit le nombre de caractères à mettre */
char tab[N + 1]; /* un tableau pour retenir la combinaison actuelle */
/* on remplit ce tableau */
for(unsigned int i = 0;i<N;i++)
tab[i] = 'a';
tab[N] = '\n';
/* on fait la boucle jusqu'à ce que le premier caractère ne soit plus une majuscule */
while(tab[0] <= 'z')
{
/* on affiche dans n'importe quel flux la chaine */
out.write(tab,N+1);
/* on incrémente le dernier caractère */
tab[N-1]++;
/* si on a un caractère supérieur à Z, on le fait revenir à A en augmentant la taille du précédent */
for(unsigned int i = N-1;i > 0;i--)
{
if(tab[i] > 'z')
{
tab[i] = 'a';
tab[i-1]++;
}
else
break;
}
}
}
</pre>
<br><br><br>
Je vais tester sous peu pour voir si l'exécution est plus rapide. (pour information, ma première exécution a duré environ 2 164 secondes)<br><br>
EDIT pour le message plus haut : pourquoi voit-on tout de suite une tentative de piratage quand quelque chose s'y rapproche ?<br>
Imaginons que je veuille coder un cryptage RSA. On va tout de suite me dire "c'est pour faire l'attaque par le milieu ?". Ca n'aurait absolument aucun sens.<br><br>
EDIT : savoir ce qui prend le plus de temps de calculs permet d'améliorer nettement la vitesse d'exécution : 512 secondes (moins de 10 minutes) au lieu de 2 164 (environ 35 minutes). </blockquote><br>
Merci pour ce code ! il est très formateur. J'avais pensé à faire un code de ce type là mais j'avoue que j'avais peur que ça se complique. J'ai bien analysé le code et j'ai tout compris !<br><br>
Merci beaucoup pour ce code très simple à paramétrer, et plus rapide de surcroit <img src="/bundles/tinymce/vendor/tiny_mce/plugins/emotions/img/hihi.png" alt="^^" class="smilies"><br><br>
Et comment as-tu fais pour chronométrer ? Tu as mis une variable qui stocke la variable de début, puis un pour la variable de fin et tu compares les 2 ?<br><br>
Merci beaucoup !Le 30 septembre 2010 à 13:20:42
Citation : Alienore
Les réinitialisations et incrémentations sont cachées dans les boucles for. Si on regarde, on verra que je fais exactement les mêmes opérations. Par ailleurs, je remplis le tampon en prenant 6 caractères à la fois.
Par ailleurs, et je l'ai déjà dit, l'opération la plus coûteuse est la mise dans un flux de chaque donnée. Il serait donc bon d'optimiser cette fonction pour le résultat attendu.
Je pourrais donc réécrire la ligne :
out << tab << std::endl;
en écrivant :
out.write(tab,N + 1);
Evidemment, il faudra avoir modifié la case tab[N] en '\n' au lieu de '\0' (write écrit les N + 1 premiers caractères de tab, sans vérification de '\0').
Pour ceux qui n'auraient pas suivi :
void inscrire_liste_chaines(std::ostream & out) /* tous les flux d'écriture héritent de ostream (si je ne me trompe pas) */
{
unsigned int const N = 6; /* définit le nombre de caractères à mettre */
char tab[N + 1]; /* un tableau pour retenir la combinaison actuelle */
/* on remplit ce tableau */
for(unsigned int i = 0;i<N;i++)
tab[i] = 'a';
tab[N] = '\n';
/* on fait la boucle jusqu'à ce que le premier caractère ne soit plus une majuscule */
while(tab[0] <= 'z')
{
/* on affiche dans n'importe quel flux la chaine */
out.write(tab,N+1);
/* on incrémente le dernier caractère */
tab[N-1]++;
/* si on a un caractère supérieur à Z, on le fait revenir à A en augmentant la taille du précédent */
for(unsigned int i = N-1;i > 0;i--)
{
if(tab[i] > 'z')
{
tab[i] = 'a';
tab[i-1]++;
}
else
break;
}
}
}
Je vais tester sous peu pour voir si l'exécution est plus rapide. (pour information, ma première exécution a duré environ 2 164 secondes)
EDIT pour le message plus haut : pourquoi voit-on tout de suite une tentative de piratage quand quelque chose s'y rapproche ?
Imaginons que je veuille coder un cryptage RSA. On va tout de suite me dire "c'est pour faire l'attaque par le milieu ?". Ca n'aurait absolument aucun sens.
EDIT : savoir ce qui prend le plus de temps de calculs permet d'améliorer nettement la vitesse d'exécution : 512 secondes (moins de 10 minutes) au lieu de 2 164 (environ 35 minutes).
Merci pour ce code ! il est très formateur. J'avais pensé à faire un code de ce type là mais j'avoue que j'avais peur que ça se complique. J'ai bien analysé le code et j'ai tout compris !
Merci beaucoup pour ce code très simple à paramétrer, et plus rapide de surcroit
Et comment as-tu fais pour chronométrer ? Tu as mis une variable qui stocke la variable de début, puis un pour la variable de fin et tu compares les 2 ?
<p><strong>Citation : Alienore</strong></p><blockquote>Les réinitialisations et incrémentations sont cachées dans les boucles for. Si on regarde, on verra que je fais exactement les mêmes opérations.</blockquote><br>
Pas de la même façon. Avec celle-ci, je ne suis pas sûr que le compilo puisse aussi bien exploiter le pipeline.Le 30 septembre 2010 à 13:40:55
Citation : Alienore
Les réinitialisations et incrémentations sont cachées dans les boucles for. Si on regarde, on verra que je fais exactement les mêmes opérations.
Pas de la même façon. Avec celle-ci, je ne suis pas sûr que le compilo puisse aussi bien exploiter le pipeline.
<p><strong>Citation : lmghs</strong></p><blockquote>
<p><strong>Citation : Alienore</strong></p>
<blockquote>Les réinitialisations et incrémentations sont cachées dans les boucles for. Si on regarde, on verra que je fais exactement les mêmes opérations.</blockquote>
<br>
Pas de la même façon. Avec celle-ci, je ne suis pas sûr que le compilo puisse aussi bien exploiter le pipeline.</blockquote> <br>
C'est à dire ? Qu'est-ce que tu entends par pipeline ? Ce n'est pas lorsque l'on met bout à bout plusieurs programmes ? En quoi est-ce que ca gène ?<br><br>
Et j'ai essayé la première version du programme à Alienore, et en fait elle à l'air plus longue (presque 1h pour seulement 5 caractères...). Je vais essayer l'autre version après.Le 30 septembre 2010 à 13:45:05
Citation : lmghs
Citation : Alienore
Les réinitialisations et incrémentations sont cachées dans les boucles for. Si on regarde, on verra que je fais exactement les mêmes opérations.
Pas de la même façon. Avec celle-ci, je ne suis pas sûr que le compilo puisse aussi bien exploiter le pipeline.
C'est à dire ? Qu'est-ce que tu entends par pipeline ? Ce n'est pas lorsque l'on met bout à bout plusieurs programmes ? En quoi est-ce que ca gène ?
Et j'ai essayé la première version du programme à Alienore, et en fait elle à l'air plus longue (presque 1h pour seulement 5 caractères...). Je vais essayer l'autre version après.
pipeline, déroulage de boucle, ... <a href="http://en.wikipedia.org/wiki/Loop_unwinding">http://en.wikipedia.org/wiki/Loop_unwinding</a><br>
(à noter que les -O2/3 (?) le réalise déjà pour nous)Le 30 septembre 2010 à 13:50:18
Donc en gros, si j'ai bien compris, pour le programme avec plein de boucle, il est plus rapide car le processeur peut pré calculer sur plusieurs "étages" alors que pour le 2eme programme, il est obligé de faire ligne par ligne et donc ne mobilise qu'une seule ligne ?<br><br>
C'est ça ? Si oui, qu'est-ce qui détermine si tel programme facilite le pipeline et quel autre non ?Le 30 septembre 2010 à 13:53:57
Donc en gros, si j'ai bien compris, pour le programme avec plein de boucle, il est plus rapide car le processeur peut pré calculer sur plusieurs "étages" alors que pour le 2eme programme, il est obligé de faire ligne par ligne et donc ne mobilise qu'une seule ligne ?
C'est ça ? Si oui, qu'est-ce qui détermine si tel programme facilite le pipeline et quel autre non ?
Cela est possible, mais il faudra vérifier.<br>
De toutes façons, comme signalé, c'est l'écriture fichier qui bouffera tout le temps.<br><br>
En général, plus la boucle sera simple, plus il sera facile pour le compilo de la dérouler.Le 30 septembre 2010 à 14:08:03
Cela est possible, mais il faudra vérifier.
De toutes façons, comme signalé, c'est l'écriture fichier qui bouffera tout le temps.
En général, plus la boucle sera simple, plus il sera facile pour le compilo de la dérouler.
Ma boucle permet de faire de façon très rapide un code demandant un nombre paramétrable de caractères.<br><br>
Pour le temps, j'ai juste écrit le main suivant :<br><pre class="brush: cpp;">#include <iostream>
#include <fstream>
#include <ctime>
int main()
{
std::ofstream test("test.txt",std::ios::out | std::ios::trunc);
time_t temps_debut = time(NULL);
inscrire_liste_chaines(test);
std::cout << time(NULL) - temps_debut << std::endl;
test.close();
return 0;
}
</pre>Le 30 septembre 2010 à 18:14:50
Ma boucle permet de faire de façon très rapide un code demandant un nombre paramétrable de caractères.
C'est vrai que ton code est sans contexte beaucoup plus paramétrable qu'avec les boucles imbriquées. C'est ce qui en fait sa force.<br><br>
Pour ce qui est de la rapidité, il faudra que je compare les 2 systèmes.<br><br>
PS : et j'ai fait tourner le programme avec les boucles sous un windows XP du lycée, il a écrit les 2.3 Go en environ 2heures sur le serveur. (je l'ai lancé avant les 2 heures de cours de français et j'ai mis le programme dans le systray <img src="/bundles/tinymce/vendor/tiny_mce/plugins/emotions/img/hihi.png" alt="^^" class="smilies"> Lorsque je suis revenu, il en était à la fin des x). Le fichier fait bien 2.3 Go comme tu l'avais dit <img src="/bundles/tinymce/vendor/tiny_mce/plugins/emotions/img/hihi.png" alt="^^" class="smilies"> : je n'avais pas compté le caractère entré -> seulement x6 au lieu de x7...<br><br><p><strong>Citation : lmghs</strong></p><blockquote>C'est vrai. Pour faire la même chose avec les imbrications, il faut sortir de la meta-prog (simple).</blockquote> <br>
Qu'est-ce que tu entends par "sortir de la meta-prog" ? C'est faire un programme beaucoup plus compliqué ?Le 1 octobre 2010 à 8:44:38
C'est vrai que ton code est sans contexte beaucoup plus paramétrable qu'avec les boucles imbriquées. C'est ce qui en fait sa force.
Pour ce qui est de la rapidité, il faudra que je compare les 2 systèmes.
PS : et j'ai fait tourner le programme avec les boucles sous un windows XP du lycée, il a écrit les 2.3 Go en environ 2heures sur le serveur. (je l'ai lancé avant les 2 heures de cours de français et j'ai mis le programme dans le systray Lorsque je suis revenu, il en était à la fin des x). Le fichier fait bien 2.3 Go comme tu l'avais dit : je n'avais pas compté le caractère entré -> seulement x6 au lieu de x7...
Citation : lmghs
C'est vrai. Pour faire la même chose avec les imbrications, il faut sortir de la meta-prog (simple).
Qu'est-ce que tu entends par "sortir de la meta-prog" ? C'est faire un programme beaucoup plus compliqué ?
<pre class="brush: cpp;">template <size_t N, size_t M> struct Loop {
static void do_it(char * p, ostream &os) {
for (*p = 'a' ; *p <= 'z' ; ++*p) {
Loop<N-1, M+1>::do_it(p+1, os);
}
}
};
template <size_t M> struct Loop<0,M> {
static void do_it(char * p, ostream &os) {
os.write(p-M, M); // on doit pouvoir jouer avec des foncteurs aussi pour éviter ce 'M'
}
};
....
std::ofstream file("toto.txt");
char t[7]; t[6] = '\n';
Loop<6,1 /* 1 pour le 7e caractère: le saut de ligne*/>::do_it(t, file);
</pre><br>
(Non testé ; il y a probablement plus propre).Le 1 octobre 2010 à 15:09:34
template <size_t N, size_t M> struct Loop {
static void do_it(char * p, ostream &os) {
for (*p = 'a' ; *p <= 'z' ; ++*p) {
Loop<N-1, M+1>::do_it(p+1, os);
}
}
};
template <size_t M> struct Loop<0,M> {
static void do_it(char * p, ostream &os) {
os.write(p-M, M); // on doit pouvoir jouer avec des foncteurs aussi pour éviter ce 'M'
}
};
....
std::ofstream file("toto.txt");
char t[7]; t[6] = '\n';
Loop<6,1 /* 1 pour le 7e caractère: le saut de ligne*/>::do_it(t, file);
Ok ! En gros la métaprogrammation c'est faire un programme qui génère lui même un autre programme.<br><br>
Ouaaaa ! <img src="/bundles/tinymce/vendor/tiny_mce/plugins/emotions/img/blink.gif" alt="o_O" class="smilies"><img src="/bundles/tinymce/vendor/tiny_mce/plugins/emotions/img/blink.gif" alt="o_O" class="smilies"><img src="/bundles/tinymce/vendor/tiny_mce/plugins/emotions/img/blink.gif" alt="o_O" class="smilies"><img src="/bundles/tinymce/vendor/tiny_mce/plugins/emotions/img/waw.png" alt=":waw:" class="smilies"><img src="/bundles/tinymce/vendor/tiny_mce/plugins/emotions/img/waw.png" alt=":waw:" class="smilies"><img src="/bundles/tinymce/vendor/tiny_mce/plugins/emotions/img/waw.png" alt=":waw:" class="smilies"><br>
Dis, j'ai essayé le code d'Alienore sur un autre ordinateur : ubuntu, 3 coeurs, et il m'a couché les 2Go en 42 secondes !!! J'y crois pas ! Et lorsque je fais un cat sur ce fichier, l'affichage à lui tout seul met bien plus longtemps que 42 secondes !!!<br><br>
Incroyable ! Je vais essayer de tester les autres.<br><br>
Par contre lmghs, je ne comprends pas ton programme... Qu'est-ce que loop ? J'ai cherché un peu sur internet et je ne trouve rien dessus... C'est le nom d'une structure ? A quoi correspondent les < > sur Loop<N-1, M+1> ? Et à quoi sert une Template ? D'après ce que j'ai peu voir sur le net, ça sert à pouvoir utiliser plusieurs type de variable sans avoir besoin de recréer une nouvelle fonction pour ça ? Et tu parles de foncteurs... Késako ?Le 2 octobre 2010 à 14:39:34
Ok ! En gros la métaprogrammation c'est faire un programme qui génère lui même un autre programme.
Ouaaaa !
Dis, j'ai essayé le code d'Alienore sur un autre ordinateur : ubuntu, 3 coeurs, et il m'a couché les 2Go en 42 secondes !!! J'y crois pas ! Et lorsque je fais un cat sur ce fichier, l'affichage à lui tout seul met bien plus longtemps que 42 secondes !!!
Incroyable ! Je vais essayer de tester les autres.
Par contre lmghs, je ne comprends pas ton programme... Qu'est-ce que loop ? J'ai cherché un peu sur internet et je ne trouve rien dessus... C'est le nom d'une structure ? A quoi correspondent les < > sur Loop<N-1, M+1> ? Et à quoi sert une Template ? D'après ce que j'ai peu voir sur le net, ça sert à pouvoir utiliser plusieurs type de variable sans avoir besoin de recréer une nouvelle fonction pour ça ? Et tu parles de foncteurs... Késako ?