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

Free Pascal Discussion :

[Free Pascal] Lecture d'un fichier et plantage


Sujet :

Free Pascal

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre habitué
    Profil pro
    Inscrit en
    Janvier 2003
    Messages
    10
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : Belgique

    Informations forums :
    Inscription : Janvier 2003
    Messages : 10
    Par défaut [Free Pascal] Lecture d'un fichier et plantage
    Bonjour.
    Dans le cadre d'un jeu que l'on doit programmer, je dois créer une procédure qui écrit les stats dans un fichier, et une autre qui les lit :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    TYPE
     
    		recstat = record
    					nom : string;
    					partie : integer;
    					win : integer;
    					point : integer;
    					egal : integer;
    					end;
    		stats = array[1..1000] of recstat;

    VAR :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
       tabstats : stats;
       filestats : file of recstat;
    Procédure de lecture :

    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 lire_fichier(var tabstats : stats; var filestats : file of recstat; var taillestats : integer);
    VAR i : integer;
    begin
    i := 1;
    RESET(filestats);
    taillestats := 0;
    while(not(EOF(filestats))) do
    begin
     
    	READ(filestats, tabstats[i]);
    	i := i + 1;
    	taillestats := taillestats + 1;
    	end;
    close(filestats);
    end; {procedure}

    Code d'appel :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    ASSIGN(filestats, 'stats.txt');
    lire_fichier(tabstats, filestats, taillestats);
    Or, il se trouve que dès que j'appelle la procédure de lecture, le programme se ferme.
    Je n'ai pas trouvé pourquoi et je suppose que si je commence par appeler la procédure d'ecriture, ça me fera la même chose.
    Je suis quasi sûr que c'est parce que j'utilise mal les fichiers.

    Quelqu'un pourrait-il m'aider à trouver le problème ?

    Merci d'avance.

    Siron

  2. #2
    Responsable Pascal, Lazarus et Assembleur


    Avatar de Alcatîz
    Homme Profil pro
    Ressources humaines
    Inscrit en
    Mars 2003
    Messages
    8 055
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 58
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ressources humaines
    Secteur : Service public

    Informations forums :
    Inscription : Mars 2003
    Messages : 8 055
    Billets dans le blog
    2
    Par défaut
    Bonjour !

    Le fichier existe-t-il déjà lorsque tu exécutes la procédure de lecture ?
    Car tu ne testes pas l'éventualité que le fichier n'existe pas.

    Le fait que tu assignes un nom de fichier à filestats en dehors de la procédure de lecture indique que filestats est vraisemblablement une variable globale. Il ne faut pas transmettre filestats comme paramètre à la procédure.
    Règles du forum
    Cours et tutoriels Pascal, Delphi, Lazarus et Assembleur
    Avant de poser une question, consultez les FAQ Pascal, Delphi, Lazarus et Assembleur
    Mes tutoriels et sources Pascal

    Le problème en ce bas monde est que les imbéciles sont sûrs d'eux et fiers comme des coqs de basse cour, alors que les gens intelligents sont emplis de doute. [Bertrand Russell]
    La tolérance atteindra un tel niveau que les personnes intelligentes seront interdites de toute réflexion afin de ne pas offenser les imbéciles. [Fiodor Mikhaïlovitch Dostoïevski]

  3. #3
    Membre habitué
    Profil pro
    Inscrit en
    Janvier 2003
    Messages
    10
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : Belgique

    Informations forums :
    Inscription : Janvier 2003
    Messages : 10
    Par défaut
    Effectivement, le problème venait du fait que le fichier n'était pas créé.

    Existe t'il en pascal, une fonction qui vérifie si un fichier existe ?

    Et y a t'il moyen de ne pas indiquer l'emplacement du fichier ?
    En supposant que le fichier serait dans le repertoire de l'exe.
    Car quand je mets 'stats.txt' au lieu de 'c:\stats.txt', le fichier plante comme si le fichier n'existe pas, et ce malgré que le exe soit dans le C.

    Merci pour l'aide.

  4. #4
    Responsable Pascal, Lazarus et Assembleur


    Avatar de Alcatîz
    Homme Profil pro
    Ressources humaines
    Inscrit en
    Mars 2003
    Messages
    8 055
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 58
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ressources humaines
    Secteur : Service public

    Informations forums :
    Inscription : Mars 2003
    Messages : 8 055
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par Siron
    Existe t'il en pascal, une fonction qui vérifie si un fichier existe ?
    Si la directive de compilation {$I-} est spécifiée, le résultat de la procédure Reset peut être récupéré par la fonction IOResult : une valeur différente de 0 indique une erreur (vraisemblablement, fichier non trouvé).

    Citation Envoyé par Siron
    Et y a t'il moyen de ne pas indiquer l'emplacement du fichier ?
    En supposant que le fichier serait dans le repertoire de l'exe.
    Car quand je mets 'stats.txt' au lieu de 'c:\stats.txt', le fichier plante comme si le fichier n'existe pas, et ce malgré que le exe soit dans le C
    Si l'exécution a lieu au départ de l'IDE, il est possible que le répertoire par défaut ne soit pas celui que tu penses; par contre, si l'exécution est externe, le répertoire de l'exe est celui par défaut.
    Règles du forum
    Cours et tutoriels Pascal, Delphi, Lazarus et Assembleur
    Avant de poser une question, consultez les FAQ Pascal, Delphi, Lazarus et Assembleur
    Mes tutoriels et sources Pascal

    Le problème en ce bas monde est que les imbéciles sont sûrs d'eux et fiers comme des coqs de basse cour, alors que les gens intelligents sont emplis de doute. [Bertrand Russell]
    La tolérance atteindra un tel niveau que les personnes intelligentes seront interdites de toute réflexion afin de ne pas offenser les imbéciles. [Fiodor Mikhaïlovitch Dostoïevski]

  5. #5
    Membre habitué
    Profil pro
    Inscrit en
    Janvier 2003
    Messages
    10
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : Belgique

    Informations forums :
    Inscription : Janvier 2003
    Messages : 10
    Par défaut
    Au départ de l'ide ?
    Je comprends pas ce que tu veux dires.

    Quand à la fonction qui vérifie si le fichier existe, je crois que je vais pas l'utiliser, car en plus ça dois être compilabe sur linux et solaris.

  6. #6
    Membre chevronné

    Inscrit en
    Avril 2003
    Messages
    284
    Détails du profil
    Informations forums :
    Inscription : Avril 2003
    Messages : 284
    Par défaut
    Juste une question...
    tu as écrit :

    taillestats := 0;

    Dans ta procedure. Or tu passes taillestats en 3ème paramètre à cette dernière ???
    Quelle est l'utilité de le passer en paramètre pour le définir ensuite, dès l'ouverture du fichier à 0?

    Autre remarque : pourquoi incrementer à la fois i et taillestat à chaque boucle?

    Si tu as besoin de récupérer taillestat à la fin de ta procedure, ecrit une fonction... et déduis taillestat de i après la fin de la boucle... i part de 1 , taillestat de 0... ça ne doit pas etre trop dur

    Ce n'est pas parceque nos microprocesseur sont puissant désormais qu'il faut leur faire calculer de l'inutile

  7. #7
    Membre habitué
    Profil pro
    Inscrit en
    Janvier 2003
    Messages
    10
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : Belgique

    Informations forums :
    Inscription : Janvier 2003
    Messages : 10
    Par défaut
    J'ai besoins de taillestats dans d'autre procedure.
    Or avec une fonction, je n'ai qu'un retour, et ici dans mon cas j'ai 2 retours.

    Sinon pour le coup de l'optimisation bidon, lol, j'avais même pas pensé.
    J'ai codé ça comme ça parceque dans ma tête je m'étais dis que taillestats est une valeur indépendante.
    C'est ce qui arrive quand on code tout de tête sans ordinogramme lol.

    Edit : Corrigé :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    procedure lire_fichier(var tabstats : stats; var filestats : file of recstat; var taillestats : integer);
    VAR i : integer;
    begin
    i := 0;
    RESET(filestats);
    taillestats := 0;
    while(not(EOF(filestats))) do
    begin
        i := i + 1;
    	READ(filestats, tabstats[i]);
    	end;
    CLOSE(filestats);
    taillestats := i;
    end; {procedure}
    lol

    Edit 2 :
    Il ne faut pas transmettre filestats comme paramètre à la procédure.
    Je passe un maximum dans les paramètre, c'est ce qu'on nous a appris à faire, et c'est plus clair comme ça dès que je regarde l'en-tête de la procédure, je vois les variables globales qu'elle va utiliser.

  8. #8
    Membre chevronné

    Inscrit en
    Avril 2003
    Messages
    284
    Détails du profil
    Informations forums :
    Inscription : Avril 2003
    Messages : 284
    Par défaut
    C'est une façon de voir
    Je passe un maximum dans les paramètre, c'est ce qu'on nous a appris à faire, et c'est plus clair comme ça dès que je regarde l'en-tête de la procédure, je vois les variables global qu'elle va utiliser.
    pourquoi ne pas mettre un commentaire?
    et ne pas créer de confusion entre le paramètre d'une procedure, qui au sein de cette dernière est une variable locale et ta variable globale? ce petit exemple te montre (en tout cas avec mon compilateur : freepascal
    que l'utilisation du nom d'une variable globale passé en paramètre dans une procedure laisse inchangée la variable globale et n'affecte que la variable au sein de la procedure...
    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
    program project1;
     
    {$mode objfpc}{$H+}
    var
    VarGlobale : string;
     
    procedure modifie1(param1 : string);
    begin
      param1 := param1 + 'ZZZ';
    end;
     
    procedure modifie2(VarGlobale : string); // ta façon de faire
    begin
      VarGlobale := VarGlobale + 'ZZZ';
    end;
     
    procedure modifie3(param1 : string); // Mieux
    begin
      param1 := param1 + 'ZZZ';
      VarGlobale := param1;
    end;
     
    procedure modifie4; // (VarGlobale : string) Encore Mieux !
    begin
      VarGlobale := VarGlobale + 'ZZZ';
    end;
     
    begin
    VarGlobale := 'chaine de depart';
    Writeln(VarGlobale,' juste initialisée ');
    modifie1(varglobale);
    Writeln(VarGlobale,' après modifie1 : rien n''a changé ');
    modifie2(varglobale);
    Writeln(VarGlobale,' après modifie2 : rien n''a changé ');
    modifie3(varglobale);
    Writeln(VarGlobale,' après modifie3 : modifié');
    modifie4;
    Writeln(VarGlobale,' après modifie4 : encore modifié');
    readln;
    end.

    le résultat donne :
    Chaine de départ juste initialisée
    Chaine de départ après modifie1 : rien n''a changé
    Chaine de départ après modifie2 : rien n''a changé
    Chaine de départZZZ après modifie3 : modifié
    Chaine de départZZZZZZ après modifie4 : encore modifié
    Mais peut-etre que ton compilateur ne réagit pas comme le mien....

  9. #9
    Membre chevronné

    Inscrit en
    Avril 2003
    Messages
    284
    Détails du profil
    Informations forums :
    Inscription : Avril 2003
    Messages : 284
    Par défaut
    PS .. je reviens sur ton problème de path :
    Tu peux tenter d'utiliser paramstr(0), en ayant bien en tète que sous linux, tu risque d'être en présence non pas de ton binaire, mais d'un lien symbolique, ce qui peut avoir de facheuses repercutions sur la suite des opérations...

    Cet article :
    http://wiki.lazarus.freepascal.org/index.php/Multiplatform_Programming_Guide#On_Linux_there_is_no_.22application_directory.22
    conseille d'utiliser la fonctions GetAppConfigDir pour y placer un fichier de configuration de ton application... Ceci devant etre fait lors de l'installation bien sûr ... pas simple, je sais, mais le multiplatteforme est plein de surprises de ce genre...

    Bonne continuation

    Clandestino

  10. #10
    Membre habitué
    Profil pro
    Inscrit en
    Janvier 2003
    Messages
    10
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : Belgique

    Informations forums :
    Inscription : Janvier 2003
    Messages : 10
    Par défaut
    J'ai trouvé comme faire, par le biais d'une librairie, j'ai une fonction fileexists dispo qui me renvoit un boolean.

    Ca marche nikel.

    Clandestino ==> tu dois mettre VAR devant les variables globals que tu veux modifier en les passants dans une en tête de procédure :

    procedure modifie(VAR i : integer);



    Par contre sous linux je me suis retrouvé avec plusieurs problèmes :

    Je crois que le problème vient du faite de :


    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 lire_fichier(var tabstats : stats; var filestats : [b]file of[/b] recstat; var taillestats : integer);
    VAR i : integer;
    begin
    i := 1;
    RESET(filestats);
    taillestats := 0;
    while(not(EOF(filestats))) do
    begin
     
       READ(filestats, tabstats[i]);
       i := i + 1;
       taillestats := taillestats + 1;
       end;
    close(filestats);
    end; {procedure}
    Il semblerais que le faite que la variable soit un file of perturbe le compilateur, du moins c'est des messages d'erreurs relatifs au file of.
    Un copain fait exactement la même chose que moi, sauf qu'il passe par une constante pour son fichier (ou un truc comme ça), et donc il n'a pas le message d'erreur.

    Mais jeudi j'ai tp et si j'arrive pas à débuguer d'ici la, je demanderais aux asistants.[/code]

  11. #11
    Responsable Pascal, Lazarus et Assembleur


    Avatar de Alcatîz
    Homme Profil pro
    Ressources humaines
    Inscrit en
    Mars 2003
    Messages
    8 055
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 58
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ressources humaines
    Secteur : Service public

    Informations forums :
    Inscription : Mars 2003
    Messages : 8 055
    Billets dans le blog
    2
    Par défaut
    L'utilisation de IOResult pour tester l'existence du fichier fonctionne avec toutes les plate-formes et est quand même très simple :
    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
    {$I-}
    RESET(filestats); 
    [$I+}
    if IOResult = 0 then
    begin
       taillestats := 0; 
       while(not(EOF(filestats))) do 
       begin 
     
          READ(filestats, tabstats[i]); 
          i := i + 1; 
          taillestats := taillestats + 1; 
          end; 
       close(filestats); 
    end else
       // message d'erreur
    Règles du forum
    Cours et tutoriels Pascal, Delphi, Lazarus et Assembleur
    Avant de poser une question, consultez les FAQ Pascal, Delphi, Lazarus et Assembleur
    Mes tutoriels et sources Pascal

    Le problème en ce bas monde est que les imbéciles sont sûrs d'eux et fiers comme des coqs de basse cour, alors que les gens intelligents sont emplis de doute. [Bertrand Russell]
    La tolérance atteindra un tel niveau que les personnes intelligentes seront interdites de toute réflexion afin de ne pas offenser les imbéciles. [Fiodor Mikhaïlovitch Dostoïevski]

  12. #12
    Membre habitué
    Profil pro
    Inscrit en
    Janvier 2003
    Messages
    10
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : Belgique

    Informations forums :
    Inscription : Janvier 2003
    Messages : 10
    Par défaut
    Ben oui, mais comme y a une librairie dispo par defaut sous solaris et dev-pascal qui permet d'avoir une fonction adéquate, je vais l'utiliser.

  13. #13
    Membre émérite
    Inscrit en
    Juin 2005
    Messages
    644
    Détails du profil
    Informations professionnelles :
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2005
    Messages : 644
    Par défaut
    avec un type incluant des strings comme celui proposé,
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    TYPE
          recstat = record
                   nom : string;
                   partie : integer;
                   win : integer;
                   point : integer;
                   egal : integer;
                   end;
          stats = array[1..1000] of recstat;
    j'ai déjà eu des problèmes d'allignement car les strings ne sont pas tous de la même longueur. J'utiliserais plutôt une structure
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    TYPE
     
          recstat = record
                   Cnom : array[0..$ff] of char;
                   partie : integer;
                   win : integer;
                   point : integer;
                   egal : integer;
                   end;
          stats = array[1..1000] of recstat;
    ici recstat est de longueur parfaitement fixe et il ne devrait plus y avoir de problèmes.
    à la sauvegarde il suffit de faire un move de nom sur CNom avec un code du type
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    var nom :  string; var L : byte absolute nom;
       begin
       ...
       move(nom[0],stats[numero actuel].Cnom,L+1);
       ...
       end;
    et le move opposé en lecture;

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

Discussions similaires

  1. [Free Pascal] Transfert des fichiers de données créés sous TP vers Free Pascal
    Par NOVICE76 dans le forum Free Pascal
    Réponses: 8
    Dernier message: 11/08/2014, 16h45
  2. Réponses: 6
    Dernier message: 02/09/2003, 15h12
  3. Lecture et ecriture fichier .ini
    Par despe dans le forum C
    Réponses: 6
    Dernier message: 23/07/2003, 20h40
  4. [langage] Optimiser la lecture d'un fichier
    Par And_the_problem_is dans le forum Langage
    Réponses: 4
    Dernier message: 05/02/2003, 08h54
  5. [langage] Optimiser la lecture d'un fichier
    Par And_the_problem_is dans le forum Langage
    Réponses: 2
    Dernier message: 11/06/2002, 10h24

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