2017-02-02 4 views
-1

Я получаю следующую ошибку при компиляции кода на C , Я использую Numerical Recipes 2nd ed. функций rk4() для решения дифференциального уравнения первого порядка.Ошибка при решении обычного дифференциального уравнения численно в C - ошибка: ожидается '=', ',', ';', 'asm' или '__attribute__' перед '{' токеном

Я не эксперт в этой области. Любая помощь будет высоко оценена.

Ошибка:

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

код:

#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 (* производные) (float x, float y, float dydx) {...}' -> 'void производные (float x, float y, float dydx) {...}' Или удалить это. – BLUEPIXY

+1

Вы хотите, по крайней мере, прочитать главу 1.2 этой книги, если не потратить время на использование C-праймера. – alk

+0

при компиляции всегда включайте все предупреждения, затем фиксируйте эти предупреждения. Выложенный код заставляет компилятор выводить около 3 десятков сообщений о проблемах. (для 'gcc', при минимальном использовании:' -Wall -Wextra -pedantic' Я также использую: '-Wconversion -std = gnu99) – user3629249

ответ

1

Вы по всей видимости, с помощью указателей на функции без причины и запутанных прототипов и объявлений с вызовами и определениями.

В верхней части, это изменение:

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[]); 

В main, это:

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 

В определении 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[]) 

Для звонков derivs в rk4,

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

В определении derivs,

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

, а затем исправить вычисление rhs.

Если вы нахожусь в письменной форме sometype (*name в будущем, не намереваясь использовать указатели функций, остановитесь. =)

+2

, если 'void производные (float, float [], float []) , 'prototype,' void производные (float x, float y, float dydx) '->' void производные (float x, float y [], float dydx []) ', но могут не совпадать (с' rhs = 1- х + у 4 *; '). – BLUEPIXY

+0

Ваше исправление в main() для вызова 'rk4()' неверно, поскольку оно все еще содержит типы для каждого из параметров, предлагайте: 'rk4 (y, dydx, n, x, h, yout);' – user3629249

+0

@ user3629249: Это последний бит цитаты или предложения? Потому что это то, что я написал. – Ryan

0

После исправления компиляционной версии я запустил diff, чтобы сообщить об изменениях систематическим образом. Эти изменения с их причинами являются:

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

Чтобы избежать путаницы, я буду использовать другое имя для параметра и заданной пользователем функции, которая будет заполнить этот параметр.

Определенная пользователем производная функция - это просто обычная функция (процедура, подпрограмма, метод), объявление указателя функции ограничено местами, где фактически переменная объявлена ​​как указатель на функцию.

14a15 
> float yout[1]; 

Добавить недостающую переменную. Это поможет программе скомпилировать, но не работать, поскольку вы смешиваете два разных диапазона индексов. Стандартным диапазоном float arr[N] является 0..N-1. Вспомогательная функция vector «Численные рецепты» использует арифметику указателя, так что диапазон индексов для действительной выделенной части float *arr=vector(L,H) равен L..H. В вашем нынешнем коде вы смешиваете диапазоны 0..0 и 1..1 и, таким образом, получаете доступ к памяти за пределами выделенного диапазона. Переключите все в векторный и индексный диапазон 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); 

Для вызова функции выглядит иначе, чем для объявления этой функции. В вызове вы просто используете имена переменных для параметров.

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); 

Сначала вы запустите цикл для вычисления следующего вектора состояния, то вы называете производной вычисление раз.

Идея передать указатель функции в качестве параметра заключается в том, что вы затем используете его, как функцию. Не нужно добавлять разыменование и т. Д., Механизм C построен таким образом.

Оба пункта также применяются к двум другим производным вычислениям. Кстати, вам не хватает вычисления производной в dydx. Идея может заключаться в том, что это значение также используется вне подпрограммы для других целей, поэтому его передача позволяет избежать двойных вычислений.

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

Внедрение пользовательской производной функции с изменением имени.

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

Передаваемые аргументы для y и dydx векторы, они должны рассматриваться в качестве векторов с соответствующими де ссылками или элементом адресацией даже в скалярном случае.

Вам необходимо реализовать намерение объявления функции. Результат вычисления производной должен быть сохранен в dydx.

Смежные вопросы