bonsoir à tous j'ai un probléme et je voudrais que vous m'aidiez. j'aimerai savoir comment supprime t-on un enregistrement. si par exemple l'enregistrement est un tableau comment supprime t-on la case i du tableau.merci d'avantage et aidez moi
bonsoir à tous j'ai un probléme et je voudrais que vous m'aidiez. j'aimerai savoir comment supprime t-on un enregistrement. si par exemple l'enregistrement est un tableau comment supprime t-on la case i du tableau.merci d'avantage et aidez moi
Hai,
Pas le choix : il faut décaler tout ce qui est plus loin en le ramenant d'une case, et ne pas oublier que désormais le tableau contient 1 case de moins valide, même si toutes restent de fait accessibles.
Si les cons volaient, il ferait nuit à midi.
Bonjour,
peut-être vais-je dire une bêtise...
plutôt que de le supprimer physiquement par décalage, peut-être simplement mettre un flag (un indicateur comme quoi il ne faut plus l'utiliser) ?
inconvénient il faut plus de place pour stocker les indicateurs, tests supplémentaires à mettre dans le code, temps cpu..
avantage, la suppression n'est pas définitive, il suffit de rebasculer le flag...
Un bon exemple vaut mieux qu'une longue explication confuse...
Fai,
Oui, c'est une bonne idée. On fait souvent comme ça quand on gère des fichiers correspondant à une base de données, l'emplacement inutilisé étant alors repris pour les prochaines données créées.
C'était valable dans le temps, quand les bases de données disponibles étaient chères, et souvent assez lentes. Mais désormais, il existe de nombreuses possibilités gratuites dans ce domaine, généralement performantes, ce qui diminue considérablement l'intérêt d'une gestion de A à Z faite "à la main".
Mais la question posée est "Suppression d'un enregistrement".
Si les cons volaient, il ferait nuit à midi.
Pour le dernier élément du tableau, tu peux utiliser une variable NombreElement qui contient
le nombre d'éléments valides du tableau. Donc à chaque suppression tu décremente cette variable de 1. Comme ca tu n'affichera qu'une seule fois le dernier élément du tableau en cas de suppression. Et si tu veux faire un ajout dans le tableau tu fais NombreElement:=NombreElement + NombreAjoute.
RQ: NombreElement<=NombreElementMaxduTableau
Alors dans le cas d'un simple enregistrement, comment on fait. Et puis j'ai un pote de la fac qui m'a proposé d'essayer un technique mais j'y arrive pas; il dit qu'on peut creer un fichier temporaire pour copier tous les enregistrements sauf celui a suprimer en suite tout ramener dans l'ancien. Quelqu'un aurait une idée?
Gio,
La bonne vieille technique qui nécessite de savoir écrire, et de disposer d'une feuille de papier et d'un crayon (ou d'une plume d'oie, pour les vrais nostalgiques ) :
Image : on a N valeurs, on veut en supprimer une, sans laisser de trou à sa place.
Il n'y a pas des milliers de solutions.
Tu décris en clair comment tu ferais manuellement, et tu as ton(tes) algorithme(s).
Si les cons volaient, il ferait nuit à midi.
bon concrètement, mon problème est le suivant : j'ai utiliser les seek, pour faire le décalage. donc je conserve l'enregistrement suivant dans un temp ensuite je recule et je déverse, c'est bien ça et ce jusqu'à la fin, mais pour faire cette boucle j'ai fait un "while not eof(fproduit) do ", mais problème : ça plante le programme. aucune réponse tout est bloqué
Hai,
Montre ton code, sinon il est impossible de t'aider par rapport à ce que tu as fait.
Si les cons volaient, il ferait nuit à midi.
Voici le code en question
Mais en plus je rencontre d'autre problèmes, "invalid file handle" et dans la faq on ne me dit pas comment remédier a ce problè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
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31 procedure manager_dell; begin writeln('donner le code du produit a supprimer'); readln(code); reset(fproduit); read(fproduit,prod); while not eof(fproduit) do begin read(fproduit,prod); if prod.code = code then while not eof(fproduit) do begin code := prod.code; dsgn := prod.designation; pu := prod.pu; stock := prod.stock; seuil := prod.seuil; seek(fproduit,filepos(fproduit) - 1*sizeof(produit)); prod.code := code; prod.dsgn := dsgn; prod.pu := pu; prod.stock := stock; prod.seuil := seuil; {prod := tempo;} write(fproduit,prod); seek(fproduit,filepos(fproduit) + 2*sizeof(produit)); { truncate(fproduit);} break; end; end; end;
Je vous donne tout mon code en pièce jointe, si quelqu'un peut m'expliquer ces problèmes.
Hai,
Je n'ai fait que jeter un coup d'oeil, mais déjà, je vois :
- Usage intensif de variables globales : à proscrire.
(On peut pratiquement toujours s'en passer, et ça rend le code très dépendant d'une part, et d'autre par difficile à maintenir/lire)
- Pour les Seek dans les fichiers, par exemple, dans la procédure recherche
le fonction FilePos tient compte de la taille de l'enregistrement, tes calculs sont donc faux. Dans le cas présent, il suffit donc de faire
Code : Sélectionner tout - Visualiser dans une fenêtre à part Seek(fproduit, FilePos(fproduit) - (1 * SizeOf(fproduit)));
Il est bien possible que ton problème vienne de là.
Code : Sélectionner tout - Visualiser dans une fenêtre à part Seek(fproduit, FilePos(fproduit) - 1);
- Pourquoi créer des procédures de ce genre :
alors qu'une saine programmation voit ici l'occasion d'utiliser une fonction :
Code : Sélectionner tout - Visualiser dans une fenêtre à part procedure verification(login, password : string; var acces : Boolean);
- Le code principal doit être découpé en fonctions/procédures (au moins une par menu géré).
Code : Sélectionner tout - Visualiser dans une fenêtre à part function verification(login, password : string) : Boolean ;
D'une manière générale, il vaut mieux écrire une fonction ou une procédure pour chaque tâche du programme, le programme principal se contentant de les organiser (ceci reste vrai à tous les niveaux : les différentes tâches d'une procédures sont elles-mêmes des procédures, etc. [procédure est ici pris au sens général de procédure ou fonction]).
- Dans la procédure manager_dell, dont tu m'as parlé en MP, il y a une lecture de trop avant d'entrer dans la boucle While :
A part ça, je n'ai pas lu en détail le code, corrige-le, et on reverra ça.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10 procedure manager_dell; begin Writeln('donner le code du produit a supprimer'); Readln(code); Reset(fproduit); Read(fproduit, prod); { ========= ici } while not Eof(fproduit) do begin Read(fproduit, prod); if prod.code = code then
Si les cons volaient, il ferait nuit à midi.
ok, je vais tester et dans l'apres midi je te fais signe, pour les nombreuses procedures utilisées, c'est le prof qui a imposer les proc au lieu des fonction.
( comment faire pour le changer, le système me l'impose )
j'ai rectifié la partie du code manager_dell, bon ca plante plus mais ça supprime pas non plus, alors surement qu'il y un problème au niveau du code lui meme mais moi je vois pas du tout.
A propos de la technique avec un autre fichier, j'ai "finalement" pris un crayon et du papier et j'ai fait un petit prog, résultat : j'ai créé un virus ; bah ouais ça génère un fichier de 100 MO qui se duplique
euh, quand tu dis trop de variables globales, tu parle de quelles variables au juste?
Gai,
C'était de l'humour trollique.
Mets-nous ton nouveau code.
Pas un virus, un bug
Toutes les variables déclarées au niveau du programme principal (la section Var du programme) qui sont utilisées directement dans les procédures.
Une procédure/fonction devrait recevoir en paramètre tous les éléments dont elle a besoin qui sont déclarés ailleurs, et n'utiliser que des variables locales pour ce qui lui est nécessaire localement.
Exemple :
Pas bon
Bon
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 program jai; Var i : Integer; Procedure carre; Begin i := i * i; End; Begin { programme principal } i := 1; Writeln(i); carre; Writeln(i); ReadLn; End.
J'ai ici volontairement utilisé le même nom i pour la variable du programme et le nom du paramètre passé à la fonction carre : le nom du paramètre, qui est local à la fonction, prend le pas sur la variable déclarée à un niveau supérieur.
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 program jai; function carre(i : Integer) : Integer; Begin carre := i * i; End; Var i : Integer; Begin { programme principal } i := 1; Writeln(i); i := carre(i); Writeln(i); ReadLn; End.
Et dans le Bon exemple, j'ai déplacé la déclaration des variables du programme juste avant le Begin du programme principal, ce qui fait que toutes les procédures/fonctions déclarées avant ne connaissent pas ces variables, et ne peuvent donc pas les utiliser "par inadvertance".
Si les cons volaient, il ferait nuit à midi.
bon je vais utiliser ta technique ca m'a l'air super "puissant". Mais bon concernat la suppression a proprement dite, tu me conseille quoi?
Fio,
Montre le nouveau code de ta procédure.
Si les cons volaient, il ferait nuit à midi.
bon voici le code, il marche maintenant mais il y a un probleme, quand je supprime le premier enregistrement il dupilque ce dernier a la deuxieme place et je sais pas ce qui cloche dans ce code
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 procedure manager_dell; var code,stock,seuil :integer; dsgn : string; pu : real; begin writeln('donner le code du produit a supprimer'); readln(code); reset(fproduit); while not eof(fproduit) do begin read(fproduit,prod); if prod.code = code then begin if eof(fproduit) then begin seek(fproduit,filepos(fproduit) - 1); truncate(fproduit); end else repeat begin writeln(filepos(fproduit)); writeln(prod.code); code := prod.code; dsgn := prod.designation; pu := prod.pu; stock := prod.stock; {seuil := prod.seuil;} write(fproduit,prod); {<=== c'est la, j'avais pas mis cette ecriture} seek(fproduit,filepos(fproduit) - 1 ); writeln(prod.code); writeln(filepos(fproduit)); prod.code := code; writeln(prod.code); prod.designation := dsgn; prod.pu := pu; prod.stock := stock; {prod.seuil := seuil;} {prod := tempo;} write(fproduit,prod); seek(fproduit,filepos(fproduit) + 2); end; until eof(fproduit); seek(fproduit,filepos(fproduit) - 1); truncate(fproduit); writeln('produit supprim'); readkey; end; end; end;
Heo,
Moi, je sais ce qui cloche : tu te compliques beaucoup trop la vie.
Il faut faire:
- Trouver la position de l'enregistrement à supprimer
- S'il existe
- faire une boucle de cette position +1 à la fin du fichier pour décaler les enregistrements vers l'avant (une bonne vieille boucle For convient très bien)
- supprimer le dernier enregistrement.
Tes Seek avec des valeurs uniquement par rapport à FilePos, sans être fondamentalement faux, compliquent beaucoup ton code.
Petit exemple vite fait sur le gaz (et donc plutôt sommaire), n'utilisant pas de variables globales
Il faudrait faire tout ça plus proprement, entre autres :
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
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85 program test_03; {$N+} {$X+} uses crt, Dos, strings; type str5 = string[5]; rints = record n : Integer; s : str5; end; fints = file of rints; procedure remplir (var f : fints); var i : integer; t : rints; begin rewrite(f); FillChar(t,sizeof(rints),0); {pour que le contenu soit propre} for i := 0 to 6 do begin t.n := i; Str(i,t.s); write(f,t); end; end; function trouve (var f : fints; n : integer) : integer; { renvoie -1 si n'existe pas, sinon la position dans le fichier } var res : integer; t : rints; begin res := -1; reset(f); while not(eof(f)) and (res = -1) do begin read(f,t); if (t.n = n) then res := FilePos(f)-1; {-1 cause du Read !! } end; trouve := res; end; procedure supprime (var f : fints; n : integer); var t : rints; i,place : integer; begin place := trouve(f,n); if (place >= 0) then begin for i := place + 1 to FileSize(f) - 1 do begin seek(f,i); read(f,t); seek(f,i-1); write(f,t); end; seek(f,FileSize(f) -1); Truncate(f); end; end; { programme principal } var f : fints; begin assign(f,'datas.dat'); remplir(f); Reset(f); writeln(filesize(f)); supprime(f,1); supprime(f,5); close(f); ReadLn; end.
- des constantes plutôt que des valeurs "magiques"
- contrôler systématiquement tous les accès fichiers
...
Si les cons volaient, il ferait nuit à midi.
Bon je vais essayer tes conseils, mais il me semble que pour la suppression c'est ce que j'ai fait, mais je comprend pas pourquoi pour le premier ca marche pas.
Mais est ce que le fait d'utiliser une boucle peut m'éviter d'utiliser des variables temporaires?
Vous avez un bloqueur de publicités installé.
Le Club Developpez.com n'affiche que des publicités IT, discrètes et non intrusives.
Afin que nous puissions continuer à vous fournir gratuitement du contenu de qualité, merci de nous soutenir en désactivant votre bloqueur de publicités sur Developpez.com.
Partager