在C中以null结尾的结构类型数组。

时间:2021-06-21 20:45:35

I'm trying to built a NULL-terminate array of stucts

我正在构建一个无终止存根的数组

Here is the code: lzdata.c

这是代码:lzdata.c。

#include <stdlib.h>
#include <stdio.h>
#include "nist.h"

int main(int argc,char *argv[])
{

    nist_t *nist; /* NIST data */

    nist=readnist();
}

The file nist.c

文件nist.c

#include <stdlib.h>
#include <stdio.h>
#include "nist.h"

nist_t *readnist()
{
    nist_t *nist; /* NIST data */
    char line[50];
    int len=50;
    int i=0;

    nist=(nist_t*)malloc(sizeof(nist_t));
    while(fgets(line,len,stdin))
    {
        nist=(nist_t*)realloc(nist,sizeof(nist_t)*(i+1));
        sscanf(line,"%s %s %f %lf",nist[i].config,nist[i].term,&(nist[i].j),&(nist[i].level));
        ++i;
    }
    nist=(nist_t*)realloc(nist,sizeof(nist_t)*(i+1));
    nist[i]=(nist_t)NULL;

    return nist;
}

The header file nist.h:

头文件nist.h:

#ifndef NIST_H
#define NIST_H

typedef struct
{
    char config[3];
    char term[4];
    float j;
    double level;
} nist_t;

nist_t *readnist();


#endif

The data file, which will be fed to the application via STDIN:

数据文件将通过STDIN发送给应用程序:

2s  ¹S   0.0    0.000000
2p  ³P°  1.0    142075.333333
2p  ¹P°  0.0    271687.000000
2p  ³P   1.0    367448.333333
2p  ¹D   0.0    405100.000000
2p  ¹S   0.0    499633.000000
3s  ³S   0.0    1532450.000000
3s  ¹S   0.0    1558080.000000
3p  ¹P°  0.0    1593600.000000
3p  ³P°  1.0    1597500.000000
3d  ³D   1.0    1631176.666667
3d  ¹D   0.0    1654580.000000
3s  ³P°  1.0    1711763.333333
3s  ¹P°  0.0    1743040.000000
3p  ³D   1.0    1756970.000000
3p  ³S   0.0    1770380.000000
3p  ³P   0.5    1779340.000000
3p  ¹D   0.0    1795870.000000
3d  ³P°  1.0    1816053.333333
3d  ¹F°  0.0    1834690.000000
3d  ¹P°  0.0    1841560.000000
...
...

When I compile:

当我编译:

$ cc -O2 -o lzdata lzdata.c nist.c nist.c: In function ‘readnist’: nist.c:24:2: error: conversion to non-scalar type requested

$ cc -O2 -o lzdata lzdata。c nist。c nist。在功能“readnist”中:nist。错误:请求转换为非标量类型

I've tried changing the line nist[i]=(nist_t)NULL; to nist[i]=(nist_t*)NULL; and I got:

我试过改变线nist[I]=(nist_t)NULL;nist[我]=(nist_t *)空;我:

$ cc -O2 -o lzdata lzdata.c nist.c nist.c: In function ‘readnist’: nist.c:24:9: error: incompatible types when assigning to type ‘nist_t’ from type ‘struct nist_t *’

$ cc -O2 -o lzdata lzdata。c nist。c nist。在功能“readnist”中:nist。c:24:9:错误:将' struct nist_t '类型赋值为' nist_t '时的不兼容类型

I've tried changing the line nist[i]=(nist_t)NULL; to nist[i]=NULL; and I got:

我试过改变线nist[I]=(nist_t)NULL;nist[我]=零;我:

$ cc -O2 -o lzdata lzdata.c nist.c nist.c: In function ‘readnist’: nist.c:24:9: error: incompatible types when assigning to type ‘nist_t’ from type ‘void *’

