Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/66.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 如何设置结构数组的“结束”_C_Data Structures_Struct_Sentinel - Fatal编程技术网

C 如何设置结构数组的“结束”

C 如何设置结构数组的“结束”,c,data-structures,struct,sentinel,C,Data Structures,Struct,Sentinel,我想将\0的等效值设置为结构数组的结尾,以便知道它何时结束 到目前为止,我正在尝试这样做: typedef struct { char * id; char * date; } ROW; int main(int argc, char *argv[]) { FILE * fp = fopen("test100k.csv", "r"); ROW * rows = malloc(sizeof(row) * 10000); int row_num = 0;

我想将\0的等效值设置为结构数组的结尾,以便知道它何时结束

到目前为止,我正在尝试这样做:

typedef struct {
    char * id;
    char * date;
} ROW;

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

    FILE * fp = fopen("test100k.csv", "r");
    ROW * rows = malloc(sizeof(row) * 10000);
    int row_num = 0;
    ROW row;
    char buffer[255];

    while(fgets(buffer, sizeof(buffer), fp) != NULL) {  
        // some logic to set the object
        rows[row_num++] = row;
    }

    rows[row_num] =  NULL; // how to do this?

}

结束行数组的正确方法是什么?

您可以尝试使用memset:

memset(&rows[row_num], NULL, sizeof(ROW));

一种可能性是通过其成员的唯一值定义一个常量作为哨兵:

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

typedef struct {
    char * id;
    char * date;
} ROW;

/* Initialising the ROW's members below to a literal could lead to 
   ambiguities, as the compiler is free to merge the same literal 
   appearing more then once into only one instance in memory. 
   Whereas initialising the members to the struct's address itself 
   guarantees the uniqueness of the address stored.
   (Just do not ever dereference it, at least not without casting it 
   back to the type ROW.) */

const ROW STOPPER_ROW = {(char*)&STOPPER_ROW, (char*)&STOPPER_ROW};

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

    ROW * rows = malloc(10000 * sizeof *rows);
    size_t row_num = 0;
    ...

    while(NULL != fgets(buffer, sizeof(buffer), fp) && 
          10000 > row_num) {    
        // some logic to set the object
        rows[row_num++] = row;
    }

    rows[row_num] = STOPPER_ROW;

    row_num = 0;
    /* Comparing only one member below in fact would do. */
    while (rows[row_num].id != STOPPER_ROW.id && 
           rows[row_num].date != STOPPER_ROW.date)
    {
        /* Use rows[row_num] here */
        ++row_num;
    }
}

以下是标准方法:

添加一个指示最后一个有效索引的计数器变量。 按引用而不是按值存储行。也就是说,为每一行分配一个空间,并在数组中存储指向它的指针,而不是存储行本身。如果指针为空,则该行无效。 如果某行存在已知的无效值,请将所有数组单元格初始化为此值。具有无效值的单元格将指示有效项的结束。
为什么需要结束阵列?您已经知道它有多大:row_num。为什么这个循环不能使用row_num?在这种特殊情况下,您可以将两个字段都设置为NULL。不过,最好只跟踪大小。@DavidC.Rankin我们不知道正常行中是否不能出现id=NULL未显示设置对象的某些逻辑。另外,如果可以传递行,则可以传递row_num.OT:调用fopen和/或malloc时始终检查=NULL返回值以确保操作成功。如果不成功,==NULL,则调用perror。。,。失败;然后清除并退出程序。memset的第二个参数是字节值。此处不能传递NULL。memset&rows[row_num],0,sizeofROW??即使NULL被更正为0,C标准也不能保证所有零位都代表一个NULL指针。唯一性不是这里需要的属性。不能保证所有可能的地址都不能表示有效的id和日期。