Partage
  • Partager sur Facebook
  • Partager sur Twitter

Exercices pour débutants en C

Au menu : zSommeChiffres (nombres, algo)

Anonyme
21 juillet 2009 à 4:56:14

Youhou j'ai réussi ^^
(j'avais rien à faire ce soir...)

Mon code est ici.

Ça doit être facilement optimisable j'en convient :lol:

Mais bon au moins ça réussit le truc.

Sinon je propose ce texte comme test avec toujours le "les" comme exemple :
les
Les
lEs
 les
_les_
_lEs_
ales
lesa
aalesaa
lesles
leslesles
aalesleslesaa
 les
les 
le
les
LES

Enfin un truc du genre, car le texte mis en exemple par Arthurus ne suffit pas pour tout tester.
  • Partager sur Facebook
  • Partager sur Twitter
21 juillet 2009 à 4:59:16

Il marche pas le lien...
C'est moi ou lui qui déconne ?
  • Partager sur Facebook
  • Partager sur Twitter
Anonyme
21 juillet 2009 à 5:03:44

Bah euh non, je viens de retester et ça mène bien vers le code exporter en html via code block (car je trouve ça plus pratique)

Bon alors si le lien ne marche toujours pas, le code est visible là.
(mais le html exporté via code block est plus lisible je trouve)
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>

int *RechercheFichier(const char *path, const char *chaine){
    FILE *f = fopen(path, "r");

    if(f){

        /* j'alloue un tableau temporaire (de 1000 occurences) ou je vais y mettre le nombre d'occurences avec leurs coordonnées dans le texte */
        int *tabOcc = malloc((1 + 1000 * 2) * sizeof(int));

        int tailleChaine = strlen(chaine);

        int nb_occurences = 0;
        int nb_ligne = 1, nb_colonne = 1;

        int c = 0, c2 = 0;
        int i = 0;

        int ok = 0;

        do{

            /*c = toupper(fgetc(f));*/ /* insensible à la casse */
            c = fgetc(f);

            if(ok == 2 && !isalnum(c)){
                tabOcc[nb_occurences * 2 + 1] = nb_ligne;
                tabOcc[nb_occurences * 2 + 2] = nb_colonne - tailleChaine;
                nb_occurences++;
                ok = i = 0;
                printf(">");
            }

            /*if(c == toupper(chaine[0]) && !isalnum(c2)){*/ /* insensible à la casse */
            if(c == chaine[0] && !isalnum(c2)){
                ok = 1;
                printf("<");
            }

            if(ok){
                /*if(c == toupper(chaine[i])){*/ /* insensible à la casse */
                if(c == chaine[i]){
                    i++;
                    if(i >= tailleChaine){
                        ok = 2;
                    }
                }else{
                    ok = i = 0;
                }
            }

            if(c == '\n'){
                nb_ligne++;
                nb_colonne = 1;
            }else{
                nb_colonne++;
            }

            c2 = c;
            printf("%c", c);

        }while(c != EOF);

        fclose(f);

        /* La je "retaille" le tableau */
        int *tabOcc2 = malloc((1 + nb_occurences * 2) * sizeof(int));

        tabOcc2[0] = nb_occurences;

        int a = 1;
        while(a < (1 + nb_occurences * 2)){
            tabOcc2[a] = tabOcc[a];
            a++;
        }

        /* je libère l'ancien */
        free(tabOcc);

        /* Et je renvoie le nouveau */
        return tabOcc2;

    }else{
        return 0;
    }
}

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

    int *tableauOccurences;

    /*tableauOccurences = RechercheFichier("fichier_test.txt", "les");*/

    if(argc == 3){
        tableauOccurences = RechercheFichier(argv[1], argv[2]);

        printf("\n\n--\n");

        int nb_occurence = tableauOccurences[0];
        printf("detecte %d fois\n", tableauOccurences[0]);

        int i;
        for(i = 0; i < nb_occurence; i++){
            printf("Occurrence %d -> ligne %d, colonne %d\n", (i + 1), tableauOccurences[i * 2 + 1], tableauOccurences[i * 2 + 2]);
        }
    }

    system("pause");

	return 0;
}
  • Partager sur Facebook
  • Partager sur Twitter
21 juillet 2009 à 5:30:02