$ cc -O2 -o lzdata lzdata。c nist。c nist。在功能“readnist”中:nist。c:24:9:错误:不兼容的类型,从类型“void *”中分配“nist_t”

There could be a different number of lines in different data files. I'm seeking to build a NULL-terminated array of nist_t data, so I can process it until I get to the NULL element. Is this possible?

不同的数据文件中可能有不同数量的行。我正在寻求构建一个以NULL结尾的nist_t数据数组,这样我就可以处理它,直到找到NULL元素为止。这是可能的吗?

3 个解决方案

#1


2  

For your compiler the macro NULL seems to be defined as ((void *) 0), that is a generic pointer to zero. Since nist[i] (for any valid value of i) is not a pointer you get the errors.

对于编译器,宏NULL似乎被定义为((void *) 0),这是一个指向0的泛型指针。因为nist[i](对于i的任何有效值)不是指针,所以您会得到错误。

The best way to solve this might be to either pass the pointer from main by reference into the function and use that, and return the size. Or by passing an integer by reference, and set it to the size.

解决这个问题的最佳方法可能是通过引用将指针从main传递到函数并使用它,然后返回大小。或者通过引用传递一个整数,并将其设置为大小。

There is another solution too, and that is to have an array of pointers. Then you need to allocate each nist_t structure separately, and free them all too. Then you can use NULL to indicate the end of the array. This is actually how argv works, it's terminated by a NULL pointer (so argv[argc] is always equal to NULL).

还有另一个解决方案,那就是有一个指针数组。然后,您需要分别分配每个nist_t结构,并将它们全部释放出来。然后可以使用NULL来表示数组的结束。这就是argv的工作原理,它被一个空指针终止(所以argv[argc]总是等于NULL)。

#2


1  

You have an array of structures. NULL is a null pointer constant. There is no null value for a structure type -- unless you define some distinguished value yourself.

你有一个结构数组。NULL是一个空指针常量。结构类型没有空值——除非您自己定义了一些特殊的值。

For example, you could modify your nist_t type so it has a member that indicates whether the entire value is valid or not:

例如,您可以修改您的nist_t类型,使其具有一个成员,该成员指示整个值是否有效:

#include <stdbool.h>
typedef struct
{
    bool is_valid;
    char config[3];
    char term[4];
    float j;
    double level;
} nist_t;

and then mark the end of the array with a nist_t element with is_valid set to false. Or perhaps you can use some invalid value for one of the other members.

然后用nist_t元素标记数组的末尾,is_valid设置为false。或者您可以为其他成员之一使用一些无效值。

This means you'll need to be careful with any code you write that deals with these structures to ensure that is_valid is initialized correctly, and that you don't try to use the other member values with is_valid is false.

这意味着您需要小心处理这些结构的任何代码,以确保正确初始化了is_valid,并且不尝试使用is_valid的其他成员值为false。

Or you can build an array if nist_t* pointers, setting the terminating element to a null pointer type assigning NULL to it.

或者,如果nist_t*指针,您可以构建一个数组,将终止元素设置为空指针类型,并将空指针类型赋给它。

But it might be simpler just to keep track of the number of valid elements in your array of nist_t objects.

但是,仅仅跟踪nist_t对象数组中有效元素的数量可能会更简单。

The particular way that NULL is defined is not very important here. All that really matters is that it's a null pointer constant. Assigning NULL to a pointer object makes it a null pointer; assigning it to any non-pointer is invalid (though there are cases where the compiler, unfortunately, might let you get away with it).

这里定义空值的特殊方法不是很重要。真正重要的是它是一个空指针常量。将空赋值给指针对象使其成为空指针;将它分配给任何非指针都是无效的(尽管有些情况下,不幸的是,编译器可能会让您侥幸过关)。

#3


0  

This works:

如此:

nist_t *readnist()
{
    nist_t *nist=NULL;  /* NIST data */
    char line[50];      /* A single line of NIST data */
    char config[10];    /* nl quantum numbers */
    char term[10];      /* Rotational term */
    float j;
    double level;       /* energy level */
    int len=50;         /* default length of string */
    int i=0;            /* counter/index variable */
    int n;              /* principal quantum number */
    char l;             /* azimuthal quantum number */
    int en=0;           /* error number */

    while(fgets(line,len,stdin))
    {
        (void)sscanf(line,"%s\t%s\t%f\t%lf",config,term,&j,&level);
        if(NULL==(nist=(nist_t*)realloc(nist,sizeof(nist_t)*(i+1))))
        {
            en=errno;
            fprintf(stderr,"Error %d: memory allocation failure\n",en);
            fprintf(stderr,"File:\t\t%s\n",__FILE__);
            fprintf(stderr,"Function:\t%s\n",__FUNCTION__);
            fprintf(stderr,"Line:\t\t%d\n",__LINE__-6);
            exit(en);
        };
        nist[i].config=(char*)malloc(sizeof(char)*(strlen(config)+1));
        nist[i].term=(char*)malloc(sizeof(char)*(strlen(term)+1));
        strcpy(nist[i].config,config);
        sscanf(config,"%d%c",&n,&l);
        nist[i].n=n;
        strcpy(nist[i].term,term);
        nist[i].j=j;
        nist[i].level=level;
        ++i;
    }
    nist=(nist_t*)realloc(nist,sizeof(nist_t)*(i+1));
    nist[i].config=NULL;
    nist[i].term=NULL;
    nist[i].j=0.0;
    nist[i].level=0.0;

    return nist;
}

And here is a routine I used to test it:

这是我用来测试它的一个惯例:

nist_t *prtnist(nist_t *nist)
{
    int i=0;

    while((NULL!=nist[i].config) && (NULL!=nist[i].term))
    {
       fprintf(stderr,"%s\t%d\t%s\t%4.1f\t%14.8e\n",nist[i].config,nist[i].n,nist[i].term,nist[i].j,nist[i].level);
        ++i;
    }
    return nist;
}

Now I've got to figure a way to get the azimuthal quantum number out of the config string.

现在我要想办法从配置字符串中得到方位角量子数。

#1


2  

For your compiler the macro NULL seems to be defined as ((void *) 0), that is a generic pointer to zero. Since nist[i] (for any valid value of i) is not a pointer you get the errors.

对于编译器,宏NULL似乎被定义为((void *) 0),这是一个指向0的泛型指针。因为nist[i](对于i的任何有效值)不是指针,所以您会得到错误。

The best way to solve this might be to either pass the pointer from main by reference into the function and use that, and return the size. Or by passing an integer by reference, and set it to the size.

解决这个问题的最佳方法可能是通过引用将指针从main传递到函数并使用它,然后返回大小。或者通过引用传递一个整数,并将其设置为大小。

There is another solution too, and that is to have an array of pointers. Then you need to allocate each nist_t structure separately, and free them all too. Then you can use NULL to indicate the end of the array. This is actually how argv works, it's terminated by a NULL pointer (so argv[argc] is always equal to NULL).

还有另一个解决方案,那就是有一个指针数组。然后,您需要分别分配每个nist_t结构,并将它们全部释放出来。然后可以使用NULL来表示数组的结束。这就是argv的工作原理,它被一个空指针终止(所以argv[argc]总是等于NULL)。

#2


1  

You have an array of structures. NULL is a null pointer constant. There is no null value for a structure type -- unless you define some distinguished value yourself.

你有一个结构数组。NULL是一个空指针常量。结构类型没有空值——除非您自己定义了一些特殊的值。

For example, you could modify your nist_t type so it has a member that indicates whether the entire value is valid or not:

例如,您可以修改您的nist_t类型,使其具有一个成员,该成员指示整个值是否有效:

