【问题标题】:Compiling some else's C program that uses math.h编译使用 math.h 的其他 C 程序
【发布时间】:2014-03-03 07:29:42
【问题描述】:

您好,我有以下名为 zeroin 的函数,我想编译并链接到 Cpp 文件,但我无法通过编译 c 文件的第一步。该函数名为 zeroin.c 我从here 获得。我已将文件放在它自己的目录中,cd 到它,因为它使用 math.h,所以我使用带有 -lm 标志的 gcc 来确保链接库。

gcc -Wall -O zeroin.c -o zeroin -lm

但是我收到以下错误:

zeroin.C:50:15: error: 'ax' was not declared in this scope
zeroin.C:50:18: error: 'bx' was not declared in this scope
zeroin.C:50:21: error: 'f' was not declared in this scope
zeroin.C:50:23: error: 'tol' was not declared in this scope
zeroin.C:50:26: error: expression list treated as compound expression in initialiser [-fpermissive]
zeroin.C:51:1: error: expected ',' or ';' before 'double'
zeroin.C:55:1: error: expected unqualified-id before '{' token

我在下面包含了 C 代码函数的代码 - 我对 C 不是很了解,只是想编译它,以便用它来查找我拥有的 C++ 文件中的函数的根。我该如何解决这些错误?

谢谢, 本。

#include "math.h"

double zeroin(ax,bx,f,tol)      /* An estimate to the root  */
double ax;              /* Left border | of the range   */
double bx;                  /* Right border| the root is seeked*/
double (*f)(double x);          /* Function under investigation */
double tol;             /* Acceptable tolerance     */
{
  double a,b,c;             /* Abscissae, descr. see above  */
  double fa;                /* f(a)             */
  double fb;                /* f(b)             */
  double fc;                /* f(c)             */

  a = ax;  b = bx;  fa = (*f)(a);  fb = (*f)(b);
  c = a;   fc = fa;

  for(;;)       /* Main iteration loop  */
  {
    double prev_step = b-a;     /* Distance from the last but one*/
                    /* to the last approximation    */
    double tol_act;         /* Actual tolerance     */
    double p;               /* Interpolation step is calcu- */
    double q;               /* lated in the form p/q; divi- */
                    /* sion operations is delayed   */
                    /* until the last moment    */
    double new_step;            /* Step at this iteration       */

    if( fabs(fc) < fabs(fb) )
    {                               /* Swap data for b to be the    */
    a = b;  b = c;  c = a;          /* best approximation       */
    fa=fb;  fb=fc;  fc=fa;
    }
    tol_act = 2*EPSILON*fabs(b) + tol/2;
    new_step = (c-b)/2;

    if( fabs(new_step) <= tol_act || fb == (double)0 )
      return b;             /* Acceptable approx. is found  */

                /* Decide if the interpolation can be tried */
    if( fabs(prev_step) >= tol_act  /* If prev_step was large enough*/
    && fabs(fa) > fabs(fb) )    /* and was in true direction,   */
    {                   /* Interpolatiom may be tried   */
    register double t1,cb,t2;
    cb = c-b;
    if( a==c )          /* If we have only two distinct */
    {               /* points linear interpolation  */
      t1 = fb/fa;           /* can only be applied      */
      p = cb*t1;
      q = 1.0 - t1;
    }
    else                /* Quadric inverse interpolation*/
    {
      q = fa/fc;  t1 = fb/fc;  t2 = fb/fa;
      p = t2 * ( cb*q*(q-t1) - (b-a)*(t1-1.0) );
      q = (q-1.0) * (t1-1.0) * (t2-1.0);
    }
    if( p>(double)0 )       /* p was calculated with the op-*/
      q = -q;           /* posite sign; make p positive */
    else                /* and assign possible minus to */
      p = -p;           /* q                */

    if( p < (0.75*cb*q-fabs(tol_act*q)/2)   /* If b+p/q falls in [b,c]*/
        && p < fabs(prev_step*q/2) )    /* and isn't too large  */
      new_step = p/q;           /* it is accepted   */
                    /* If p/q is too large then the */
                    /* bissection procedure can     */
                    /* reduce [b,c] range to more   */
                    /* extent           */
    }

    if( fabs(new_step) < tol_act )  /* Adjust the step to be not less*/
      if( new_step > (double)0 )    /* than tolerance       */
    new_step = tol_act;
      else
    new_step = -tol_act;

    a = b;  fa = fb;            /* Save the previous approx.    */
    b += new_step;  fb = (*f)(b);   /* Do step to a new approxim.   */
    if( (fb > 0 && fc > 0) || (fb < 0 && fc < 0) )
    {                           /* Adjust c for it to have a sign*/
      c = a;  fc = fa;                  /* opposite to that of b    */
    }
  }

}

--编辑--

谢谢大家的建议,我把格式改成ANSI格式,把EPSILON改成DBL_EPSILON,还把#include"math.h"改成#include——更新后的函数(包含在下面)。但是,如果我这次尝试编译:

$gcc -Wall zeroin.c -o zeroin -lm 
zeroin.c: In function 'zeroin':
zeroin.c:78:17: error: 'DBL_EPSILON' undeclared (first use in this function)
zeroin.c:78:17: note: each undeclared identifier is reported only once for each function it appears in
zeroin.c:116:7: warning: suggest explicit braces to avoid ambiguous 'else' [-Wparentheses]

如果 DBL_EPSILON 说它没有定义,我是否可能需要另一个库?

谢谢, 本。

#include <math.h>

