C 保存多个文件中使用的多个常量值

C 保存多个文件中使用的多个常量值,c,variables,constants,C,Variables,Constants,我正在创建一个具有大量常量值的大型应用程序,这些常量值在应用程序的整个运行过程中使用,但有时在使用、传感器参数等之间会发生变化。在我非常熟悉的Python中,我只需使用一个单独的文件来存储所有变量,使用所有的大写字母来表示一个常量值,如下所示(仅举一个例子): 但是我想知道在C中存储相同类型值的推荐方法。我找不到答案,我确信答案可以在某处找到,但我找不到,可能我使用了错误的搜索关键字 与我在python中所做的“相同”的最佳方法是:对所有变量使用单个文件,然后使用头文件在文件之间共享它们?“建议

我正在创建一个具有大量常量值的大型应用程序,这些常量值在应用程序的整个运行过程中使用,但有时在使用、传感器参数等之间会发生变化。在我非常熟悉的Python中,我只需使用一个单独的文件来存储所有变量,使用所有的大写字母来表示一个常量值,如下所示(仅举一个例子):

但是我想知道在C中存储相同类型值的推荐方法。我找不到答案,我确信答案可以在某处找到,但我找不到,可能我使用了错误的搜索关键字

与我在python中所做的“相同”的最佳方法是:对所有变量使用单个文件,然后使用头文件在文件之间共享它们?

“建议使用C存储相同类型的值。我找不到答案,…”

如果你不了解你当前的目标/计划,这个问题就没有正确的答案,只有猜测。以下是基于项目假设范围的一些指导性建议

头文件定义的常量:
如果这是一个快速原型或概念验证,那么使用头文件方法可能就完全足够了。这可能取决于“…大量常量值…”的实际大小。这完全取决于你。这取决于您对编辑所有这些值的耐心程度,以及当值的准确性很重要时您的细致程度。如果只有10-20个项目,那么好吧,如果比这大得多,我会选择取消头文件的想法,并使用配置文件或数据库条目。
缺点-这不是运行时可调的。编译时定义的是运行时的行为。
优点–易于实施。(使用
#定义
外部
作用域变量和
定义既简单又有很好的文档记录)

外部初始化文件/数据库:
若项目定义良好,并且在开发过程中进展顺利,并且使用了大量配置值,那个么从外部存储(无论是文件还是数据库)读取可能是最好的。一旦实现,这将以最小的工作量支持最大的运行时灵活性。
缺点–这在实施过程中需要更多的时间和严格性。只要文件在语法上严格,并且不需要频繁更改字段定义或字段计数,读取文件的代码就不必复杂。
优势–最大的运行时灵活性。可以使用用户的运行时提示来输入在运行时会话期间要使用的文件/数据库表等

下面是一个非常简单的概念,用于读取一个简单的文件(如您的文章描述的文件),即使这将编译和构建,也将其视为伪代码,并根据需要进行修改/扩展

enum {//enum values useful to use as indexes to struct values during initialization
    IP,
    SAMPS_PER_SCAN,
    SCAN_FREQUENCY,
    USE_FILTER,
    MEMBERS_MAX
};
//Useful during file read to test record field name 
//against coded field strings prior to parsing field 
//data value into struct
const char members[][20] = {"IP","SCAN_FREQUENCY","SCAN_FREQUENCY","USE_FILTER"};

int get_member_index(const char *mem);//prototype helper function

typedef struct {//struct designed to match configuration dataset
    char ipAddr[20];
    int sPerScan;
    double sfreq;
    bool filter;
}params_s;

params_s params;//create instance of struct parameters

