Programmation Help vieux rouillé

Résolu
Bonjour,

Bonjour,

Voila, j'ai un ensemble de fichier ascii (une centaine) contenant un nombre de lignes variables de valeurs rangées dans l'ordre décroissant:

exemple:

fichier1.out

339.87
333.85
332.12
328.35
323.57
320.36
308.99
303.39
297.65
289.89
288.54
276.96
265.50
227.05

Je voudrais calculer la valeur X(n+1) - X(n), avec n l'indice de ligne, sauf pour la dernière ligne ou l'opération doit être 360-(X(1)-X(finale)).

Je veux ensuite conserver uniquement la valeur max de cette série de calcul.

Enfin je voudrai obtenir un fichier de type:

Nom du fichier Valeur Max

fichier1.out 50
fichier2.out 100
.
.
.
.
etc.

Dans lequel sont rassemblées les valeurs max obtenues pour chaque fichier .out

Mon fortran et mon C sont beaucoup trop loin et je n'ai malheureusement pas beaucoup de temps.
Si quelqu'un peut m'aider....

Merci
Configuration: Windows XP
Firefox 2.0

6 réponses

  1. Salut romaingeol
    Ouhla, tu m'as obligé à ressortir et à dépoussiérer les vieux codes fortran pour voir comment on faisait ne serait-ce qu'une boucle, tentons quand même...

    On va supposer que ton programme et tes fichiers sont dans le même répertoire, ce qui est pas très propre en fait donc si tu veux changer ça dis le moi (en supposant que le programme marche déjà...), c'est du Fortran90

    PROGRAM CALCUL_ROMAINGEOL
    
    IMPLICIT NONE
    INTEGER :: UNITE_LECTURE
    INTEGER :: UNITE_ECRITURE
    INTEGER :: NOMBRE_FICHIERS
    CHARACTER*4 :: CHAR_FICH
    CHARACTER*15 :: NOM_FICHIER
    INTEGER :: I,J,N_LIGNES
    REAL*8 :: DUMMY,TESTVAL,TEST
    REAL*8, POINTER, DIMENSION(:) :: VALEURS
    
    UNITE_ECRITURE=67
    UNITE_LECTURE=66
    
    WRITE(*,*) 'Nombre de fichiers : '
    READ(*,*) NOMBRE_FICHIERS
    
    OPEN(UNIT=UNITE_ECRITURE,FILE='Valeurs_Max.dat',&
                & STATUS='unknown',ACTION='write')
    
    DO I=1,NOMBRE_FICHIERS
          WRITE(CHAR_FICH,'(I4)') I 
          NOM_FICHIER='fichier'//TRIM(CHAR_FICH)//'.out'
          OPEN(UNIT=UNITE_LECTURE,FILE=TRIM(NOM_FICHIER),&
                & STATUS='old',ACTION='read')
    
    !! PREMIER PASSAGE POUR COMPTER LE NOMBRE DE LIGNES DU FICHIER !!
    !! ET ENSUITE ALLOUER VALEURS !!
          N_LIGNES = 0
          DO WHILE (0 < 1)
                 READ(UNITE_LECTURE,*,ERR=125,END=123) DUMMY
                 N_LIGNES = N_LIGNES+1
          END DO
          123 CONTINUE
    
          REWIND(UNITE_LECTURE)
    
          ALLOCATE(VALEURS(N_LIGNES))
           DO J=1,N_LIGNES
              READ(UNITE_LECTURE,*,ERR=125,END=125) VALEURS(J)
           END DO
    
           TEST=360-(VALEURS(1)-VALEURS(N_LIGNES))
           DO J=1,N_LIGNES-1
                 TESTVAL=VALEURS(J+1)-VALEURS(J)
                 IF (TESTVAL > TEST) THEN
                      TEST=TESTVAL
                 END IF
           END DO
    
    DEALLOCATE(VALEURS)
    
    WRITE(UNITE_ECRITURE,*) TRIM(NOM_FICHIER)//'     ', TEST
    
    CLOSE(UNITE_LECTURE)
    
    END DO
    
    CLOSE(UNITE_ECRITURE)
    RETURN
    125 CONTINUE
    WRITE(*,*) 'Erreur'
    STOP


    Pas sûr que ça marche... je l'ai même pas testé.
    Dis-moi quand même.
    1. Ok, Merci!
      il y avait quelques anomalie dans les noms de variables mais le programme marche pour l'exemple que je t'ai donné.
      Le problème c'est que les fichier .out ont des noms totalement aléatoires:

      exemple 990710_101010.out

      Seul la longueur des noms de fichiers est constante.

      PROGRAM CALCUL_ROMAINGEOL

      IMPLICIT NONE
      INTEGER :: UNITE_LECTURE
      INTEGER :: UNITE_ECRITURE
      INTEGER :: NOMBRE_FICHIERS
      CHARACTER*4 :: CHAR_FICH
      CHARACTER*15 :: NOM_FICHIER_INPUT
      CHARACTER*15 :: NOM_FICHIER_RESULTAT
      INTEGER :: I,J,N_LIGNES
      REAL*8 :: DUMMY,TESTVAL,TEST
      REAL*8, POINTER, DIMENSION(:) :: VALEURS

      UNITE_ECRITURE=67
      UNITE_LECTURE=66

      WRITE(*,*) 'Nombre de fichiers : '
      READ(*,*) NOMBRE_FICHIERS

      OPEN(UNIT=UNITE_ECRITURE,FILE='Valeurs_Max.dat', STATUS='unknown',ACTION='write')

      DO I=1,NOMBRE_FICHIERS
      WRITE(CHAR_FICH,'(I1)') I
      NOM_FICHIER_INPUT='fichier'//TRIM(CHAR_FICH)//'.out'

      WRITE(*,*) NOM_FICHIER_INPUT
      OPEN(UNIT=UNITE_LECTURE,FILE=NOM_FICHIER_INPUT, STATUS='old',ACTION='read')

      !! PREMIER PASSAGE POUR COMPTER LE NOMBRE DE LIGNES DU FICHIER !!
      !! ET ENSUITE ALLOUER VALEURS !!
      N_LIGNES = 0
      DO WHILE (0 < 1)
      READ(UNITE_LECTURE,*,ERR=125,END=123) DUMMY
      N_LIGNES = N_LIGNES+1
      END DO
      123 CONTINUE

      REWIND(UNITE_LECTURE)

      ALLOCATE(VALEURS(N_LIGNES))
      DO J=1,N_LIGNES
      READ(UNITE_LECTURE,*,ERR=125,END=125) VALEURS(J)
      END DO

      TEST=360-(VALEURS(1)-VALEURS(N_LIGNES))
      DO J=1,N_LIGNES-1
      TESTVAL=VALEURS(J+1)-VALEURS(J)
      IF (TESTVAL > TEST) THEN
      TEST=TESTVAL
      END IF
      END DO

      DEALLOCATE(VALEURS)

      WRITE(UNITE_ECRITURE,*) TRIM(NOM_FICHIER_INPUT)//' ', TEST

      CLOSE(UNITE_LECTURE)

      END DO

      CLOSE(UNITE_ECRITURE)
      RETURN
      125 CONTINUE
      WRITE(*,*) 'Erreur'
      STOP
      END
      1. Salut romaingeol

        En Fortran je vois pas comment on peut faire ce que tu veux, il y a peut-être un moyen d'ouvrir un par un tous les fichiers d'un répertoire mais je le connais pas.

        La seule solution que je peux te donner (avec ce que je connais) c'est de créer au départ un fichier avec tous les noms de tes fichier.out
        Dans ce cas ce serait mieux de réorganiser un peu le code.
        Voilà ce que je te suggèrerais:

        Appelons TRAVAIL le répertoire où sera ton code et tes fichiers de données.
        Dans TRAVAIL tu mettras ton code.
        Dans le répertoire TRAVAIL tu crées un sous-dossier que t'appelles par exemple DATA
        et dans lequel tu mets tous tes fichier.out

        D'après ton premier message t'es sous Windows (du moins pour ton message dans le forum)... Donc tu ouvres une fenêtre de commande (Windows+R -> cmd -> OK), tu te places dans TRAVAIL/DATA et tapes dir /A:A /B > ../data_files.dat (si t'es sous Unix ou Linux tu tapes ls > ../data_files.dat), ça te créera un fichier data_files.dat avec le nom de tous tes fichiers de données dans le répertoire TRAVAIL

        Ensuite pour le code je ferais ça:
        PROGRAM CALCUL_ROMAINGEOL
        
        IMPLICIT NONE
        INTEGER :: UNITE_LECTURE
        INTEGER :: UNITE_ECRITURE
        CHARACTER*17, POINTER, DIMENSION(:) :: NOM_FICHIER_INPUT
        CHARACTER*17 :: DUMMY_CHAR
        CHARACTER*22 :: FICHIER_TEMP
        INTEGER :: I,J,N_FICHIERS,N_LIGNES
        REAL*8 :: DUMMY,TESTVAL,TEST
        REAL*8, POINTER, DIMENSION(:) :: VALEURS
        
        UNITE_ECRITURE=67
        UNITE_LECTURE=66
        
        OPEN(UNIT=UNITE_LECTURE,FILE='data_files.dat', STATUS='old',ACTION='read')
        !! PREMIER PASSAGE POUR COMPTER LE NOMBRE DE LIGNES DU FICHIER !!
        !! ET ENSUITE ALLOUER NOM_FICHIER_INPUT !!
        N_FICHIERS = 0
        DO WHILE (0 < 1)
        READ(UNITE_LECTURE,*,ERR=125,END=121) DUMMY_CHAR
        N_FICHIERS = N_FICHIERS+1
        END DO
        121 CONTINUE
        
        REWIND(UNITE_LECTURE)
        
        ALLOCATE(NOM_FICHIER_INPUT(N_FICHIERS))
        DO I=1,N_FICHIERS
        READ(UNITE_LECTURE,*,ERR=125,END=125) NOM_FICHIER_INPUT(J)
        END DO
        
        CLOSE(UNITE_LECTURE)
        
        OPEN(UNIT=UNITE_ECRITURE,FILE='Valeurs_Max.dat', STATUS='unknown',ACTION='write')
        
        DO I=1,N_FICHIERS
        FICHIER_TEMP='DATA/'//NOM_FICHIER_INPUT(I)
        OPEN(UNIT=UNITE_LECTURE,FILE=TRIM(FICHIER_TEMP), STATUS='old',ACTION='read')
        
        !! PREMIER PASSAGE POUR COMPTER LE NOMBRE DE LIGNES DU FICHIER !!
        !! ET ENSUITE ALLOUER VALEURS !!
        N_LIGNES = 0
        DO WHILE (0 < 1)
        READ(UNITE_LECTURE,*,ERR=125,END=123) DUMMY
        N_LIGNES = N_LIGNES+1
        END DO
        123 CONTINUE
        
        REWIND(UNITE_LECTURE)
        
        ALLOCATE(VALEURS(N_LIGNES))
        DO J=1,N_LIGNES
        READ(UNITE_LECTURE,*,ERR=125,END=125) VALEURS(J)
        END DO
        
        TEST=360-(VALEURS(1)-VALEURS(N_LIGNES))
        DO J=1,N_LIGNES-1
        TESTVAL=VALEURS(J+1)-VALEURS(J)
        IF (TESTVAL > TEST) THEN
        TEST=TESTVAL
        END IF
        END DO
        
        DEALLOCATE(VALEURS)
        
        WRITE(UNITE_ECRITURE,*) TRIM(NOM_FICHIER_INPUT(I))//' ', TEST
        
        CLOSE(UNITE_LECTURE)
        
        END DO
        
        DEALLOCATE(NOM_FICHIER_INPUT)
        
        CLOSE(UNITE_ECRITURE)
        
        RETURN
        125 CONTINUE
        WRITE(*,*) 'Erreur'
        STOP
        END

        Pour les tableaux de caractères, je sais plus si c'est possible en Fortran et si c'est le cas je sais pas si ma syntaxe est bonne, tu me diras...

        Après tu peux aussi créer un exécutable qui te fasse tout (lister les fichiers et exécuter le code Fortran). C'est tout con mais je sais même pas faire un truc aussi simple sous Windows. Donc au cas où t'aurais aussi un Unix ou Linux voilà ce que tu peux faire :

        Tu crées un fichier merged_code dans le répertoire TRAVAIL dans lequel il y aura :
        #!/bin/sh
        cd DATA
        ls > ../data_files.dat
        cd ..
        nom_de_l'exécutable_fortran
        

        Tu oublies pas de faire un chmod +x merged_code et normalement en lançant merged_code ça devrait rouler (enfin je crois...).
        1. Ah mais c'est tout facile!!! (merci Davide...)
          C'est tout pareil sous Windows pour le dernier truc que je t'ai écrit (ou presque), tu tapes ça :
          cd DATA
          dir /A:A /B > ../data_files.dat
          cd ..
          nom_de_l'exécutable_fortran
          

          Et tu l'enregistres en merged_code.bat et ça suffit, il y a rien d'autre à faire.

          Mais là en fait j'ai surtout l'impression d'écrire dans le vide... T'es toujours là romaingeol?
          Allô! McFly? Y'a personne au bout du fil?
      2. Oui désolé, je suis là

        Merci beaucoup, j'étais arrivé aux m^mes conclusions.
        Le programme tourne et ça m'a permis de bien révisé mon fortran

        encore merci
        1. Pourquoi le fortran, si ce n'est pas indiscret ? A mon humble avis, on peut un programme moins long avec un langage de script comme awk par exemple.
        2. @_vinceParce que romaingeol parlait de Fortran ou de C dans son premier message.
          C'est vrai que je me suis pas posé la question de savoir si ça ce faisait facilement avec autre chose, je lui ai donné une méthode avec ce que je savais faire, c'est probablement pas la meilleure, mais elle avait l'air de marcher.

          Mais toutes les solutions sont les bienvenues _vince!!! Si t'as un truc tu peux l'écrire, romaingeol choisira la solution qui lui convient le mieux.

          Et de rien... content que ça marche romaingeol!!!

          A plus et bonne journée à vous deux.
      3. j'ai cherché avec awk mais je ne voyais pas comment faire...
        1. Je crois que j'ai parle un peu trop vite.... Il n'y a pas de fonction REWIND en awk et on ne connait pas le nombre de total de lignes lors de la lecture des differents fichiers. Pour contourner "simplement" le probleme, il faudrait rajouter une balise en debut ou fin de fichier ;-)
        2. @_vinceAh ben dans ce cas, une boucle sur tous les fichiers avec echo % >> fichiers.out c'est bon, non?
          Ça donne quoi ce que t'as? Fais voir.
      4. Finalement, j'ai trouve une solution qui vaut ce qui vaut. Je n'ai pas verifie les resultats.
        En rajoutant une balise "fin" a la fin de chaque fichier, ca me donne un scripte du genre:

        BEGIN {
        # tous les fichiers en entree doivent avoir "fin" sur la derniere ligne

        # 1 correspond a la premiere ligne, 2 a la deuxieme, 3 aux lignes suivantes
        flag = 1;

        # valeur interdite
        DUMMY = -666;
        # contient X(N-1)
        derniere = DUMMY;
        # contient X(N-2)
        avantderniere = DUMMY;
        # contient X(1)
        premiere = DUMMY

        LOGFILE = "file.out"
        print "" > LOGFILE
        }

        3 == flag && $1 !~ /fin/ && derniere != DUMMY && avantderniere != DUMMY {
        ## de la ligne N = 3 jusque (N_MAX - 1),
        ## ret = X(N-1) - X(N-2)
        ret = derniere - avantderniere;
        if (ret_max < ret) {
        ret_max = ret;
        }
        # on decale
        avantderniere = derniere
        derniere = $1;
        }

        2 == flag && $1 !~ /fin/ && derniere == DUMMY && avantderniere != DUMMY {
        ## deuxieme ligne du fichier, N = 2
        ## on ne calcule toujours rien
        derniere = $1;
        flag = 3;
        ## premiere valeur "par defaut" de ret_max
        ret_max = derniere - avantderniere;
        }

        1 == flag && $1 !~ /fin/ && premiere == DUMMY && avantderniere == DUMMY && derniere == DUMMY {
        ## premiere ligne du fichier, N = 1
        ## on calcule rien
        flag = 2;
        avantderniere = $1;
        premiere = $1;
        }

        /fin/ && derniere != DUMMY && premiere != DUMMY {
        ## derniere ligne du fichier (N_MAX)
        flag = 1;
        ret = 360 - (premiere - derniere);
        if (ret_max < ret) {
        ret_max = ret;
        }
        print FILENAME "\t" ret_max >> LOGFILE;

        ## par securite
        derniere = DUMMY;
        avantderniere = DUMMY;
        premiere = DUMMY;
        }

        ###########

        Il faut ensuite executer le script comme ca:
        awk -f test.awk file*.in

        Il y a avait plus simple en mettant le script dans un shell pour compter le nombre de lignes du fichier pour le passer en variable au script awk. On doit pouvoir aussi faire plus simple en perl, en lisant chaque, puis en mettant les valeurs dans un tableau... mais j'arrete la pour les exercices intellectuels ;-)