Linux VI f77
Linux VI f77
Linux VI f77
cal (calendar)
cal 2002
date (affiche la date, le mois, l'heure et l'année du jour. Les messages d'erreur
et les e-mails sont toujours datés avec la date système)
date -s
wc ("word & count", affiche le nombre de lignes + mots + caractères)
who | wc -l (affiche uniquement le nombre de lignes)
spell (programme de correction orthographique)
cat rapport.txt | spell > faute.txt
read (lit dans un script shell la ligne saisie à partir de l'entrée par défaut, le
clavier)
L'Éditeur vi
vi est un éditeur de fichiers qui contiennent des lignes de texte. Il fonctionne en mode écran; le nom vi
provient du mot visual. I
1 Commandes de base
• Substitution :
1) Introduction
voir /pat/internet/techinfo
• structure de l'ordinateur (CPU, mémoire, interfaces, bus)
• les caractéristiques du CPU, les différentes vitesses dans un PC, les
caches.
• les périphériques
• le langage machine (petit exemple), les 5 générations de langages
2) La gestion de l'ordinateur
• BIOS, OS, DOS
• les disques et leur gestion (FAT, répertoires, adressage absolu et relatif)
• les Files Systems (FAT12, 16, 32, Unix, NFS...)
• sous Unix : arborescence classique, montage/démontage, mkdir, rmdir,
cd, ls, rm
• la compilation, l'édition de liens. En pratique (kwrite prog.f & / gcc prog.f
-o prog / prog). Si vous cherchez un compilateur, je vous conseille le
meilleur : GNU G77 (www.gnu.org). Il est disponible dans toutes les
distributions Linux, pour Windows j'en ai fait une copie ici.
3) Bases du fortran 77
• le format de la ligne ( C2345+789.....72CCCC ) : en colonne 1, un C (ou *)
indique que la ligne est un commentaire (ne sera pas prise en compte
par le compilateur). Les colonnes 1 à 5 peuvent contenir un label
(numéro de ligne par exemple). S'il y a un caractère en colonne 6 (un +
par exemple), cette ligne est la continuation de la suivante. Les colonnes
7 à 72 contiennent les instructions. A partir de la colonne 73, plus rien
n'est lu.
Les compilateurs actuels (dont g77) acceptent un commentaire en fin de
ligne : il commence par ! (et va jusquà la fin de la ligne). C'est même
conseillé en premier caractère d'une ligne de commentaire (au lieu de C)
pour la compatibilité avec F90 et plus.
• les identificateurs (noms des objets) : utilisez les caractères (A-Z,0-9), ni
espace ni accent ni - (réservé à la soustraction). Le premier doit être une
lettre, pas un chiffre. Le compilateur transforme toutes les minuscules en
majuscules (sauf si entre apostrophes ' ). 6 caractères maxi (31 maxi en
général, mais il vaut mieux qu'il n'y en ait pas deux avec les mêmes 6
premiers). Les identificateurs sont séparées par un ou plusieurs espaces,
que l'on peut omettre si le caractère suivant n'est pas (A-Z,0-9).
• les types de variables de base : integer (en général jusqu'à +ou- 109),
real (en général avec 7 chiffres significatifs), double precision (en général
avec 15 chiffres significatifs). Remarque : on peut (quand on sait
exactement ce qu'on fait) imposer le nombre d'octets des variables :
integer *2 et *4, real *4 et *8). Il existe aussi les character, logical et
complex (voir plus loin)
• les opérateurs arithmétiques, par priorité décroissante : (1) - unaire, (2)
** puissance, (3) * et /, (4) + et -. En cas de calcul entre deux entiers, le
résultat est entier. Dès qu'il y a au moins un réel, le résultat est réel. Dès
qu'il y a un double précision, le résultat est double précision.
• les constantes : 1 (entier ), 100.0 ou 1E2 (réel), 1D0 (double précision)
• petit programme (premprog.f)
program calcul entête
implicit none pour plus de sécurité, nous refusons
integer nb les déclarations implicites
real pu,pt
print *,'combien de pièces ?' écrire à l'écran
read *,nb lire au clavier
print *,'prix unitaire ?'
read *,pu
pt=pu*nb affectation: le calcul est effectué puis
print *,'cela fera ',pt,' en tout' le résultat est stocké dans pt
stop
end program calcul clôture
(voir seconddeg.f)
Remarque sur la division : il faut TOUJOURS vérifier que le dénominateur est
non nul (le célèbre domaine de définition cher à tous vos profs de maths depuis
le collège).
Le label est un entier dans ]0,99999] (doit rentrer dans les 5 premiers
caractères de la ligne). L'incrément est optionnel (1 par défaut). La boucle sera
effectuée avec l'indice (que vous aurez déclaré avant en integer) allant de
'val.initiale' à 'val.finale' compris, par pas de 'incrément' . Il ne faut JAMAIS
tenter de modifier l'indice, val.initiale, val.finale ou incrément en cours de
boucle. En sortie de boucle, l'indice ne vaut pas nécessairement la valeur
finale, ça dépend des compilateurs.
exemple :
do 10 i=1,10
print *,i,'è coucou'
10 continue
qui donne
1è coucou
2è coucou
3è coucou
4è coucou
5è coucou
6è coucou
7è coucou
8è coucou
9è coucou
10è coucou
En fait, le continue ne peut fermer que la dernière boucle ouverte (mais on
peut imbriquer des boucles). Le label n'apporte rien (que peut-être la clarté).
Mais ces boucles ne peuvent se faire que si leur nombre est fixé d'avance.
C'est pourquoi la plupart des compilateurs acceptent d'autres boucles, mais
elles ne sont pas standardisées dans fortran 77. Celle qui me semble la plus
fréquente (et acceptée par les normes suivantes) est :
DO while (condition logique)
une ou plusieurs instructions
ENDDO
exemple :
DO while(x.gt.1)
x=x/2
ENDDO
do
instructions
while(condition)
do
instructions
until (condition)
Une écriture fréquente est le IF (condition) GOTO label, servant par exemple
pour créer des boucles "tant que" qui soient compatibles avec tout compilateur.
exemple :
SUBROUTINE echange (x,y)
implicit none
real x,y,tampon
tampon=x
x=y
y=tampon
RETURN
END SUBROUTINE echange
autre part :
real a,b
a=10
b=15
CALL echange (a,b)
Les arguments réels doivent être exactement du même type que les arguments
formels, aussi nombreux et dans le même ordre (même pas de transformation
automatique d'entier en réel). Les arguments sont dits "passés par adresse", ce
qui signifie que toute modification à l'argument formel est répercutée à
l'argument réel (j'en parle parce que dans d'autres langages c'est différent).
Une fonction, quand à elle, a un résultat. Elle est appelée dans une expression
type FUNCTION nom (liste d'arguments formels)
déclarations locales (y compris arguments formels)
instructions (dont RETURN pour quitter la fonction, précédé d'une
affectation au nom de la fonction)
END FUNCTION nom
exemple:
real function puiss(x,n)
implicit none
real x,p
integer i,n
p=x;
do i=2,n
p=p*x
enddo
puiss=p
return
end function puiss
appel :
real z,puiss
z=2.3
print *, 'calcul: ', puiss(z,10)+1
Remarque : ici z reste à 2.3, car dans la fonction x est inchangé. Si l'on avait
modifié x dans la fonction, on aurait obtenu ce que l'on appelle un "effet de
bord".
Exemple de sous-programme à effet de bord :
real function factorielle(n)
integer res,n
res=1
do while (n.GT.1)
res=res*n
n=n-1
enddo
factorielle=res
return
end function factorielle
donneront ce résultat
120 est la factorielle de 1
6) Les tableaux
On peut regrouper sous un seul nom plusieurs variables simples, c'est un
tableau unidimensionnel ou vecteur. On les déclare ainsi :
type nom (indice début: indice fin)
La plupart du temps, on omet l'indice début (qui sera 1), l'indice fin sera alors
aussi le nombre de composantes. Il existe dans ce cas une seconde méthode
pour déclarer le tableau :
type nom
dimension nom(nombre)
exemple :
real vecteur(3)
ou
real vecteur
dimension vecteur(3)
exemple
x=(vecteur(i)-vecteur(1))/vecteur(i+1)
Dans la déclaration, la dimension du tableau n'a besoin d'être donnée que dans
l'entité qui réserve la place nécessaire en mémoire, pas pour ceux qui
reçoivent le tableau en argument, qui même si on leur donne la dimension ne
s'en servent pas. C'est pourquoi il vaut mieux indiquer * (certains
programmeurs dimensionnent à 1 les tableaux reçus en arguments, mais c'est
peu clair). Une autre solution est de la passer en argument (ou même une
dimension inférieure à la dimension réelle, mais pas plus grande), dans la
fonction ci-dessus on déclarerait real x(nb).
Vous pouvez voir ici un programme de base sur les tableaux (tab-sp.f)
Pour représenter une matrice, on utilise un tableau bidimensionnel. La
déclaration est :
type nom (deb lig:fin lig , deb col:fin col)
l'appel est
nom(indice ligne, indice colonne)
subroutine affmat(mat,diml,dimc)
implicit none
integer diml,dimc
real mat(diml,dimc)
integer il,ic
do il=1,diml
print *,('M(',il,ic,')=',m(il,ic),ic=1,dimc)
enddo
end
Il est également possible d'initialiser des variables. C'est à dire fixer une valeur
initiale à une variable, mais cette valeur pourra changer au cours du
programme. On utilise pour cela la déclaration DATA :
DATA liste de variables / liste de valeurs initiales /
exemple :
real x,y
data x,y / 0.0 , 0.5 /
double
integer real
précision
double
integer integer real
précision
double
real real real
précision
La conversion n'est faite que lorsque c'est nécessaire. Dans la plupart des cas,
c'est la meilleure solution car la plus rapide. Il n'y a que dans le cas de la
division que le résultat est différent suivant les cas. En effet, la division de deux
entiers donne un entier (et un reste, mais il est ignoré). Par exemple, si x et
y=2 sont réels, i=5 et j=3 sont des entiers, alors x=y+i/j met 3 dans x : la
division est prioritaire à l'addition, donc on l'effectue en premier. Les deux
opérandes i et j sont de même type donc 5/3 donne 1 (reste 2); y et 1 sont de
type différent donc 1 est converti en 1.0, et additionné à y pour donner 3.0 qui
est stocké dans x.
De même, l'affectation (variable=calcul) calcule d'abord l'expression à droite
du signe =, ce n'est qu'après qu'il regarde le type de la variable devant
recevoir le résultat pour faire, s'il le faut, une conversion. Vous pouvez donc
écrire x=i mais pas i=x.
exemple :
double precision x,y,z
x=5/3
y=5.0/3.0
z=5D0/3D0
print 10,x,y,z
10 format (f18.15)
affichera :
1.000000000000000
1.666666626930237
1.666666666666667
argument double
integer real
résultat précision
integer
ifix (ou int) idint
(partie entière)
integer
(entier le plus nint idnint
proche)
double
dfloat dble
précision
Ici aussi, faites attention aux divisions : float(5/3) ne vaut pas float(5)/float(3)
double
integer real
précision
Les variables des différents common peuvent être initialisées (si nécessaire)
dans une entité nommée bloc data qui ne peut comporter que des common,
des déclarations et des data :
block data
common/temp/nb,t
integer nb
real t(100)
data nb /0/
end block data
Le fichier désigné est inclus à cet endroit. Attention, cette possibilité n'est pas
disponible partout, mais sous g77 elle l'est (comme d'ailleurs toules les
directives # du C).
exemple :
open(10,FILE='resultats.txt')
---- etc ----
close(10)
Les options sont identiques à l'open, plus END qui donne le label où doit sauter
le programme quand on est arrivé à la fin du fichier (pratique quand on n'en
connaît pas la longueur).
En cas d'écriture à l'écran, l'unité est 6, mais on peut l'appeler *. On peut
même utiliser
print format, liste de variables
Pour la lecture au clavier, l'unité est 5, mais on peut l'appeler *. On peut
également utiliser :
read format, liste de variables
Chaque read ou write correspond à une ligne. Si l'on donne une liste de
plusieurs variables dans un read, il faudra absolument entrer toutes les valeurs
(entre espaces ou virgules) avant la touche Entrée. Mais certains compilateurs
(G77 par exemple) considèrent qu'un caractère '$' en fin de format demande
de ne pas retourner à la ligne.
remarque : on peut également écrire ou lire dans une variable chaîne de
caractères, il suffit de remplacer le numéro d'unité par le nom de la chaîne. De
même, le format peut être une chaîne.
character*40 fmt
integer i,nbchif
data i /123/ , nbchif /4/
write(fmt,10) nbchif
10 format(' ''*'',I',I1,',''*''')
write (*,*) 'pour vérification FMT vaut:',fmt
write (*,fmt) i
ceci affichera :
pour vérification FMT vaut:( '*',I4,'*')
* 123*