C语言中以NULL结尾的结构类型数组

时间:2014-03-29 19:50:56

标签: c arrays pointers struct

我正在尝试构建一个空终止的stucts数组

以下是代码:lzdata.c

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

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

    nist_t *nist; /* NIST data */

    nist=readnist();
}

文件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;
}

标题文件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

数据文件,将通过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
...
...

编译时:

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

我尝试将行nist[i]=(nist_t)NULL;更改为nist[i]=(nist_t*)NULL;,我得到了:

$ 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 *’

我尝试将行nist[i]=(nist_t)NULL;更改为nist[i]=NULL;,我得到了:

$ 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 *’

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

3 个答案:

答案 0 :(得分:2)

对于编译器,宏NULL似乎被定义为((void *) 0),这是一个指向零的通用指针。由于nist[i](对于i的任何有效值)而不是指针,您会收到错误。

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

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

答案 1 :(得分:1)

你有一系列结构。 NULL是一个null 指针常量。结构类型没有空值 - 除非您自己定义一些不同的值。

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

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

然后使用nist_t元素标记数组的结尾,is_valid设置为false。或者也许你可以为其中一个成员使用一些无效值。

这意味着您需要小心处理您编写的任何处理这些结构的代码,以确保is_valid被正确初始化,并且您不会尝试将其他成员值用于{{ 1}}是is_valid

或者你可以构建一个数组,如果false指针,将终止元素设置为空指针类型,为其分配nist_t*

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

nist_t定义的特定方式在这里不是很重要。真正重要的是它是一个空指针常量。将NULL分配给指针对象使其成为空指针;将它分配给任何非指针都是无效的(尽管有些情况下编译器可能会让你侥幸逃脱)。

答案 2 :(得分:0)

这有效:

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

以下是我用来测试它的例程:

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

现在,我必须想办法从config字符串中获取方位角量子数。