arthurus@arthurus:~/zero$ cat fichier_test.txt 
Bonjour,
Un jour un personnage nommé Arthurus a
proposé un exercice pour traiter : les chaines, 
les fichiers, les argv[] ...
Enfin, espérons que ce ne sera pas trop dur pour les zéros.
Bon courage à tous, et bon codage ;)

arthurus@arthurus:~/zero$ ./prog 
BONJOUR,
UN JOUR UN PERSONNAGE NOMMé ARTHURUS A
PROPOSé UN EXERCICE POUR TRAITER : <LES> CHAINES, 
<LES> FICHIERS, <LES> ARGV[] ...
ENFIN, ESPéRONS QUE CE NE SERA PAS TROP DUR POUR <LES> ZéROS.
BON COURAGE à TOUS, ET BON CODAGE ;)
�

--
detecte 4 fois
Occurrence 1 -> ligne 3, colonne 37
Occurrence 2 -> ligne 4, colonne 1
Occurrence 3 -> ligne 4, colonne 15
Occurrence 4 -> ligne 5, colonne 51


Bon c'est un bon début... (sympa les < > qui se mettent autour du mot ;) )

Cependant :
  • Pourquoi le texte est affiché en maj ?
  • Pourquoi tu n'utilises pas argv[] ?
  • Tu as un décalage de colonnes.
    l'occurrence 1 se trouve à la colonne 36 et pas 37.
    l'occurrence 4 se trouve à la colonne 50 et pas 51.


Pour ce qui est du code, je ne l'ai pas encore lu... Je le ferai une fois ces détails corrigés (Mais bien joué quand même.)
  • Partager sur Facebook
  • Partager sur Twitter
Anonyme
21 juillet 2009 à 5:36:20

les < > ainsi que la chaine en majuscule c'était juste pour tester, j'ai oublier de mettre en commentaire ces printf.
Sinon pour le décalage des colonnes c'est bizarre je n'ai pas ça chez moi.
Peut être ça vient des accents, ça arrive que sur les lignes ou il y'en a.
Test sans les accents pour voir.

Pour argv je sais pas trop comment faire j'ai jamais touché à ça.
Mais de toutes manière je me suis dit que ça serait pas long à changer.

Citation : Arthurus

(Mais bien joué quand même.)


héhé merci :)
  • Partager sur Facebook
  • Partager sur Twitter
21 juillet 2009 à 5:42:22

Ouais tu as raison...

Sinon moi les < > ça me plait ... (Tu peux les garder si tu veux).

Bon bein restes plus que argv[] ;) (franchement ça te prendra 20 secondes à le faire... Et c'est super pratique par la suite, car tu n'aura pas à modifier ton .c pour chercher une autre chaine que "les").

Le lien que GuilOooo t'as donné est pas mal (Tu n'as besoin que du début du tuto pour faire ce qui est demandé dans cet exo)

EDIT :
Euh... Tu es sûr d'avoir géré les maj ? (J'ai remplacé quelques "les" par "Les")

arthurus@arthurus:~/zero$ cat fichier_test.txt
Bonjour,
Un jour un personnage nommé Arthurus a
propose un exercice pour traiter : Les chaines, 
les fichiers, les argv[] ...
Enfin, esperons que ce ne sera pas trop dur pour Les zéros.
Bon courage à tous, et bon codage ;)


Pourtant ça donne la même chose

arthurus@arthurus:~/zero$ ./prog 
BONJOUR,
UN JOUR UN PERSONNAGE NOMMé ARTHURUS A
PROPOSE UN EXERCICE POUR TRAITER : <LES> CHAINES, 
<LES> FICHIERS, <LES> ARGV[] ...
ENFIN, ESPERONS QUE CE NE SERA PAS TROP DUR POUR <LES> ZéROS.
BON COURAGE à TOUS, ET BON CODAGE ;)
�

--
detecte 4 fois
Occurrence 1 -> ligne 3, colonne 36
Occurrence 2 -> ligne 4, colonne 1
Occurrence 3 -> ligne 4, colonne 15
Occurrence 4 -> ligne 5, colonne 50
  • Partager sur Facebook
  • Partager sur Twitter
Anonyme
21 juillet 2009 à 8:53:18

Citation : L'exercice

  • Un séparateur est un caractère parmis cette liste :
  • ...
  • Nous appellerons un mot : le plus grand ensemble de caractères non séparateurs concaténés.