int main(void)
{
    int index = 0;
    char line[80] = {0}; //change size bases on known actual file contents
    char *tok = NULL;
    
    FILE *fp = fopen(".\\data.txt", "r");
    if(fp)
    {
        while(fgets(line, sizeof(line), fp))
        {
          //This is where file is parse
            index = get_member_index(line);
            if(index < 0)
            {
                //error message to user that file is corrupt or incorrect
                //exit program, or provide try again loop to enter another file name
            }
            else
            {
                switch(index)  {//parse data according to type of each parameter
                    case IP:
                        //use strtok or scanf strchr combination to extract value from string
                        tok = strtok(line, "=\" ");//consume first part of line
                        tok = strtok(NULL, "=\" ");  
                        strcpy(params.ipAddr, tok);
                        break;
                    case SAMPS_PER_SCAN:
                       tok = strtok(line, "= ");//consume first part of line
                       tok = strtok(NULL, "= ");//get value
                       params.sPerScan = atoi(tok);
                        break;
                    case SCAN_FREQUENCY:
                        //construt parse for double
                        break;
                    case USE_FILTER:
                        //construct parse for bool
                        break;
                };
                    
            }
        }
        fclose(fp);//file no longer needed, close it
        
        //use captured struct parameter data throughout code
        //via passing as function argument.
    }
    return 0;
}
//helper function to get index of parameter in data line
int get_member_index(const char *mem)
{
    for(int i=0;i<MEMBERS_MAX; i++)
    {
        if(strstr(mem, members[i]))
        {
            return i;
        }
    }
    return -1;
}
enum{//enum值可在初始化期间用作结构值的索引
知识产权,
每扫描一次采样,
扫描频率,
使用过滤器,
成员人数
};
//在读取文件以测试记录字段名期间非常有用
//在分析字段之前针对编码字段字符串
//将数据值转换为结构
常量字符成员[][20]={“IP”、“扫描频率”、“扫描频率”、“使用过滤器”};
int get_member_index(const char*mem)//原型辅助函数
typedef结构{//struct设计用于匹配配置数据集
char-ipAddr[20];
斯珀斯坎国际酒店;
双sfreq;
布尔滤波器;
}params_s;
params_s params//创建结构参数的实例
内部主(空)
{
int指数=0;
字符行[80]={0};//根据已知的实际文件内容更改大小
char*tok=NULL;
文件*fp=fopen(“.\\data.txt”,“r”);
if(fp)
{
while(fgets(line,sizeof(line),fp))
{
//这就是解析文件的地方
索引=获取成员索引(行);
如果(指数<0)
{
//向用户发送的文件已损坏或不正确的错误消息
//退出程序,或提供重试循环以输入其他文件名
}
其他的
{
开关(索引){//根据每个参数的类型分析数据
案例IP:
//使用strtok或scanf-strchr组合从字符串中提取值
tok=strtok(行“=\”);//使用行的第一部分
tok=strtok(空,=\);
strcpy(参数ipAddr,tok);
打破
每扫描一次的案例样本:
tok=strtok(行“=”);//消耗行的第一部分
tok=strtok(NULL,“=”;//获取值
参数s.sPerScan=atoi(tok);
打破
病例扫描频率:
//双精度解析
打破
案例使用过滤器:
//bool的构造分析
打破
};
}
}
fclose(fp);//文件不再需要,请将其关闭
//在整个代码中使用捕获的结构参数数据
//通过作为函数参数传递。
}
返回0;
}
//用于获取数据行中参数索引的helper函数
int get_member_索引(const char*mem)
{

对于(int i=0;i我将添加一个
.h
文件,其中包含要在其中使用这些常量的定义

例如,您的常数.h将是:

#define IP "169.254.98.220"      // The ip used to connect to the LiDAR via Ethernet
#define SAMPLES_PER_SCAN 2400    // number of scans collected in one revolution
#define SCAN_FREQUENCY 35        // Hz, note that a high samples_per_scan can require a low scan_frequency
#define USE_FILTER false         // Uses a filter to average 5 incoming scans into one
您只需将这一行添加到您想要使用它们的
.c
文件中,假设这些文件位于同一文件夹中:

#include "constants.h"
定义是由预编译器处理的宏,因此它基本上与在使用宏的任何地方写入值相同。更多信息
#include "constants.h"
#define A_NUMBER_PLUS_ANOTHER (42 + 66)
// Don't forget those :       ^       ^