double zeroin(double ax, double bx, double(*f)(double x), double tol)       /* An estimate to the root */
{
  double a,b,c;             /* Abscissae, descr. see above  */
  double fa;                /* f(a)             */
  double fb;                /* f(b)             */
  double fc;                /* f(c)             */

  a = ax;  b = bx;  fa = (*f)(a);  fb = (*f)(b);
  c = a;   fc = fa;

  for(;;)       /* Main iteration loop  */
  {
    double prev_step = b-a;     /* Distance from the last but one*/
                    /* to the last approximation    */
    double tol_act;         /* Actual tolerance     */
    double p;               /* Interpolation step is calcu- */
    double q;               /* lated in the form p/q; divi- */
                    /* sion operations is delayed   */
                    /* until the last moment    */
    double new_step;            /* Step at this iteration       */

    if( fabs(fc) < fabs(fb) )
    {                               /* Swap data for b to be the    */
        a = b;  b = c;  c = a;          /* best approximation       */
        fa=fb;  fb=fc;  fc=fa;
    }
    tol_act = 2*DBL_EPSILON*fabs(b) + tol/2;
    new_step = (c-b)/2;

    if( fabs(new_step) <= tol_act || fb == (double)0 )
    {
        return b;               /* Acceptable approx. is found  */
    }

                /* Decide if the interpolation can be tried */
    if( fabs(prev_step) >= tol_act  /* If prev_step was large enough*/
    && fabs(fa) > fabs(fb) )    /* and was in true direction,   */
    {                   /* Interpolatiom may be tried   */
    register double t1,cb,t2;
    cb = c-b;
    if( a==c )          /* If we have only two distinct */
    {               /* points linear interpolation  */
      t1 = fb/fa;           /* can only be applied      */
      p = cb*t1;
      q = 1.0 - t1;
    }
    else                /* Quadric inverse interpolation*/
    {
      q = fa/fc;  t1 = fb/fc;  t2 = fb/fa;
      p = t2 * ( cb*q*(q-t1) - (b-a)*(t1-1.0) );
      q = (q-1.0) * (t1-1.0) * (t2-1.0);
    }
    if( p>(double)0 )       /* p was calculated with the op-*/
      q = -q;           /* posite sign; make p positive */
    else                /* and assign possible minus to */
      p = -p;           /* q                */

    if( p < (0.75*cb*q-fabs(tol_act*q)/2)   /* If b+p/q falls in [b,c]*/
        && p < fabs(prev_step*q/2) )    /* and isn't too large  */
      new_step = p/q;           /* it is accepted   */
                    /* If p/q is too large then the */
                    /* bissection procedure can     */
                    /* reduce [b,c] range to more   */
                    /* extent           */
    }

    if( fabs(new_step) < tol_act )  /* Adjust the step to be not less*/
      if( new_step > (double)0 )    /* than tolerance       */
    new_step = tol_act;
      else
    new_step = -tol_act;

    a = b;  fa = fb;            /* Save the previous approx.    */
    b += new_step;  fb = (*f)(b);   /* Do step to a new approxim.   */
    if( (fb > 0 && fc > 0) || (fb < 0 && fc < 0) )
    {                           /* Adjust c for it to have a sign*/
      c = a;  fc = fa;                  /* opposite to that of b    */
    }
  }

}

【问题讨论】:

  • 是什么让您认为您的问题与math.h 有关?
  • 为了正确起见,您应该#include &lt;math.h&gt;(库标题)而不是"math.h"(用户定义的标题),但这不太可能是问题的原因。

标签: c compilation compiler-errors


【解决方案1】:

这段代码使用了古老的pre-standard风格的函数签名,参数类型在参数列表之后。

改变

double zeroin(ax,bx,f,tol)      /* An estimate to the root  */
double ax;              /* Left border | of the range   */
double bx;                  /* Right border| the root is seeked*/
double (*f)(double x);          /* Function under investigation */
double tol;             /* Acceptable tolerance     */
{

到:

double zeroin(double ax, double bx, double (*f)(double), double tol)
{

肯定有办法让gcc 接受旧样式,但除非您担心上游更改的合并冲突,否则您最好更新它:-)

【讨论】:

    【解决方案2】:

    文件名似乎有一个大写的扩展名.C,这使 GCC 认为它是 C++ 而不是 C。代码是 C 的古老方言(称为“K&R 风格”),不兼容使用 C++。

    将文件重命名为zeroin.c,或在命令行中使用-x c指定语言。

    或者,如果您需要使用不理解 K&R 语法的编译器,您可以更改函数头以使用现代语法:

    double zeroin(double ax, double bx, double(*f)(double x), double tol)
    {
        // code here
    }
    

    剩下的问题是EPSILON的使用;在现代 C 库中,称为 DBL_EPSILON

    【讨论】:

    • 谢谢,我已经更改了文件扩展名,现在我将完成其他语法更改,看看效果如何。
    【解决方案3】:

    我认为这是非常古老的 C 代码。以这种方式声明zeroin 函数的语法

    double zeroin(ax,bx,f,tol)      /* An estimate to the root  */
    double ax;              /* Left border | of the range   */
    double bx;                  /* Right border| the root is seeked*/ 
    double (*f)(double x);          /* Function under investigation */
    double tol;             /* Acceptable tolerance     */
    

    已经很老了,现在已经被弃用了,所以你的编译器不理解它。改成这样:

    double zeroin(double ax, double bx, double (*f)(double x), double tol)
    

    【讨论】:

      【解决方案4】:

      你正在使用 K & R 风格的函数声明

      尝试使用 ANSI 标准样式:

      double zeroin(double ax,double bx, double (*f)(double), double tol);
      

      【讨论】:

        【解决方案5】:

        如果 DBL_EPSILON 说它没有定义,我是否可能需要另一个库?

        也许

        #include <float.h>
        

        需要

        【讨论】:

          猜你喜欢
          • 2014-11-18
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-04-28
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多