Programmation Help vieux rouillé

Résolu
romaingeol -  
_vince Messages postés 37 Statut Membre -
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. Sacabouffe Messages postés 9427 Date d'inscription   Statut Membre Dernière intervention   1 863
     
    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.
    0
  2. romaingeol
     
    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
    0
  3. Sacabouffe Messages postés 9427 Date d'inscription   Statut Membre Dernière intervention   1 863
     
    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...).
    0
    1. Sacabouffe Messages postés 9427 Date d'inscription   Statut Membre Dernière intervention   1 863
       
      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?
      0
  4. romaingeol
     
    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
    0
    1. _vince Messages postés 37 Statut Membre
       
      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.
      0
      1. Sacabouffe Messages postés 9427 Date d'inscription   Statut Membre Dernière intervention   1 863 > _vince Messages postés 37 Statut Membre
         
        Parce 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.
        0
  5. Vous n’avez pas trouvé la réponse que vous recherchez ?

    Posez votre question
  6. romaingeol
     
    j'ai cherché avec awk mais je ne voyais pas comment faire...
    0
    1. _vince Messages postés 37 Statut Membre
       
      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 ;-)
      0
      1. Sacabouffe Messages postés 9427 Date d'inscription   Statut Membre Dernière intervention   1 863 > _vince Messages postés 37 Statut Membre
         
        Ah 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.
        0
  7. _vince Messages postés 37 Statut Membre
     
    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 ;-)
    0