IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Pascal Discussion :

Rotation d'un tableau


Sujet :

Pascal

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Inscrit en
    Octobre 2006
    Messages
    89
    Détails du profil
    Informations forums :
    Inscription : Octobre 2006
    Messages : 89
    Par défaut Rotation d'un tableau
    Ce programme est sensé faire une rotation d'un tableau par un nombre d'éléments k, c'est à dire qu'on assimile le tableau à un cerle qu'on fait tourner autour d'un axe fixe de k cases puis on l'aplatit pour voir le résultat... c'est très mal exprimé tout ça, voici un exemple:
    3 5 2 3 9
    k=0 on ne fait pas bouger les éléments,
    k=2 . . 3 . .
    le 3 a pris la case 3 (place du 2), il était en case 1
    on continue pour le reste
    . . 3 5 2
    on est arrivé à la fin du tableau, on reprend depuis le début avec le même ordre bien sûr

    3 9 3 5 2
    et voila!
    evidemment, il faut deux tableaux
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    program rotationnellation;
    uses wincrt;
    type tab = array[1..100] of integer;
    procedure remplir(var x:integer; var Table:tab);
    var i:integer;
    begin
    repeat 
    	write('nombre de cases du tableau?' );
    	read(x);
    until x in [3..10];
    for i:=1 to x do 
    	begin
    	write('Valeur #',i, 'du tableau?  ');
    	read(Table[i]);
    	end;
    end;
    procedure rotation(var table2 : tab; k,x :integer; table1:tab);
    var i,j:integer;
    begin
    i:=1;
    while  i-x+k-1<>0 do table2[i+k]:=table1[i];
    for j:=1 to k do table2[j]:=table1[i];
    end;
    var T1,T2:tab; n,k,c,i : integer;
    begin
    remplir(n,T1);
    writeln('entrez le nombre ''k'' d''éléments de la rotation');
    writeln('choisissez un k négatif pour une rotation de sens indirect');
    writeln('k ?  ');
    read(k);
    if k>n then 
    	begin
    	c:=k;
    	repeat
    	c:=c-n;
    	until c<=n;
    	k:=c;
    	end;
    if k<0 then repeat k:=k+n until k>-1;
     
     
    rotation(T2,k,n,T1);
    for i:=1 to n do write(T1[i] :2);
    for i:=1 to n do write(T2[i] :2);
    end.
    Je suis convaincu que c'est juste !!!
    le programme plante après la saisie de k.
    Merci d'avoir lu, je vous remercirai de m'avoir aidé j'espère

  2. #2
    Membre chevronné Avatar de Haywire
    Homme Profil pro
    Développeur Java
    Inscrit en
    Mars 2006
    Messages
    462
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur Java
    Secteur : Finance

    Informations forums :
    Inscription : Mars 2006
    Messages : 462
    Par défaut
    Bonjour,

    en fait ton programme ne plante pas, le problème se situe à cette ligne:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    while  i-x+k-1<>0 do table2[i+k]:=table1[i];
    c'est une boucle infinie car le résultat de la condition de continuation ne changera jamais.

    A part ça il y a des petits défauts qui n'empêche pas ton programme de tourner mais qu'il vaut mieux éviter.
    Le plus important et celui qui saute aux yeux directement:
    tu passes n en paramètre dans remplir, mais tu ne l'as pas initialisé avant.
    Il vaut mieux que tu demandes d'entrer la taille du tableau avant d'appeler la procédure.
    Donc dans le prog principale tu demandes a l'utilisateur quelle taille de tableau il veut, tu stockes la réponse dans n et puis tu passes n en paramètre à la procédure remplir, qui se chargera de remplir le tableau correctement.

    Rappel: dans la mesure du possible, il faut que les fonctions et procédure ne fassent qu'une seule chose. Si une procédure fait 2 choses, découpe la en 2 procédures, ou met une partie dans ton programme principale.
    Normalement les procédure et fonctions ne doivent pas intéragir avec l'utilisateur, autrement dit elles ne doivent pas lui poser de questions ni afficher quoi que ce soit. L'utilisateur ne doit communiquer qu'avec le programme principal, qui se charge ensuite d'assigner les tâches aux fonctions et procédures.

    un exemple humain: quand tu achètes une voiture tu ne communiques qu'avec le vendeur. Ce n'est pas l'ouvrier à la chaîne qui te demande combien de portes tu désires sur ta voiture et de quelle couleur il doit la peindre. De même ce n'est pas lui qui va te donner les clefs.

    En programmation c'est pareil, il faut qu'il y ai un maximum d'indépendance entre les différentes parties d'un programme.
    Ta procédure remplir n'a pas besoin de savoir que c'est un utilisateur qui indique le nombre d'élément du tableau (read), et elle n'a pas non plus besoin de savoir que c'est une console qui affiche le programme ( write).
    Si tu supprimes tout ça, tu pourras réutiliser ta procédure remplir dans n'importe quel programme que ce soit une application console ou non. Du moment que ce programme connait le type de tableau a lui fournir.

    Voilà désolé pour le blabla mais plutôt que de corriger tes erreurs je pense qu'il est utile de rappeler certaines règles de conceptions.
    Maintenant si tu n'arrives pas à corriger ou si tu as encore des questions n'hésite pas.

  3. #3
    Membre confirmé
    Inscrit en
    Octobre 2006
    Messages
    89
    Détails du profil
    Informations forums :
    Inscription : Octobre 2006
    Messages : 89
    Par défaut
    j'ai donc oublié d'incrémenter le compteur i, deux fois, grave erreur mais je me la pardonne quand-même...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    procedure rotation(var table2 : tab; k,x :integer; table1:tab);
    var i,j:integer;
    begin
    i:=1;
    while  i-x+k-1<>0 do
    	begin
    	table2[i+k]:=table1[i];
    	i:=i+1;
    	end;
    for j:=1 to k do
    	begin
    	table2[j]:=table1[i];
    	i:=i+1;
    	end;
    end;
    A propos de la procedure remplir, tu as dit qu'il ne fallait pas qu'une procédure communique avec l'utilisateur, je peux savoir pourquoi ? J'avoue que l'idée est séduisante mais, la procédure n'a pas besoin d'être simplifiée je trouve, d'ailleurs il est ridicule d'en faire une procédure, il vaudrait mieux que ce soit dans le programme principal, je le fais parce qu'en classe on nous demande de décomposer en modules.
    S'il fallait faire comme tu dis, est-ce que cela veut dire que je dois écrire une fonction booleenne qui teste le parmètre n ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    function Test(x:integer):bolean;
    b:=false;
    if x in [3..10] then b:=true;
    test:=b;
    et dans le principal je mets :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    repeat
    writeln('combien de cases?  ');
    read(n);
    test(n);
    until test(n);
    en effet ça donnerait ça:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    program rotationnellation;
    uses wincrt;
    type tab = array[1..100] of integer;
    function test(x:integer):boolean;
    var b:boolean;
    begin
    b:=false;
    if x in [3..10] then b:=true;
    test:=b;
    end;
    procedure remplir(x:integer; var Table:tab);
    var i:integer;
    begin
    for i:=1 to x do 
    	begin
    	write('Valeur #',i, 'du tableau?  ');
    	read(Table[i]);
    	end;
    end;
    procedure rotation(var table2 : tab; k,x :integer; table1:tab);
    var i,j:integer;
    begin
    i:=1;
    while  i-x+k-1<>0 do
    	begin
    	table2[i+k]:=table1[i];
    	i:=i+1;
    	end;
    for j:=1 to k do
    	begin
    	table2[j]:=table1[i];
    	i:=i+1;
    	end;
    end;
    var T1,T2:tab; n,k,c,i : integer;
    begin
    repeat
    writeln('combien de cases?  ');
    read(n);
    test(n);
    until test(n);
    remplir(n,T1);
    writeln('entrez le nombre ''k'' d''éléments de la rotation');
    writeln('choisissez un k négatif pour une rotation de sens indirect');
    writeln('k ?  ');
    read(k);
    if k>n then 
    	begin
    	c:=k;
    	repeat
    	c:=c-n;
    	until c<=n;
    	k:=c;
    	end;
    if k<0 then repeat k:=k+n until k>-1;
     
     
    rotation(T2,k,n,T1);
    for i:=1 to n do write(T1[i] :2);
    write(chr(13));
    for i:=1 to n do write(T2[i] :2);
    end.
    Merci Mushroom7!

  4. #4
    Membre confirmé
    Inscrit en
    Octobre 2006
    Messages
    89
    Détails du profil
    Informations forums :
    Inscription : Octobre 2006
    Messages : 89
    Par défaut
    Optimisé :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    program rotationnellation;
    uses wincrt;
    type tab = array[1..100] of integer;
    procedure remplir(var x:integer; var Table:tab);
    var i:integer;
    begin
    repeat 
    	write('nombre de cases du tableau?   ');
    	read(x);
    until x in [3..10];
    for i:=1 to x do 
    	begin
    	write('Valeur #',i, 'du tableau?  ');
    	read(Table[i]);
    	end;
    end;
    procedure rotation(var table2 : tab; k,x :integer; table1:tab);
    var i:integer;
    begin
    i:=1;
    for i:=1 to x do
    if (i+k)<=x then table2[i+k]:=table1[i] else table2[i+k-x]:=table1[i];
    end;
    var T1,T2:tab; n,k,c,i : integer;
    begin
    remplir(n,T1);
    writeln('entrez le nombre ''k'' d''éléments de la rotation');
    writeln('choisissez un k négatif pour une rotation de sens indirect');
    writeln('k ?  ');
    read(k);
    if k>n then 
    	begin
    	c:=k;
    	repeat
    	c:=c-n;
    	until c<=n;
    	k:=c;
    	end;
    if k<0 then repeat k:=k+n until k>-1;
     
     
    rotation(T2,k,n,T1);
    for i:=1 to n do write(T1[i] :2);
    write(chr(13));
    for i:=1 to n do write(T2[i] :2);
    end.

  5. #5
    Membre chevronné Avatar de Haywire
    Homme Profil pro
    Développeur Java
    Inscrit en
    Mars 2006
    Messages
    462
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur Java
    Secteur : Finance

    Informations forums :
    Inscription : Mars 2006
    Messages : 462
    Par défaut
    A propos de la procedure remplir, tu as dit qu'il ne fallait pas qu'une procédure communique avec l'utilisateur, je peux savoir pourquoi ?
    Je l'ai dis mais ce n'est pas moi qui l'ai inventé

    Pourquoi? Parce que si elle communique avec l'utilisateur, elle en est dépendante et donc dépendante du programme principal.
    Si ensuite tu écris un autre programme, qui n'a pas besoin d'intervention d'un utilisateur pour tourner, et que dans ce programme tu dois aussi remplir un tableau, tu devras écrire une autre procédure.
    C'est une perte de temps inutile.
    Si tu avais écrit tout de suite une version général ( générique) et indépendante de ta procédure, qui se contente de remplir un tableau sans se soucier de qui décide de sa taille, tu aurais pu faire un simple copier coller.
    Evidemment quand il s'agit de remplir un tableau ça prend 2min de réecrire une nouvelle version, mais quand tu auras des procédures ou fonctions plus compliquées, tu seras contente de n'avoir a y réfléchir qu'une seule fois.

    Ce n'est jamais une obligation, ce ne sont que des règles qui ont été inventé pour simplifier la vie des programmeur. Au plus les parties d'un programmes sont indépendantes, au plus la lecture, l'écriture, le débogage et la mise à jour du programme seront faciles.

    J'avoue que l'idée est séduisante mais, la procédure n'a pas besoin d'être simplifiée je trouve, d'ailleurs il est ridicule d'en faire une procédure, il vaudrait mieux que ce soit dans le programme principal, je le fais parce qu'en classe on nous demande de décomposer en modules.
    S'il fallait faire comme tu dis, est-ce que cela veut dire que je dois écrire une fonction booleenne qui teste le parmètre n ?
    On vous demande de décomposer justement pour vous habituer à diviser un problème en plusieurs petits problèmes indépendants.
    De nouveau pour des touts petits programmes d'aprentissage on pourrait s'en passer, mais c'est une bonne habitude à prendre dès le début. Et au niveau apprentissage tu risques d'avoir pas mal d'exercices sur les tableaux, donc c'est quand même un gain de temps de pouvoir réutiliser ta procédure dans tous ces exercices. Et pour ça il faut bien qu'elle soit indépendante du programme puisque les exercices ne font pas la même chose.

    Pour la fonction qui teste n, ce n'est pas pareil.
    Tu dois toujours penser en terme de "réutilisabilité logicielle".
    Est-ce que tu risques d'avoir besoin dans d'autres programmes d'une fonction qui teste si N est entre 3 et 10?
    C'est peu probable ! Car N et les valeurs qu'il peut prendre sont spécifiques a ce programme.
    En plus les fonctions et procédures servent ausis à ne pas devoir recopier le même code a plein d'endroits dans un programme. Et ici tu n'as besoin de vérifier n qu'une seule fois.
    De plus, le code de ta fonction test peut s'ecrire en une seule ligne, il n'y a donc pas d'avantage a remplacer cette ligne dans le programme principal par une ligne qui appele la fonction test.

    Cependant, ça pourrait être utile, même si ce n'est appelé qu'une seule fois dans le programme, si le code de la fonction test était assez long ou complexe.
    A ce moment là, remplacer tout ce code par une ligne d'appel de fonction dans le programme principal simplifie la lecture du code par la suite.
    Ainsi si tu as ecrit la fonction test et que tu l'as nommée "estValide", pour quelqu'un qui veut lire ton programme ensuite, la ligne: if estValide(n) est suffisament clair pour qu'il n'ait pas besoin d'aller lire le code de estValide.
    Et s'il a envie de savoir quels sont les critères de validité il peut toujours aller lire le code de la fonction.

  6. #6
    Membre confirmé
    Inscrit en
    Octobre 2006
    Messages
    89
    Détails du profil
    Informations forums :
    Inscription : Octobre 2006
    Messages : 89
    Par défaut
    Je l'ai dis mais ce n'est pas moi qui l'ai inventé
    En me relisant je réalise que c'est vrai, j'ai l'air de mettre en doute ce que tu dis. Ca me fait sourire parce que ce n'était pas du tout mon intention.

    Merci pour les précisions, je tacherai d'en faire une hygiène de programmation.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Rotation de tableau
    Par le_touriste dans le forum Word
    Réponses: 13
    Dernier message: 26/08/2011, 15h47
  2. [FPDF] Faire une rotation de 90° a un tableau
    Par discogarden dans le forum Bibliothèques et frameworks
    Réponses: 4
    Dernier message: 06/02/2008, 14h42
  3. Rotation de case dans un tableau 2D
    Par Oberown dans le forum Algorithmes et structures de données
    Réponses: 20
    Dernier message: 23/08/2006, 16h58
  4. [Tableaux] Rotation d'un tableau en PHP
    Par amarcil dans le forum Langage
    Réponses: 4
    Dernier message: 25/04/2006, 20h26

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo