Visualizzazione dei risultati da 1 a 7 su 7
  1. #1

    [C] Chiarimenti sulle strutture in un esempio di codice di integrazione numerica

    Ciao a tutti. Avrei bisogno di alcuni chiarimenti riguardo le strutture nel linguaggio C. Prendendo ad esempio questa parte di codice (è la prima volta che scrivo sul forum, essendo il codice abbastanza lungo ho inserito solo una parte in quanto ciò che mi interessa è in che modo vengono utilizzate in questo caso le strutture)

    codice:
    #include <stdio.h>
    #include <math.h>
    
    struct phaseSpace {
      double x; 
      double v;
    };
         
    /* I PROTOTIPI */
         
    struct phaseSpace *initHarmonicOscillator(double m_x0, double m_v0);
    struct phaseSpace *euler(double m_dt, double m_omega2,  struct phaseSpace *m_pXAndV);
    
    int main(void) {
    
    ...
    
      struct phaseSpace xAndV;
    
    ...
    
    }
    
    /*********************************/
    struct phaseSpace  *initHarmonicOscillator(double x0, 
    					   double v0) {
      static struct phaseSpace xAndV; 
      xAndV.x = x0;
      xAndV.v = v0;
      return &xAndV;
    }
    
    /*********************************/
    struct phaseSpace *euler(double dt, double omega2, 
                             struct phaseSpace *pXAndVOld) {
      static struct phaseSpace xAndVNew;
    
      xAndVNew.v = (*pXAndVOld).v + 
        forceHarmonicOscillator(omega2, (*pXAndVOld).x) * dt;
    
      xAndVNew.x = pXAndVOld->x + pXAndVOld->v * dt;
      return &xAndVNew;
    }
    Oltre al mio libro, ho letto anche la parte sullo struct nella guida sul C in questo sito, ma ancora non sono riuscito a capire chiaramente come vengono utilizzate in questo codice. Prima viene dichiarato lo struct contenente due variabili di tipo double, dopodiché viene dichiarato un puntatore della struttura? Cioè cosa rappresenta

    codice:
    struct phaseSpace *euler(double dt, double omega2,  struct phaseSpace *pXAndVOld)
    viene dichiarata un'istanza che ha come nome un puntatore a una funzione?

    Scusatemi se sto dicendo baggianate ma ci sto sbattendo la testa da ieri e ancora non sono riuscito a capire
    "I don't know anything, but I do know that everything is interesting if you go into it deeply enough."(Richard P. Feynman)

    “Don’t waste time living someone else’s life. Stay hungry. Stay Foolish” (Steve Jobs)

  2. #2
    Ciao e benvenuto nel forum,
    Le funzioni che hai citato non fanno parte della struct.


    struct xxx *funzione( parametri... ){
    .. code ...
    }
    Indica semplicemente una funzione che riceve i parametri e ritorna un puntatore di tipo "struct xxx".
    Il concetto è lo stesso di scrivere:
    int function( int parametroIntero){
    }

  3. #3
    Utente di HTML.it
    Registrato dal
    Sep 2012
    Messaggi
    707

    Re: [C] Chiarimenti sulle strutture in un esempio di codice di integrazione numerica

    Originariamente inviato da xavier310
    viene dichiarata un'istanza che ha come nome un puntatore a una funzione?
    Molto più semplice: è una normalissima funzione di nome "euler" che ritorna come tipo un puntatore a un struttura di tipo "phaseSpace".

  4. #4
    Innanzitutto vi ringrazio delle risposte! Quindi sarebbe la stessa cosa se invece di utilizzare la funzione io inserissi direttamente nella main

    codice:
    int main(void){
    
    ....
    
     static struct phaseSpace xAndVNew;
    
     xAndVNew.v = (*pXAndVOld).v +  forceHarmonicOscillator(omega2, (*pXAndVOld).x) * dt;
    
     xAndVNew.x = pXAndVOld->x + pXAndVOld->v * dt;
    
    ....
    
    }
    Altri due piccoli chiarimenti:

    Se scrivessi:

    struct phaseSpace euler(double m_dt, double m_omega2, struct phaseSpace *m_pXAndV);

    cioè senza l'asterisco non sarebbe sempre "una funzione di nome "euler" che ritorna come tipo un puntatore a un struttura di tipo "phaseSpace". Cioè quando dichiaro una funzione, e voglio che quella funzione ritorni la locazione di un puntatore, devo specificare l'asterisco davanti al nome della funzione?

    ************************************************** **************

    Ultima cosa: il termine "static" in questo caso va davanti a struct perchè dopo l'uscita della funzione si vuole che venga trovata da altri programmi giusto? Quindi, se inserissi la dichiarazione prima della main non ci sarebbe bisogno del termine "static" ?
    "I don't know anything, but I do know that everything is interesting if you go into it deeply enough."(Richard P. Feynman)

    “Don’t waste time living someone else’s life. Stay hungry. Stay Foolish” (Steve Jobs)

  5. #5
    Utente di HTML.it
    Registrato dal
    Sep 2012
    Messaggi
    707
    Mhm, quelle funzioni non è che fossero il massimo... ritornare il puntatore a una variabile statica dichiarata nella funzione presuppone già che non possa essere usata in ambiente multithread.

    Quindi ricopiando il corpo di quella funzione ti sei portato dietro quello "static".

    L'hai scritta tu?

  6. #6
    No è un codice ricavato dal libro. Forse è stato scritto in questo modo perchè si adattava meglio alla spiegazione sulle strutture e sui metodi di integrazione.

    Quindi per variabile statica significa che viene letta da tutte le funzioni giusto? In teoria static lo posso scrivere davanti a qualsiasi variabile e non solo struct esatto?

    Per quanto riguarda la domanda precedente, quando dichiaro una funzione, e voglio che quella funzione ritorni la locazione di un puntatore, devo specificare l'asterisco davanti al nome della funzione?

    Comunque l'intero codice del programma è:

    codice:
    /* Introduciamo le strutture, ripassiamo l'I/O
    /* e le funzioni, impariamo ad evitare gli effetti */
    /* collaterali nell'uso di funzioni */
    
    #include <stdio.h>
    #include <math.h>
    
    #define EXIT_SUCCESS       0
    #define EXIT_FAILURE      -9
    #define EULER              0
    #define EULER_CROMER       1
    
    /* Notate che il punto e virgola alla fine */
    /* delle prossime righe e' cruciale! */
    
    struct phaseSpace {
      double x; 
      double v;
    };
         
    /* I PROTOTIPI */
         
    /* m_ nelle righe sotto ci ricorda che si */
    /* tratta di variabili mute, li' solo per */
    /* memoria (potremmo non metterle nel prototipo, */
    /* ma indicare solo il tipo) */
    /* in questo esempio usiamo p per i puntatori */
         
    struct phaseSpace *initHarmonicOscillator(double m_x0, 
    					  double m_v0);
    struct phaseSpace *euler(double m_dt, double m_omega2, 
    			 struct phaseSpace *m_pXAndV);
    struct phaseSpace *eulerCromer(double m_dt, double m_omega2, 
    			       struct phaseSpace *m_pXAndV);
    
    /* notate che energy() e' generica, */
    /* mentre forceHarmonicOscillator() e' proprio per */
    /* l'oscillatore armonico (da cui il nome) */
    
    double energy(double m_omega2, struct phaseSpace *m_pXAndV);
    double forceHarmonicOscillator(double m_omega2, double m_x);
    double potentialEnergyHarmonicOscillator(double m_omega2, 
    					 double m_x);
    double myReadDouble(char *m_printMessage);
    long   myReadLong(char *m_printMessage);
    
    /*********************************/
    int main(void) {
      double x0, v0, dt, omega2, totalTime, energy0, energy1;
      long   numberOfSteps, algorithm, i;
      struct phaseSpace xAndV;
    
      /* I simboli # sono per far piacere a gnuplot, per */
      /* esempio, o ad aiutarci ad usare un filtro per eliminare */
      /* le righe che non ci serviranno nella grafica */
    
      printf("# Integrazione Oscillatore Armonico\n");
      printf("#v1.1.1, 30 settembre 2005\n");
    
      /* queste myRead sono li' per evitarci un po' di codice... */
    
      totalTime = 
        myReadDouble(
           "Inserire il tempo totale di integrazione");
      algorithm = 
        myReadLong("Inserire 0 per Eulero, 1 per Eulero-Cromer");
      dt = myReadDouble("Inserire dt");
      x0 = myReadDouble("Inserire x0");
      v0 = myReadDouble("Inserire v0");
      omega2 = myReadDouble("Inserire omega2");
    
      /* Il cast lo facciamo noi esplicitamente, per tenere */
      /* le cose sotto controllo!! */
    
      numberOfSteps = (long)(totalTime/dt); 
      printf("# dt = %g tempo totale = %g\n",
    	 dt, totalTime);
      printf("# omega2 = %g numero passi = %d\n",
    	 omega2, numberOfSteps);
    
      /* una funzione senza effetti collaterali. quel */
      /* che cambia lo cambia con = */
    
      xAndV = *initHarmonicOscillator(x0, v0); 
      printf("# Condizioni iniziali x0 = %g v0 = %g\n", 
    	 xAndV.x, xAndV.v);
      energy0 = energy(omega2, &xAndV);
      printf("# L'energia al tempo t = 0 vale %g\n", energy0);
      if (algorithm == EULER) {
        printf("# Usiamo l'algoritmo di Eulero\n");
        for (i = 0; i < numberOfSteps; i++) {
    
          /* un'altra funzione senza effetti collaterali... */
    
          xAndV = *euler(dt, omega2, &xAndV);
          energy1 = energy(omega2, &xAndV);
          printf("%g %g %g %g\n", 
    	     (double)i*dt, xAndV.x, xAndV.v, energy1 - energy0);
        }
      } else if (algorithm == EULER_CROMER) {
        printf("# Usiamo l'algoritmo di Eulero-Cromer\n");
        for (i = 0; i < numberOfSteps; i++) {
    
          /* un'altra funzione senza effetti collaterali... */
    
          xAndV = *eulerCromer(dt, omega2, &xAndV);
          energy1 = energy(omega2, &xAndV);
          printf("%g %g %g %g\n", 
    	     (double)i*dt, xAndV.x, xAndV.v, energy1 - energy0);
        }
      } else {
        printf("# TUONI E FULMINI:");
        printf("L'algoritmo n. %ld non e' implementato. Errore.\n",
    	   algorithm);
        exit(EXIT_FAILURE);
      }
      energy1 = energy(omega2, &xAndV);
      printf("# L'energia al tempo t = %d vale %g\n",
             numberOfSteps, energy1);
      return EXIT_SUCCESS;
    }
    
    /*********************************/
    struct phaseSpace  *initHarmonicOscillator(double x0, 
    					   double v0) {
      static struct phaseSpace xAndV; 
      xAndV.x = x0;
      xAndV.v = v0;
      return &xAndV;
    }
    
    /*********************************/
    struct phaseSpace *euler(double dt, double omega2, 
                             struct phaseSpace *pXAndVOld) {
      static struct phaseSpace xAndVNew;
    
      /* che succede se omettete le prime parentesi */
      /* nella riga sotto ?*/
    
      xAndVNew.v = (*pXAndVOld).v + 
        forceHarmonicOscillator(omega2, (*pXAndVOld).x) * dt;
    
      /* perche' qui usiamo -> e non . ? */
    
      xAndVNew.x = pXAndVOld->x + pXAndVOld->v * dt;
      return &xAndVNew;
    }
    
    /*********************************/
    struct phaseSpace *eulerCromer(double dt, double omega2, 
    			        struct phaseSpace *pXAndVOld) {
    
    /* Qual e' la differenza fra Eulero ed Eulero-Cromer? */
    
      static struct phaseSpace xAndVNew;
      xAndVNew.v = (*pXAndVOld).v + 
        forceHarmonicOscillator(omega2, (*pXAndVOld).x) * dt;
      xAndVNew.x = pXAndVOld->x + xAndVNew.v * dt;
      return &xAndVNew;
    }
    
    /*********************************/
    double energy(double omega2, struct phaseSpace *pXAndV) {
    
    /* Calcoliamo in realta' 2 E / m */
    
      double localEnergy;
      localEnergy = (*pXAndV).v * (*pXAndV).v 
        + potentialEnergyHarmonicOscillator(omega2, (*pXAndV).x);
      return localEnergy;
    }
    
    /*********************************/
    double forceHarmonicOscillator(double omega2, double x) {
      return - omega2 * x;
    }
    
    /*********************************/
    double potentialEnergyHarmonicOscillator(double omega2, 
                                             double x) {
      return omega2 * x * x;
    }
    
    /*********************************/
    long myReadLong(char *printMessage) {
      long inputData;
    
      printf("# %s\n",printMessage); 
      fflush(stdout);
      scanf("%ld",&inputData);
    
      return inputData;
    }
    
    /*********************************/
    double myReadDouble(char *printMessage) {
      double inputData;
    
      printf("# %s\n",printMessage); fflush(stdout);
      scanf("%lg", &inputData);
    
      return inputData;
    }
    "I don't know anything, but I do know that everything is interesting if you go into it deeply enough."(Richard P. Feynman)

    “Don’t waste time living someone else’s life. Stay hungry. Stay Foolish” (Steve Jobs)

  7. #7
    Utente di HTML.it
    Registrato dal
    Sep 2012
    Messaggi
    707
    Quindi per variabile statica significa che viene letta da tutte le funzioni giusto? In teoria static lo posso scrivere davanti a qualsiasi variabile e non solo struct esatto?
    No, riguardo al significato di "static" per le variabili ha questi due utilizzi:
    - per le variabili globali: significa che è visibile solo nel file in cui è dichiarata
    - per le variabili dichiarate all'interno di una funzione: significa che anziché essere allocate sullo stack e quindi deallocate automaticamente all'uscita dalla funzione la loro "vita" dura per tutta la durata del programma.

    Per quanto riguarda la domanda precedente, quando dichiaro una funzione, e voglio che quella funzione ritorni la locazione di un puntatore, devo specificare l'asterisco davanti al nome della funzione?
    Giusto, anche se si parla di "puntatore a un certo tipo", quindi riformulerei la tua frase con:
    "se voglio che quella funzione ritorni un puntatore a intero, devo specificare puntatore a intero davanti al nome della funzione"

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2024 vBulletin Solutions, Inc. All rights reserved.