Je trouve ça super ambigu. Que faire d'un caractère comme ^G par exemple ? Il est dans ASCII, il n'est pas dans la liste des caractères séparateurs, ça veut donc dire que je peux le mettre dans un mot :/ ? Pourquoi ne pas simplement dire "un mot est le plus grand ensemble de caractères alphanumériques à la suite" ?
  • Partager sur Facebook
  • Partager sur Twitter
Anonyme
21 juillet 2009 à 9:42:55

Citation : Arthurus

Euh... Tu es sûr d'avoir géré les maj ? (J'ai remplacé quelques "les" par "Les")

Nan ouai désolé, hier soir jme suis emmêlé... C'était bon du premier coup, mais vu que par exemple sur google et un peu partout ailleurs c'est insensible à la casse, j'ai modif au dernier moment en pensant bien faire...

Donc là c'est bon j'ai corrigé. "Les" != "les"

Pour les argv c'est fait aussi ;)
J'ai modifier la source

Donc j'ai fait un fichier "RechercheFichier.bat" avec dedans :
console.exe fichier_test.txt les

Et ça marche pareil.
  • Partager sur Facebook
  • Partager sur Twitter
21 juillet 2009 à 11:05:38

Citation : zulon

Je trouve ça super ambigu. Que faire d'un caractère comme ^G par exemple ? Il est dans ASCII, il n'est pas dans la liste des caractères séparateurs, ça veut donc dire que je peux le mettre dans un mot :/ ? Pourquoi ne pas simplement dire "un mot est le plus grand ensemble de caractères alphanumériques à la suite" ?


http://www.siteduzero.com/forum-83-329 [...] html#r3952428
  • Partager sur Facebook
  • Partager sur Twitter
Anonyme
21 juillet 2009 à 11:30:00

D'accord. Mais si les autres font comme moi, il vaudrait peut-être mieux corriger le message d'origine :) ?
  • Partager sur Facebook
  • Partager sur Twitter
21 juillet 2009 à 14:02:56

Voici mon code qui a l'air de fonctionner, j'avais oublié de le poster hier :
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

typedef char bool;
#define true 1
#define false 0

#define MAX 10002

typedef struct
{
    int ligne;
    int colonne;
} Occurrence;

bool separateur (int caractere);

int main(int argc, char* argv[])
{
    FILE*fichier = fopen (argv[2], "r");
    Occurrence *liste_occurrences = NULL;
    int i;

    if (fichier == NULL)
        printf("Le fichier specifie n'existe pas\n");
    else
    {
        int num_ligne = 0;
        char buf[MAX] = {0};
        char* p = NULL;
        int nbOccurrences = 0;
        while (fgets (buf, MAX, fichier) != NULL)
        {
            num_ligne++;
            p = buf;
            while ((p = strstr (p, argv[1])) != NULL)
            {
                /* Si l'occurence se trouve au début de buf, on vérifie que
                le caractère après l'occurence soit un séparateur */
                if (p == buf && separateur (*(p+strlen(argv[1]))))
                    goto trouve;
                /* Sinon, si elle se trouve au milieu, on vérifie que le caractère
                précédent et celui suivant l'occurrence soient des séparateurs */
                else if (separateur (*(p-1)) && separateur (*(p+strlen(argv[1]))))
                    goto trouve;
                else
                    goto pasTrouve;

                // Si on a trouvé une occurrence à argv[2], on l'ajoute à la liste
                trouve:
                    nbOccurrences++;
                    liste_occurrences = realloc (liste_occurrences, nbOccurrences * sizeof(Occurrence));
                    liste_occurrences[nbOccurrences-1].ligne = num_ligne;
                    liste_occurrences[nbOccurrences-1].colonne = (p-buf)/sizeof(char) + 1;

                pasTrouve:
                // On décalle p d'un caractère pour ne pas traiter de nouveau la même chaîne
                p++;
            }
        }

        fclose (fichier);

        // Affichage du résultat
        printf("Le mot '%s' a ete trouve %d fois dans le fichier %s.\n", argv[1], nbOccurrences, argv[2]);
        for (i = 0 ; i < nbOccurrences ; i++)
            printf("Occurence %d -> ligne %d, colonne %d\n", i+1, liste_occurrences[i].ligne, liste_occurrences[i].colonne);
    }

    printf("\nAppuyez sur Entree pour mettre fin au programme...\n");
    getchar ();
    return EXIT_SUCCESS;
}

