IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Fortran Discussion :

tableau dont la taille est modifié par une procédure


Sujet :

Fortran

  1. #1
    Membre du Club
    Profil pro
    Étudiant
    Inscrit en
    Mars 2009
    Messages
    112
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2009
    Messages : 112
    Points : 53
    Points
    53
    Par défaut tableau dont la taille est modifié par une procédure
    Bonjour,

    Après avoir passé un moment sur le forum, je poste ma question... Je vous mets ici un exemple simple "correspondant" à mon problème: je dois créer une procédure qui a pour but de trier les éléments d'un tableau, d'en éliminer certains et d'en conserver d'autres. Par exemple, garder les nombres différents de 2 présents dans un tableau et supprimer les autres. Voilà comment je procède:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    integer :: n
    integer, dimension(:), allocatable :: tab, tab0
     
    n=10
    allocate(tab(10))
     
    do i=1, n
     tab(i)=i
    end do
     
    call maroutine(n, tab)
    allocate(tab0(n))
    tab0=tab(1:n)
    deallocate(tab)
     
    ...


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    subroutine maroutine(n, tab)
     
    integer, intent(inout) :: n
    integer, intent(inout) :: tab
     
    integer :: i, j
     
    j=0
    do i=1, n
     if(tab(i) .ne. 2) then
      j=j+1
      tab(j)=tab(i)
     end if
    end do
     
    n=j
     
    end subroutine
    J'aimerais bien pouvoir me passer d'allouer tab0 et de recopier tab dans tab0. En fait, ce qui serait bien, serait de pouvoir passer tab dans maroutine, et que maroutine modifie elle-même tab en tab0 (notammant qu'elle change la taille de tab).

    Est-ce qu'il y a un autre moyen de faire ça? Peut-être avec des pointeurs (je ne suis pas calé sur ce sujet... honte à moi)?

    Merci d'avance.

  2. #2
    Modérateur

    Profil pro
    Inscrit en
    Août 2006
    Messages
    974
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Août 2006
    Messages : 974
    Points : 1 346
    Points
    1 346
    Par défaut
    Je n'ai pas le temps de faire la recherche, mais voici quelques pistes à explorer :
    • Ça pourrait fonctionner si le paramètre de la routine est allocatable (sinon pointer) et qu'il est intent(inout). Tu auras donc besoin d'une interface (peut être générée par un module).
    • En Fortran 90 et 95, il y a ambiguïté sur le sens du intent avec un allocatable et un pointer: ça s'applique au contenu de la variable ou au pointeur ?
    • Tu ne peux pas changer la taille du tableau. Tu dois donc allouer une variable temporaire, copier le contenu, deallouer, puis réallouer le paramètre dummy, et finalement copier le contenu. En Fortran 2003, tu peux éliminer certaines étapes avec la fonction movealloc (nom incertain, de mémoire)

  3. #3
    Modérateur

    Profil pro
    Inscrit en
    Août 2006
    Messages
    974
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Août 2006
    Messages : 974
    Points : 1 346
    Points
    1 346
    Par défaut
    Voici un exemple permettant de redimensionner un tableau :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    module MonModule
       implicit none
     
    contains
    subroutine Redim(a,n)
       integer, allocatable, intent(inout) :: a(:)
       integer, intent(in) :: n
     
       integer, allocatable :: b(:)
       integer LenMin
     
       allocate(b(n))
       LenMin = min(n,size(a))
       b(:LenMin) = a(:LenMin)
       if (n > LenMin) b(LenMin:) = a(LenMin)
       deallocate(a)
       allocate(a(n))
       a = b
       deallocate(b)
       end subroutine
     
    end module
     
    program test
       use MonModule
       implicit none
     
       integer, allocatable :: x(:)
       integer i
     
       allocate(x(10))
       do i = 1, 10
          x(i) = i
       enddo
       write(*,*) '[1:10]=',x
       call Redim(x,20)
       write(*,*) '[1:20]:',x
       call Redim(x,5)
       write(*,*) '[1:5]:',x 
       end program

  4. #4
    Membre du Club
    Profil pro
    Étudiant
    Inscrit en
    Mars 2009
    Messages
    112
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2009
    Messages : 112
    Points : 53
    Points
    53
    Par défaut
    Merci beaucoup. Je vais essayer ça. On peut même imaginer intégrer le module dans la sous-routine pour être quitte d'appeler Redim dans le programm de base... non?
    En fait, si j'aimerais ne pas devoir appeler la procédure Redim depuis le programme, c'est pour être quitte de se poser la question (quelques mois après, une fois qu'on a un peu oublié comment telle ou telle fonction procède): est-ce que je dois redimensionner tel tableau après l'appel de telle procédure?... hum...

  5. #5
    Membre du Club
    Profil pro
    Étudiant
    Inscrit en
    Mars 2009
    Messages
    112
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2009
    Messages : 112
    Points : 53
    Points
    53
    Par défaut
    Me revoilà sur mon message. En fait, j'ai remarqué quelque chose qui me semble bizarre: la différence entre un vecteur a une dimension et une "colonne" d'un tableau à deux dimensions. Plus précisément, j'alloue et initialise un tableau par:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
       integer, allocatable :: y(:,:)
       integer i
     
       allocate(y(2,10))
       do i = 1, 10
          y(1,i) = i
          y(2,i) = 10+i
       enddo
    Si maintenant, je passe en argument la première "colonne de y" à la fonction Redim

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    call Redim(y(1,:),20)
    j'obtiens l'erreur:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    Error: Actual argument for 'a' must be ALLOCATABLE at (1)
    Ma question alors est: existe-t-il une solution pour éviter ce problème, plus simple et élégante que:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    allocate(y_copie(10))
    y_copie=y(1,:)
    call Redim(y_copie,20)
    et les allocations/déallocations qui en découlent?
    Merci d'avance pour votre réponse.

  6. #6
    Modérateur

    Profil pro
    Inscrit en
    Août 2006
    Messages
    974
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Août 2006
    Messages : 974
    Points : 1 346
    Points
    1 346
    Par défaut
    Si tu ne passes qu'une colonne d'un tableau allocatable, cette colonne peut difficilement conserver l'attribut allocatable (sinon, tu pourrais allouer des colonnes de longueurs différentes dans un même tableau, ou simplement désallouer certaines colonnes et pas d'autre)...

  7. #7
    Membre du Club
    Profil pro
    Étudiant
    Inscrit en
    Mars 2009
    Messages
    112
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2009
    Messages : 112
    Points : 53
    Points
    53
    Par défaut
    En effet. Merci pour l'explication. Je vais essayer de créer une routine de redimensionnement de tableau pour faire ce que j'aimerais.

Discussions similaires

  1. Réponses: 2
    Dernier message: 20/02/2011, 19h48
  2. Réponses: 2
    Dernier message: 20/10/2010, 13h05
  3. Réponses: 5
    Dernier message: 12/03/2010, 12h03
  4. Réponses: 7
    Dernier message: 27/05/2008, 11h54
  5. Réponses: 2
    Dernier message: 06/08/2007, 16h39

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo