2017-02-02 5 views
-1

Je reçois erreur suivante lorsque je compile mon code C . J'utilise Numerical Recipes 2nd ed. fonctions rk4() pour résoudre une équation différentielle de premier ordre.erreur lors de la résolution numériquement équation différentielle ordinaire dans C - erreur: attendu '=', ',', ';', 'asm' ou '__attribute__' avant '{' token

Je ne suis pas expert dans ce domaine. Toute aide sera grandement appréciée.

erreur est:

first_order_DE_RK4_example1.c:75: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘{’ token 
Code

est:

#include "nrutil.h" 
#include <stdio.h> 
#include <math.h> 

void rk4(float y[], float dydx[], int n, float x, float h, float yout[], 
    void (*derivs)(float, float [], float [])); 

void (*derivs)(float, float[], float[]); 


int main() 
{ 
    int n; float h; float x; 
    float y[1]; 
    float dydx[1]; 

    n=1; 
    h=0.2; 
    x=0; 
    y[0] = 1; 
    dydx[0] = 5.0; 

void rk4(float y[], float dydx[], int n, float x, float h, float yout[], 
    void (*derivs)(float, float [], float [])); 

    return 0; 
} 


void rk4(float y[], float dydx[], int n, float x, float h, float yout[], 
    void (*derivs)(float, float [], float [])) 
{ 
    int i; 
    float xh,hh,h6,*dym,*dyt,*yt; 

    dym=vector(1,n); 
    dyt=vector(1,n); 
    yt=vector(1,n); 
    hh=h*0.5; 
    h6=h/6.0; 
    xh=x+hh; 

    for (i=1;i<=n;i++) 
      { 
      yt[i]=y[i]+hh*dydx[i]; 
     (*derivs)(xh,yt,dyt); 
      } 

    for (i=1;i<=n;i++) 
      { yt[i]=y[i]+hh*dyt[i]; 
     (*derivs)(xh,yt,dym); 
      } 

    for (i=1;i<=n;i++) 
     { 
     yt[i]=y[i]+h*dym[i]; 
     dym[i] += dyt[i]; 
    } 

    (*derivs)(x+h,yt,dyt); 

    for (i=1;i<=n;i++) 
      { 
     yout[i]=y[i]+h6*(dydx[i]+dyt[i]+2.0*dym[i]); 
      } 

    free_vector(yt,1,n); 
    free_vector(dyt,1,n); 
    free_vector(dym,1,n); 
} 


void (*derivs)(float x, float y, float dydx) 
{ 
    float rhs; 
    rhs = 1-x+4*y; 
} 
+5

'void (* dérivés) (float x, flottant y, float dydx) {...}' -> 'void derivés (float x, float y, float dydx) {...}' Ou supprime ça. – BLUEPIXY

+1

Vous voulez au moins lire le chapitre 1.2 de ce livre, si vous ne prenez pas le temps de passer par un primaire C. – alk

+0

lors de la compilation, activez toujours tous les avertissements, puis corrigez ces avertissements. Le code affiché provoque le compilateur à sortir environ trois douzaines de messages sur les problèmes. (pour 'gcc', utilisez au minimum:' -Wall -Wextra -pedantic' J'utilise aussi: '-Wconversion -std = gnu99) – user3629249

Répondre

1

Vous semblez utiliser des pointeurs de fonction sans raison et des prototypes et des déclarations confuses avec des appels et des définitions.

Au sommet, ce changement:

void rk4(float y[], float dydx[], int n, float x, float h, float yout[], 
    void (*derivs)(float, float [], float [])); 

void (*derivs)(float, float[], float[]); 
void rk4(float y[], float dydx[], int n, float x, float h, float yout[]); 

void derivs(float, float[], float[]); 

En main, ceci:

void rk4(float y[], float dydx[], int n, float x, float h, float yout[], 
void (*derivs)(float, float [], float [])); 
rk4(y, dydx, n, x, h, yout); // with some appropriate declared yout 

Dans la définition de rk4,

void rk4(float y[], float dydx[], int n, float x, float h, float yout[], 
    void (*derivs)(float, float [], float [])) 
void rk4(float y[], float dydx[], int n, float x, float h, float yout[]) 

Pour les appels à derivs dans rk4,

(*derivs)(xh,yt,dyt); 
derivs(xh, yt, dyt); 

Dans la définition de derivs,

void (*derivs)(float x, float y, float dydx) 
void derivs(float x, float y[], float dydx[]) 

puis fixer le calcul de rhs.

Si vous vous trouvez en train d'écrire sometype (*name à l'avenir sans avoir l'intention d'utiliser des pointeurs de fonction, arrêtez. =)

+2

si 'void derivs (float, float [], float []) ; 'est prototype,' void derivs (float x, flottant y, float dydx) '->' void derivs (float x, float y [], flottant dydx []) 'mais pourrait ne pas correspondre (' rhs = 1- x + 4 * y; '). – BLUEPIXY

+0

votre correctif suggéré dans main() pour l'appel à 'rk4()' est incorrect car il contient toujours les types pour chacun des paramètres, suggérer: 'rk4 (y, dydx, n, x, h, yout);' – user3629249

+0

@ user3629249: Est-ce le dernier bit un devis ou une suggestion? Parce que c'est ce que j'ai écrit. – Ryan

0

Après correction d'une version de compilation, j'ai exécuté diff pour signaler les changements de manière systématique. Ces changements avec leurs raisons sont les suivantes:

8c8 
< void (*derivs)(float, float[], float[]); 
--- 
> void myprime(float, float[], float[]); 

Pour éviter toute confusion, je vais utiliser un autre nom pour le paramètre et la fonction définie par l'utilisateur qui remplira ce paramètre.

La fonction dérivée définie par l'utilisateur est simplement une fonction ordinaire (procédure, sous-routine, méthode), la déclaration du pointeur de fonction est limitée aux endroits où une variable est déclarée en tant que pointeur de fonction.

14a15 
> float yout[1]; 

Ajoutez la déclaration de variable manquante. Cela aidera le programme à compiler, mais pas à exécuter, car vous mélangez deux plages d'index différentes. La plage standard de float arr[N] est 0..N-1. La fonction d'assistance vector de "Recettes numériques" utilise l'arithmétique de pointeur de sorte que la plage d'index pour la partie allouée valide de float *arr=vector(L,H) est L..H. Dans votre code actuel, vous mélangez les plages 0..0 et 1..1 et accédez ainsi à la mémoire en dehors de la plage allouée. Commuter tout à vecteur et la plage d'index 1..n.

23,24c24 
< void rk4(float y[], float dydx[], int n, float x, float h, float yout[], 
<  void (*derivs)(float, float [], float [])); 
--- 
> rk4(y, dydx, n, x, h, yout, myprime); 

L'appel d'une fonction est différent de la déclaration de cette fonction. Dans l'appel, vous utilisez simplement les noms de variables pour les paramètres.

44,47c44,47 
<   { 
<    yt[i]=y[i]+hh*dydx[i]; 
<   (*derivs)(xh,yt,dyt); 
<   } 
--- 
>  { 
>   yt[i]=y[i]+hh*dydx[i]; 
>  } 
>  derivs(xh,yt,dyt); 

D'abord, vous exécutez la boucle pour calculer le vecteur d'état suivant, vous appelez le calcul dérivé une fois. L'idée de passer le pointeur de fonction en paramètre est de l'utiliser comme s'il s'agissait d'une fonction. Pas besoin d'ajouter de déréférencement etc., le mécanisme C est construit comme ça.

Les deux points s'appliquent également aux deux autres calculs dérivés. Soit dit en passant, il vous manque le calcul de la dérivée dans dydx. L'idée est peut-être que cette valeur est également utilisée en dehors de la routine à d'autres fins, ce qui évite le double calcul.

73c74 
< void (*derivs)(float x, float y, float dydx) 
--- 
> void myprime(float x, float y[], float dydx[]) 

Implémentez la fonction dérivée définie par l'utilisateur avec le changement de nom.

75,76c76 
< float rhs; 
< rhs = 1-x+4*y; 
--- 
> dydx[0] = 1-x+4*y[0]; 

Les arguments passés pour y et dydx sont des vecteurs, ils doivent être traités comme des vecteurs avec de-référence ou d'un élément d'adressage appropriée même dans le cas scalaire.

Vous devez implémenter l'intention derrière la déclaration de fonction. Le résultat du calcul de la dérivée doit être stocké dans dydx.