bool separateur (int caractere)
{
    return (ispunct(caractere) || isspace (caractere));
}

Désolé pour ce que certains jugeront comme étant des mauvaises habitudes ^^ . Pour le goto, j'ai trouvé ça plus approprié pour éviter de dupliquer le code se trouvant sous l'étiquette trouve (sinon, j'aurais dû l'écrire une fois sous le if et une fois sous le else if, ce n'est que 4 lignes donc ça aurait pu passer, mais par principe j'ai préféré mettre un goto).
Pour le reste, quelques commentaires pour aider à comprendre, en espérant que ce ne soit pas très obscur, auquel cas je détaillerai un peu plus :) .

Je me permets également de poser une autre version de la fonction pour rechercher un séparateur que j'avais codé avant d'avoir les précisions sur ce qu'on devait considérer comme séparateur ou non. Sont considérés comme séparateurs tous les caractères autres que les majuscules non accentuées et les minuscules (accentuées ou non) :
// Renvoie true si le caractère est un séparateur (non chiffre ou non lettre)
bool separateur (unsigned char caractere)
{
    int max = strlen (liste_separateurs);
    int i;

    if ((caractere >= 'A' && caractere <= 'Z') || (caractere >= 'a' && caractere <= 'z')
        || caractere == 'é' || caractere == 'è' || caractere == 'ñ' || caractere == 'à' || caractere == 'ù')

    return false;
}
  • Partager sur Facebook
  • Partager sur Twitter
21 juillet 2009 à 14:13:21

À mon avis c'est contre nature de vouloir stocker les occurrences ; autant afficher un message pour chaque occurrence trouvée et afficher le total seulement à la fin ; les outils de traitement en flux font ça. Ça évite de se trimbaler une liste ou un tableau.
  • Partager sur Facebook
  • Partager sur Twitter
21 juillet 2009 à 14:22:40

J'y avais pensé pour ma part, mais j'ai choisi cette forme pour coller au plus près à n'énoncé en respectant l'affichage indiqué car je l'ai considéré comme étant implicitement une consigne, mais si ça n'est pas le cas en effet c'est plus simple.
  • Partager sur Facebook
  • Partager sur Twitter
21 juillet 2009 à 14:31:35

Boaf c'est juste un énoncé comme ça, le but c'est de vous faire pratiquer. :) Les variations sont tout à fait bienvenues, je pense.
  • Partager sur Facebook
  • Partager sur Twitter
21 juillet 2009 à 16:00:12

Citation : rz0

Boaf c'est juste un énoncé comme ça, le but c'est de vous faire pratiquer. :) Les variations sont tout à fait bienvenues, je pense.



Mais bien sur...

Il ne faut pas bloquer sur des détails, comme par exemple est ce qu'un caractère accentué est séparateur ou pas !

Ce n'est pas l'esprit de l'exo...
  • Partager sur Facebook
  • Partager sur Twitter
21 juillet 2009 à 16:56:55

Les gotos sont inutiles, ici le flôt de controle est très simple.

if (p == buf && separateur (*(p+strlen(argv[1])))
    || separateur (*(p-1)) && separateur (*(p+strlen(argv[1])))) {
    nbOccurrences++;
    liste_occurrences = realloc (liste_occurrences, nbOccurrences * sizeof(Occurrence));
    liste_occurrences[nbOccurrences-1].ligne = num_ligne;
    liste_occurrences[nbOccurrences-1].colonne = (p-buf)/sizeof(char) + 1;
}

p++;
  • Partager sur Facebook
  • Partager sur Twitter
21 juillet 2009 à 17:08:19

Oui ils le sont mais pas pour cette raison. J'aurais pu (dû ?) passer par un booléen. Néanmoins, il faut faire deux if séparés, car si p == buf, p-1 n'est pas attribuée donc il y a un léger risque d'erreur de segmentation.
  • Partager sur Facebook
  • Partager sur Twitter
21 juillet 2009 à 17:28:05

Mon code se comporte comme le tien : ce bug était déjà présent dans ton programme, s'il échoue à la première condition il va tester la deuxième.

Il suffit de reformuler la condition pour éviter cela :
p == buf && separateur (*(p+strlen(argv[1])))
|| p > buf && separateur (*(p-1)) && separateur (*(p+strlen(argv[1])))

