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

  • Votes
  • Date
  • Date décroissante
  1. 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 ;-)
    1. 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.
    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. 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?
    4. 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
        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.