#include <stdbool.h>
typedef struct
{
    bool is_valid;
    char config[3];
    char term[4];
    float j;
    double level;
} nist_t;

and then mark the end of the array with a nist_t element with is_valid set to false. Or perhaps you can use some invalid value for one of the other members.

然后用nist_t元素标记数组的末尾,is_valid设置为false。或者您可以为其他成员之一使用一些无效值。

This means you'll need to be careful with any code you write that deals with these structures to ensure that is_valid is initialized correctly, and that you don't try to use the other member values with is_valid is false.

这意味着您需要小心处理这些结构的任何代码,以确保正确初始化了is_valid,并且不尝试使用is_valid的其他成员值为false。

Or you can build an array if nist_t* pointers, setting the terminating element to a null pointer type assigning NULL to it.

或者,如果nist_t*指针,您可以构建一个数组,将终止元素设置为空指针类型,并将空指针类型赋给它。

But it might be simpler just to keep track of the number of valid elements in your array of nist_t objects.

但是,仅仅跟踪nist_t对象数组中有效元素的数量可能会更简单。

The particular way that NULL is defined is not very important here. All that really matters is that it's a null pointer constant. Assigning NULL to a pointer object makes it a null pointer; assigning it to any non-pointer is invalid (though there are cases where the compiler, unfortunately, might let you get away with it).

这里定义空值的特殊方法不是很重要。真正重要的是它是一个空指针常量。将空赋值给指针对象使其成为空指针;将它分配给任何非指针都是无效的(尽管有些情况下,不幸的是,编译器可能会让您侥幸过关)。

#3


0  

This works:

如此:

nist_t *readnist()
{
    nist_t *nist=NULL;  /* NIST data */
    char line[50];      /* A single line of NIST data */
    char config[10];    /* nl quantum numbers */
    char term[10];      /* Rotational term */
    float j;
    double level;       /* energy level */
    int len=50;         /* default length of string */
    int i=0;            /* counter/index variable */
    int n;              /* principal quantum number */
    char l;             /* azimuthal quantum number */
    int en=0;           /* error number */

    while(fgets(line,len,stdin))
    {
        (void)sscanf(line,"%s\t%s\t%f\t%lf",config,term,&j,&level);
        if(NULL==(nist=(nist_t*)realloc(nist,sizeof(nist_t)*(i+1))))
        {
            en=errno;
            fprintf(stderr,"Error %d: memory allocation failure\n",en);
            fprintf(stderr,"File:\t\t%s\n",__FILE__);
            fprintf(stderr,"Function:\t%s\n",__FUNCTION__);
            fprintf(stderr,"Line:\t\t%d\n",__LINE__-6);
            exit(en);
        };
        nist[i].config=(char*)malloc(sizeof(char)*(strlen(config)+1));
        nist[i].term=(char*)malloc(sizeof(char)*(strlen(term)+1));
        strcpy(nist[i].config,config);
        sscanf(config,"%d%c",&n,&l);
        nist[i].n=n;
        strcpy(nist[i].term,term);
        nist[i].j=j;
        nist[i].level=level;
        ++i;
    }
    nist=(nist_t*)realloc(nist,sizeof(nist_t)*(i+1));
    nist[i].config=NULL;
    nist[i].term=NULL;
    nist[i].j=0.0;
    nist[i].level=0.0;

    return nist;
}

And here is a routine I used to test it:

这是我用来测试它的一个惯例:

nist_t *prtnist(nist_t *nist)
{
    int i=0;

    while((NULL!=nist[i].config) && (NULL!=nist[i].term))
    {
       fprintf(stderr,"%s\t%d\t%s\t%4.1f\t%14.8e\n",nist[i].config,nist[i].n,nist[i].term,nist[i].j,nist[i].level);
        ++i;
    }
    return nist;
}

Now I've got to figure a way to get the azimuthal quantum number out of the config string.

现在我要想办法从配置字符串中得到方位角量子数。