Ou alors :
p == buf
    ? separateur (*(p+strlen(argv[1])))
    : separateur (*(p-1)) && separateur (*(p+strlen(argv[1])))


Edit : en remarquant que tu répètes deux fois la condition sur p+strlen(..), on peut carrément écrire :
(p == buf || separateur (*(p-1))) && separateur (*(p+strlen(argv[1])))
  • Partager sur Facebook
  • Partager sur Twitter
21 juillet 2009 à 17:48:24

Le but est justement de tester la seconde si la premiere est fausse. Si la première condition échoute, p != buf alors p-1 est allouée. On peut donc y accéder sans risque. Si on met tout dans la même condition, on lit le contenu pointé par p-1 dans tous les cas, y compris le cas dangereux où p == buf.
  • Partager sur Facebook
  • Partager sur Twitter
21 juillet 2009 à 18:20:09

Non, si la première condition échoue tu n'as pas forcément p != buf, tu peux avoir p == buf vrai et separateur (*(p+strlen(argv[1]))) faux.

Permets-moi de répéter que if (cond1) action else if (cond2) action (quand c'est bien la même action à chaque fois) est strictement équivalent à if (cond1 || cond2) action.

Edit : ou alors j'ai raté un truc énorme et je suis complètement à l'ouest (c'est possible), mais je ne crois pas.
  • Partager sur Facebook
  • Partager sur Twitter
21 juillet 2009 à 18:22:00

Bonjour à tous.

Ma proposition
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>

int zGrep(FILE *src, char const *needle)
{
    int nbOcc = 0;

    size_t row = 0;
    size_t col = 0;

    size_t lenWord = 0;
    size_t lenNeedle = strlen(needle);

    char *word = malloc(lenNeedle * sizeof *word);
    if (word != NULL)
    {
        int cmpOk = 1;

        int c;
        while ((c = fgetc(src)) != EOF)
        {
            ++col;
            if (isalnum(c) && cmpOk)
            {
                word[lenWord++] = (char)c;
                cmpOk = !(lenWord > lenNeedle || word[lenWord - 1] != needle[lenWord - 1]);
            }
            else
            {
                if (lenWord == lenNeedle && cmpOk)
                {
                    printf("1 occurrence trouvee a la ligne %u colonne %u\n\n",
                           row + 1, col - lenWord);
                    ++nbOcc;
                }

                if (c == '\n')
                {
                    ++row;
                    col = 0;
                }
                lenWord = 0;
                cmpOk = 1;
            }
        }
    }
    if (word)
        free(word), word = NULL;

    return nbOcc;
}



void showUsage(void)
{
    puts
    (
        "zGrab usage \n"
        "1er arg : Nom du fichier a analyser. \n"
        "2nd arg : Chaine a rechercher dans le fichier. \n"
    );
}



int main(int argc, char *argv[])
{
    int exitCode = EXIT_SUCCESS;
    if (argc != 3)
    {
        showUsage();
        exitCode = EXIT_FAILURE;
    }
    else
    {
        FILE *in = fopen(argv[1], "r");
        if (in == NULL)
        {
            perror("Erreur d'ouverture du fichier ");
            exitCode = EXIT_FAILURE;
        }
        else
            zGrep(in, argv[2]);

        fclose(in);
    }

    return exitCode;
}


a+

edit : Code corrigé dans la mesure du possible... ;) et ajout de commentaires...
edit : Autres corrections. Promis, je ne touche plus à mon code... ;)
edit : :-° Loupé, et j'ai enlevé le code avec les commentaires devenus obsolètes...
  • Partager sur Facebook
  • Partager sur Twitter
Zeste de Savoir, le site qui en a dans le citron !
21 juillet 2009 à 18:24:04

Exact, je n'avais pas relevé le détail que tu mentionnes dans la première partie du post.
Tu as raison pour la suite, mais à cause du p-1, je ne peux pas utiliser cette forme. Je ne dois lire le caractère pointé par p-1 que lorsque p != buf, il faut donc que j'utilise une condition (imbriquée je pense) pour faire en sorte que ce soit le cas.
  • Partager sur Facebook
  • Partager sur Twitter
21 juillet 2009 à 18:26:40

