Programmation Help vieux rouillé

Résolu
romaingeol -  
_vince Messages postés 37 Date d'inscription   Statut Membre Dernière intervention   -
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
A voir également:

6 réponses

Sacabouffe Messages postés 9427 Date d'inscription   Statut Membre Dernière intervention   1 835
 
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
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
Sacabouffe Messages postés 9427 Date d'inscription   Statut Membre Dernière intervention   1 835
 
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
Sacabouffe Messages postés 9427 Date d'inscription   Statut Membre Dernière intervention   1 835
 
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
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
_vince Messages postés 37 Date d'inscription   Statut Membre Dernière intervention  
 
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
Sacabouffe Messages postés 9427 Date d'inscription   Statut Membre Dernière intervention   1 835 > _vince Messages postés 37 Date d'inscription   Statut Membre Dernière intervention  
 
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

Vous n’avez pas trouvé la réponse que vous recherchez ?

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