ronoobresil
Messages postés7Date d'inscriptionsamedi 12 avril 2008StatutMembreDernière intervention15 avril 2008
-
12 avril 2008 à 03:18
ronoobresil
Messages postés7Date d'inscriptionsamedi 12 avril 2008StatutMembreDernière intervention15 avril 2008
-
12 avril 2008 à 16:27
Bonjour,
Je suis débutant sous Delphi...Ça fait pas mal de temps que j'avais pas fait de programmation
Et, bien évidemment comme tout bon débutant, j'ai un problème que je n'arrive pas à résoudre depuis quelques jours...J'ai pas mal cherché dans l'aide, sur le net, mais je commence à être à court d'idées...
J'espere que ma difficulté vous sautera aux yeux.
Je cherche à developper une petite application, sans prétention, pour ouvrir un fichier texte, stocker ses valeurs et les modifier, (puis plus tard sauver dans un autre fichier)
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
tex:TstringList;
filename,filepath : string;
a:integer;
b:string;
implementation
{$R *.dfm}
Function effacerentete(tex:TStringList;nl:integer):TStringList;
var premiercar,temp:string;
i,j,nbre,err:integer;
F:TStringList;
begin
F:=TstringList.Create;
j:=1;
for i:=1 to nl do
begin
temp:=tex[i];
premiercar:=copy(temp,1,1);
Val(premiercar,nbre,err);
if (err=0) then //si premier caractere est un nomnbre
begin
F[j]:=Tex[i]; //rempli le TstrinList F avec les lignes correspondantes
j:=j+1;
end;
end;
Result:=F; //renvoie F comme resultat
F.Free
end;
procedure TForm1.SpeedButton1Click(Sender: TObject);
begin
tex:=TstringList.Create; // initialise tex
with OpenDialog1 do
begin
if Execute then
begin
fileName := OpenDialog1.FileName;
Edit1.Text:=filename;
tex.LoadFromFile(filename); //rempli tex
Label1.Caption:=tex[1] //affiche la premiere ligne pour verifier le contenu
end;
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
a:=tex.Count; //determine le nombre de lignes
tex:=effacerentete(tex,a); //efface les lignes commençant par autre chose que des chiffres
Label1.Caption:=tex[1]; //affiche la premiere ligne (verification)
tex.Free //libere tex
end;
end.
Deux choses:-tout marche jusqu'à tex:=effacerentete(tex,a); ...La ça coince... Il n'a pas l'air de rentrer dans la focntion, plante avant.
-si je place
STR(a,b);
Label1.Caption:=b;
avant l'appel de la fonction effacerentete Label1n'affiche pas la valeur de b (meme si je mets un sleep(2000) juste après. Mais l'affiche si je supprime l'appel de la focntion...
Je suppose que c'est la même cause.. Merci pour tout,
cs_Delphiprog
Messages postés4297Date d'inscriptionsamedi 19 janvier 2002StatutMembreDernière intervention 9 janvier 201332 12 avril 2008 à 10:02
Je te laisse deviner où est ton erreur :
Function effacerentete(tex:TStringList;nl:integer):TStringList;
var premiercar,temp:string;
i,j,nbre,err:integer;
F:TStringList;
begin
F:= TstringList.Create;
j:=1;
for i:=1 to nl do
begin
temp:=tex[i];
premiercar:=copy(temp,1,1);
Val(premiercar,nbre,err);
if (err=0) then //si premier caractere est un nomnbre
begin
F[j]:=Tex[i]; //rempli le TstrinList F avec les lignes correspondantes
j:=j+1;
end;
end;
Result:=F; //renvoie F comme resultat
F.Free
end;
Si tu libères l'objet retourné, comment veux-tu pouvoir y accéder ensuite si la référence tex est nulle ???
Ce genre de programmation est à proscrire et il faut revenir aux fondamentaux : c'est à l'appelant de détruire les objets qu'il crée et non à l'appelé. Sinon, quand le code devient un tant soit peu complexe, on se fait vite avoir.
Je te propose une autre forme, cette fois sans risque :
unit Unit1;
{$R *.dfm}
var
tex: TstringList;
a: integer;
FileName: TFileName;
procedure EffacerEntete(Tex: TStringList; nl: integer);
var
i: integer;
F: TStringList;
begin
if nl < 0 then
exit;
F : = TstringList.Create;
try
for i := 1 to nl do
if length(Tex[i]) > 0 then
begin
if Tex[i][1] in ['0'..'9'] then
F.Append(Tex[i]);
end;
Tex.Assign(F);
finally
F.Free
end; {try..finally}
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
a := tex.Count; //determine le nombre de lignes
effacerentete(tex, a);
//efface les lignes commençant par autre chose que des chiffres
Label1.Caption := tex[1]; //affiche la premiere ligne (verification)
///////////////// tex.Free NON, non et non !
end;
procedure TForm1.SpeedButton1Click(Sender: TObject);
begin
///////////////// tex := TstringList.Create; // NON !!!
if OpenDialog1.Execute then
begin
fileName := OpenDialog1.FileName;
Edit1.Text := filename;
tex.LoadFromFile(filename); //rempli tex
Label1.Caption := tex[1]
end;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
Tex := TStringList.Create
end;
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
Tex.Free;
end;
end.
Tu remarqueras certains commentaires destinés à attirer ton attention sur les risques que tu prends en instanciant un TStringList dans button1click et en le libérant dans speedbutton1click. Il est préférable, vu que ce composant n'a pas de propriétaire, de s'assurer qu'il sera libéré dans tous les cas de figure. Ici, le composant Tex est intsnacié dans le OnCreate de la fiche et libéré dans le OnClose.
May Delphi be with you !
<hr color="#008000" />Pensez à cliquer sur Réponse acceptée lorsque la réponse vous convient.
cs_Delphiprog
Messages postés4297Date d'inscriptionsamedi 19 janvier 2002StatutMembreDernière intervention 9 janvier 201332 12 avril 2008 à 10:04
J'ai oublié de préciser que l'emploi de :
if Tex[i][1] in ['0'..'9'] then
F.Append(Tex[i]);
est surement moins coûteux en temps de traitement que l'emploi de la fonction VAL.
Bonne journé et May Delphi be with you ! <hr color="#008000" />Pensez à cliquer sur Réponse acceptée lorsque la réponse vous convient.
schnawd
Messages postés20Date d'inscriptionmardi 5 octobre 2004StatutMembreDernière intervention12 juillet 2015 12 avril 2008 à 10:11
Bonjour,
Serrait-il possible de savoir la tête que ton fichier aura, et ce que tu veux récupérer dedant.
Sinon pour sauver plus tard les données dans un autre fichier, si l'application se ferme, alors tu perds tout, Donc ans ce cas là tu dois l'enregistrer dans un fichier temporaire, puis le recharger à chaque redémarrage de l'appli.
Sinon au lieu d'utiliser un label, utilise un memo que tu mets en read-only, car si j'ai bien compris b est de type TStringList, donc tu peux te débrouiller à le mettre en TStrings, de façon à faire un
memo.lines := b;
Et puis tu fais ce que tu veux du style de memo, tu peux très bien le faire ressembler à un TCaption.
ronoobresil
Messages postés7Date d'inscriptionsamedi 12 avril 2008StatutMembreDernière intervention15 avril 2008 12 avril 2008 à 15:11
Merci pour la rapidité (et l'efficacité) de la réponse.
Mes fichiers ASCII se présentent sous la forme suivante:
-Une entête avec quelques lignes de texte (programme de création, date, parametres divers) =>à supprimer
-Un tableau de 7 ou 8 colonnes d'entier séparés par des tabulations, dont je ne veux garder que certaines colonnes.
Je desire faire de petites opérations, un tri de ces valeurs et remettre une entête (que le programme pour lequel je fais cette conversion reconnaisse).
Mon but est de formater mon fichier ASCII pour qu'il soit utilisable par une seconde application.(déjà existante).
En tout cas merci, ça me remotive, j'y retourne....
Renaud
Vous n’avez pas trouvé la réponse que vous recherchez ?
ronoobresil
Messages postés7Date d'inscriptionsamedi 12 avril 2008StatutMembreDernière intervention15 avril 2008 12 avril 2008 à 16:10
Rebonjour,
La procédure liée au click speedbutton1 ne fonctionne pas jusqu'au bout (plantage avant).
procedure TForm1.SpeedButton1Click(Sender: TObject);
begin
if OpenDialog1.Execute then
begin
fileName := OpenDialog1.FileName;
Edit1.Text := filename;
tex.LoadFromFile(filename); //la procedure semble planter sur cette ligne
Label1.Caption := tex[1]
end;
end;
Instantanément après de la selection du fichier, ça coupe, avec le message d'erreur suivant:
"Project Project1.exe raised execption class EAccessViolation with message
"Access Violation at address 00454584 in module Project1.exe". Read of address 000000000. Access stopped"
Je tourne depuis une ou deux heures...J'espere que vous pourrez m'éclairer à nouveau. Bonne journée,