Non. mon post contient le code qui fait ce que tu veux (après, je ne sais pas si c'est ce qu'il faut, je ne me suis pas intéressé au problème ni à ton code dans l'ensemble).
D'ailleurs la condition ternaire fait exactement ce que tu dis, une condition imbriquée (coucou rz0 expression/statement %%), mais ma proposition suivante est plus courte.
  • Partager sur Facebook
  • Partager sur Twitter
21 juillet 2009 à 18:30:03

Citation : bluestorm

Permets-moi de répéter que if (cond1) action else if (cond2) action (quand c'est bien la même action à chaque fois) est strictement équivalent à if (cond1 || cond2) action.

Edit : ou alors j'ai raté un truc énorme et je suis complètement à l'ouest (c'est possible), mais je ne crois pas.


Avec un "ou inclusif", il est inutile d'évaluer cond2 si cond1 est vérifié et tous les compilateurs C à ma connaissance "optimisent" (mais on peut parler de "bon sens") à ce niveau. Donc l'équivalence que tu montres est correcte.

Je m'étais déjà intéressé à la question et j'ai fait un petit test :
int f() {
    printf("Dans f \n");
    return 1;
}

int g() {
    printf("Dans g \n");
    return 0;
}

int main()
{
    if(f() || g())
        printf("Oui");
    return 0;
}

Le résultat est sans appel :
Dans f
Oui
  • Partager sur Facebook
  • Partager sur Twitter
21 juillet 2009 à 18:33:19

Citation : Al3xx

Le but est justement de tester la seconde si la premiere est fausse



En C c'est toujours le cas.

Je m'explique...

Il existe des langages qui font la difference entre un operateur boolean normal, et un operateur boolean qui tient compte de l'ordre.

En ADA par exemple, le fait d'ecrire A and B, va évaluer A, puis B (quelque soit le résultat de A), puis faire l'opération and.

Par contre A and then B, va évaluer A, si A est faux, on s'arrête, sinon on teste B.

(Pour le or, c'est dans le sens inverse, si on A or else B, on teste A, si A est vrai on s'arrête, sinon on continue).

Revenons au C maintenant... Tous les opérateurs logiques prennent compte de l'ordre.

C'est à dire quand tu fais : A or B, ça teste A, si c'est vrai, on quitte sans tester B (avec un résultat vrai), sinon on teste B.

EDIT : Grilled
  • Partager sur Facebook
  • Partager sur Twitter
21 juillet 2009 à 18:36:14

D'accord, donc suivant ce qui vient d'être dit (que je n'avais pas compris précédemment), je peux sans problème utiliser ta condition, bluestorm. Merci pour tes remarques et à shareman pour tes précisions :)

EDIT: et Arthurus aussi.
Pratique, on doit pouvoir trouver certaines applications. Cependant, c'est spécifié par la norme ou c'est dépendant de l'implémentation ? (car si c'est le cas, même si tous les compilos le font en principe, il y a un risque)
  • Partager sur Facebook
  • Partager sur Twitter
Anonyme
21 juillet 2009 à 18:46:10

Citation : shareman

Avec un "ou inclusif", il est inutile d'évaluer cond2 si cond1 est vérifié et tous les compilateurs C à ma connaissance "optimisent" (mais on peut parler de "bon sens") à ce niveau.


S'ils veulent se faire appeler "compilateur C", ils ont intérêt : c'est le comportement requis par la norme. Pas besoin de t'inquiéter si le compilo X de l'architecture Y fait comme tu le veux donc :) .
  • Partager sur Facebook
  • Partager sur Twitter
22 juillet 2009 à 12:59:34

Pour info, j'ai édité le code de la correction de zBrace. Il est plus logique d'évaluer la condition testant si le compteur est strictement négatif uniquement si l'on vient de décrémenter ce dernier.
  • Partager sur Facebook
  • Partager sur Twitter
23 juillet 2009 à 12:39:51

salut tout le monde,

je voulais savoir si quelqu'un savait quand un prochain exercice seras posté car je regarde dans le tableau de la première page et il n'y as pas de nouveaux exercices .


Merci d'avance
  • Partager sur Facebook
  • Partager sur Twitter
23 juillet 2009 à 12:50:56

Hum, shareman a oublié d'update la page mais il y a un exo en cours : http://www.siteduzero.com/forum-83-329 [...] html#r3951095
  • Partager sur Facebook
  • Partager sur Twitter