所以我要开始我的项目。现在,我正在尝试制作头文件并将其包含在代码中。但是我不确定我是否做对了。
下面是项目:我只包括我已经完成的部分,因为我不想完成一个项目。我想了解。
目标:创建一个C脚本,该脚本将基于系数(a1和a2)和以下项找到二阶线性时不变系统D 2 y + a1Dy + a2 = 0的零输入响应初始条件(y(0)和y'(0))。 (D = d / dt)
要求:
应该提示用户输入线性系统的系数和两个初始条件:D 2 y + a1Dy + a2 =0。
找到二阶非平凡解的根。 D 2 y + a1Dy + a2 = 0 =>λ 2 +a1λ+ a2 = 0
为此步骤创建头文件。
我创建的头文件roots.h
:
#ifndef roots_h
#define roots_h
#include <stdio.h>
// Function Declaration
float posroot(float, float);
float negroot(float, float);
#endif /* roots_h */
roots.c:
#include <math.h>
int posroot(float a1, float a2){
float root1;
root1=(((-1)*(a1)) + sqrt((pow(a1,2)) - (4*a1*a2))) / (2);
return root1;
}
#include <math.h>
int negroot(float a1, float a2){
float root2;
root2= (((-1)*(a1)) - sqrt( (pow(a1,2)) - (4*a1*a2))) / (2);
return root2;
}
main.c:
#include <stdio.h>
#include "roots.h"//header file
int main(){
//Variables
float a1, a2, y0, dy0,root1, root2;
//User asked to type in coeffecients
printf("Enter a1 a2 y(0) and y'(0) seperated by a space: ");
scanf("%f %f %f %f", &a1, &a2, &y0, &dy0);
//Using the functions
root1=posroot(a1, a2);
root2=negroot(a1, a2);
//print the roots
printf("The roots of the second order nontrivial solution: %f and %f", root1,root2);
return 0;
}
在头文件上,它一直说“ Initializer元素不是编译时常量”。
答案 0 :(得分:1)
您似乎对头文件的用途有根本的误解-它们的存在是为了确保不同的源(.c)文件都在全局事物(变量类型等)上达成共识。
您似乎正在尝试将函数代码放入标头中。线
float Header( float l1, float l2);
是全局例程Header的前向声明,该例程带有两个参数,两个参数都是浮点数。
但是随后您似乎正在放入应该在.c文件中的Header()函数的内容。由于在声明行的末尾有分号,因此出现编译错误。该功能应该看起来像
float Header( float l1, float l2)
{
float a1, a2, return_value;
float l1= (((-1)*(a1)) + sqrt( (pow(a1,2)) - (4*a1*a2))) / (2);
float l2= (((-1)*(a1)) - sqrt( (pow(a1,2)) - (4*a1*a2))) / (2);
return some_value;
}
此代码仍然是错误的(正在引用未分配的变量a1和a2,并覆盖传入的变量l1和l2。而且返回值从未分配过-大概是要对l1和l2和返回结果。
如果您纠正了这些错误并使Header()函数正常工作,如果您将其从.h文件中#include到.c文件中,则它实际上会进行编译,但这是一个非常糟糕的主意。这意味着,如果两个.c文件都被#include了,那么最终将导致链接错误,因为将定义两个Header()实例。在static inline
函数的情况下。
对您的新代码的评论:
您的roots.h文件看起来不错。
roots.c文件应仅#include <math.h>
一次。多次执行此操作是安全的,因为它周围有#ifndef指令,但是没有理由这样做。您还应该在其中#include“ roots.h”,以确保以其他文件期望的方式声明函数。在您提供的代码中,您错误地认为posroot()和negroot()被定义为返回整数,但是roots.h文件表示它们返回浮点数。使用#include的“ roots.h”,可以保证得到编译错误(这是您想要的)。没有它,您将需要调试代码以找出错误的原因。
main.c文件看起来不错,尽管我不明白为什么您在不使用它们时要求用户输入y0和dy0。
答案 1 :(得分:1)
在函数外部声明变量时,其初始化程序表达式必须是可以在编译时求值的表达式。这不包括任何调用函数的初始化程序。
您似乎希望变量l1
和l2
在函数内 。在main()
中的代码上下文中,关于头文件roots.h的意义不大。
虽然您需要功能 definition ,但通常不应将此类定义放在头文件中(除非已将其声明为inline
或static
,但这是不常见的)在非平凡的应用程序中可能会导致“代码膨胀”,因此即使对于平凡的代码,这也不是您要养成的习惯。
头文件通常是 declarative ;也就是说,它们声明在其他地方定义的符号。然后,您可以使用单独的编译单元和各个翻译单元的链接。
在这种情况下,您可能会:
roots.h
#ifndef roots_h
#define roots_h
// Find the roots of the second order nontrivial solution
void roots( float a1, float a2, float* l1, float* l2 ) ;
#endif /* roots_h */
roots.c
#include <math.h>
#include "roots.h"
void roots( float a1, float a2, float* l1, float* l2 )
{
float r = sqrt( a1*a1 - 4*a1*a2) ;
*l1 = (-a1 + r) / 2 ;
*l2 = (-a1 - r) / 2 ;
}
main.c
#include <stdio.h>
#include "roots.h" //header file
int main()
{
printf("Enter a1 and a2 separated by a space: ");
float a1, a2;
scanf("%f %f", &a1, &a2);
float l1, l2;
roots( a1, a2, &l1, &l2) ;
printf( "l1 = %f, l2 = %f\n", l1, l2 ) ;
return 0;
}
您必须分别编译roots.c和main.c,然后链接生成的目标文件。通常,您将通过makefile或IDE项目管理来管理单独的编译和链接-否则,即使只有很少的翻译单元,它也会变得非常繁琐且容易出错。
对于琐碎的代码(我感谢这是一个较大的项目的一部分),您可以简单地避免这样做,并将代码放在单个文件中:
#include <stdio.h>
#include <math.h>
void roots( float a1, float a2, float* l1, float* l2 )
{
float r = sqrt( a1*a1 - 4*a1*a2) ;
*l1 = (-a1 + r) / 2 ;
*l2 = (-a1 - r) / 2 ;
}
int main()
{
printf("Enter a1 and a2 separated by a space: ");
float a1, a2;
scanf("%f %f", &a1, &a2);
float l1, l2;
roots( a1, a2, &l1, &l2) ;
printf( "l1 = %f, l2 = %f\n", l1, l2 ) ;
return 0;
}