如何在C中读取.cnf文件(合取范式)?

如何在C中读取.cnf文件(合取范式)?,c,data-structures,sat,C,Data Structures,Sat,该文件如下所示。我需要读取它们并将它们存储在数据结构中(可能是邻接列表)。但我不知道如何忽略无用的注释,在“p cnf”之后开始阅读 c This Formula is generated by mcnf c c horn? no c forced? no c mixed sat? no c clause length = 3 c p cnf 20 91 4 -18 19 0 3 18 -5 0 -5 -8 -15 0 -20 7 -16 0 10 -13 -7 0 ... 这是我的密码,只有

该文件如下所示。我需要读取它们并将它们存储在数据结构中(可能是邻接列表)。但我不知道如何忽略无用的注释,在“p cnf”之后开始阅读

c This Formula is generated by mcnf
c
c horn? no
c forced? no
c mixed sat? no
c clause length = 3
c
p cnf 20 91
4 -18 19 0
3 18 -5 0
-5 -8 -15 0
-20 7 -16 0
10 -13 -7 0
...
这是我的密码,只有当文件中没有字母时才能使用

    // It would be the following code if the file starts with integers, but how could I change it if you were considering comments? I haven't debugged it yet so it might go wrong, I'll do it later.)

typedef struct LiteralNode {
    int linum; 
    int tag;    //When the variable is true, it is 1, else it is -1.
    struct LiteralNode *next;
} LiteralNode;

typedef struct ClauseNode {
    struct ClauseNode *next;
    int No;
    struct LiteralNode *info;
} ClauseNode;

typedef struct Clause {
    int literal_num;
    int clause_num;
    ClauseNode *root;
} Clause;
   Status CreateClause(Clause *cl, char *filename)
{
    int m, i = 0;
    ClauseNode *p, *q;
    q = (ClauseNode*)malloc(sizeof(ClauseNode));
    p = (ClauseNode*)malloc(sizeof(ClauseNode));
    LiteralNode *l1,*l2;
    p = cl -> root;
    l1 = (LiteralNode*)malloc(sizeof(LiteralNode));
    l2 = (LiteralNode*)malloc(sizeof(LiteralNode));
    FILE *fp = fopen(filename, "rb");
    if (fp == NULL) {
        return ERROR;
    }
    fscanf(fp,"%d", &cl -> clause_num);
    fscanf(fp, "%d",&cl -> literal_num);
    while(fscanf(fp, "%d", &m) != EOF){
        i++;
        q -> No = i;
        q -> next = NULL;
        l1 -> linum = m;
        l1 -> next = NULL;
        q -> info = l1;
        p -> next = q;
        p = q;
        fscanf(fp, "%d", &m);
        while (m != 0) {
            l2 -> linum = m;
            l2 -> tag = 0;
            l2 -> next = NULL;
            l1 -> next = l2;
            l1 = l2;
            fscanf(fp, "%d", &m);
        }
    }
    return OK;
}

该图像是关于我用来存储CNF的数据结构。

您可以迭代这些行:如果一行以
c
开头或为空:放弃它。如果以
p
开头:解析问题定义。如果它以数字开头:切换到子句模式,解析子句而不考虑行尾。C标准库很好地实现了这一点

现在,这是C,C并不能很好地支持任何复杂的数据结构。实现数据结构需要非常小心!我们将通过实现一个“简单”的动态大小的<代码>子句<代码>类型:C++中的一些东西将用<代码> STD::vector < /代码>来解决。我们需要注意错误处理——否则程序的行为将是未定义的,我们根本不希望这样。我们提前捕获任何算术溢出

#include <assert.h>
#include <stdint.h>
#include <stdlib.h>

typedef int ClauseLiteral;
static const int ClauseLiteralMax = INT_MAX;

typedef struct Clause {
  size_t size;
  size_t capacity; // does not include the terminating zero
  ClauseLiteral literals[1];
};

// Maximum capacity that doesn't overflow SIZE_MAX
static inline size_t Clause_max_capacity(void) {
  return (SIZE_MAX-sizeof(Clause))/sizeof(ClauseLiteral);
}

static size_t Clause_size_for_(size_t const count_of_literals) {
  assert(count_of_literals);
  if (count_of_literals > Clause_max_capacity()) return 0;
  return sizeof(Clause) + count_of_literals*sizeof(ClauseLiteral);
}

static size_t Clause_next_capacity_(size_t const capacity) {
  assert(capacity);
  const size_t growth_factor = 2;
  if (capacity > Clause_max_capacity()/growth_factor) {
    if (capacity < Clause_max_capacity()) return Clause_max_capacity();
    return 0;
  }
  return capacity * growth_factor;
}

static Clause *new_Clause_impl_(size_t const capacity) {
  size_t const alloc_size = Clause_size_for_(capacity);
  assert(alloc_size);
  Clause *const clause = calloc(alloc_size); // is zero-terminated
  if (!clause) return NULL;
  clause->size = 0;
  clause->capacity = capacity;
  return clause;
}

Clause *new_Clause(void) { return new_Clause_impl_(4); }

void free_Clause(Clause *clause) { free(clause); }

/** Assures that the clause exists and has room for at least by items */
bool Clause_grow(Clause **const clause_ptr, size_t by) {
  assert(clause_ptr);
  if (!*clause_ptr) return (*clause_ptr = new_Clause_impl_(by));
  Clause *const clause = *clause_ptr;
  assert(clause->size <= clause->capacity);
  if (clause->size > (SIZE_MAX - by)) return false; // overflow
  if (by > Clause_max_capacity()) return false; // won't fit
  if (clause->size > (Clause_max_capacity() - by)) return false; // won't fit
  size_t const new_size = clause->size + by;
  assert(new_size <= Clause_max_capacity());
  if (new_size > clause->capacity) {
    size_t new_capacity = clause->capacity;
    while (new_capacity && new_capacity < new_size)
      new_capacity = Clause_next_capacity_(new_capacity);
    if (!new_capacity) return false;
    Clause *const new_clause = realloc(clause, Clause_size_for_(new_capacity));
    if (!new_clause) return false;
    *clause_ptr = new_clause;
  }
  *clause_ptr->literals[new_size] = 0; // zero-terminate
  return true;
}

bool Clause_push_back(Clause **clause_ptr, ClauseLiteral literal) {
  assert(clause_ptr);
  assert(literal); // zero literals are not allowed within a clause
  if (!Clause_grow(clause_ptr, 1)) return false;
  (*clause_ptr)->literals[(*clause_ptr)->size++] = literal;
  return true;
}
#包括
#包括
#包括
typedef int ClauseLiteral;
静态常数int=int_MAX;
typedef结构子句{
大小;
size\u t capacity;//不包括终止零
条款文字[1];
};
//不溢出大小的最大容量\u MAX
静态内联大小\u t子句\u最大容量(无效){
退货(尺寸最大尺寸(条款))/sizeof(条款);
}
静态大小\u t子句\u大小\u用于(大小\u t常量\u文本计数\u){
断言(文本的计数);
if(count_of_literals>子句_max_capacity())返回0;
返回sizeof(子句)+count_of_literals*sizeof(子句);
}
静态大小条款下一个容量(大小常数容量){
断言(能力);
常数大小增长系数=2;
if(容量>条款最大容量()/增长系数){
if(容量<子句_max_capacity())返回子句_max_capacity();
返回0;
}
回报能力*增长系数;
}
静态子句*新子句执行(大小常数容量){
大小常数分配大小=条款大小(容量);
断言(alloc_大小);
子句*const子句=calloc(alloc_size);//以零结尾
if(!子句)返回NULL;
子句->大小=0;
条款->容量=容量;
返回条款;
}
新条款(无效){返回新条款(4)}
无效自由条款(条款*条款){free(条款);}
/**确保该条款存在,且至少有个项目的空间*/
bool条款(条款**const条款ptr,尺寸依据){
断言(第条);
如果(!*条款ptr)返回(*条款ptr=新条款impl(by));
子句*const子句=*子句\u ptr;
断言(条款->大小容量);
if(子句->大小>(size_MAX-by))返回false;//溢出
如果(by>子句_max_capacity())返回false;//将不适合
if(子句->大小>(子句\u max\u capacity()-by))返回false;//不适合
大小常数新大小=子句->大小+依据;
断言(新的大小子句->容量){
大小\u t新容量=条款->容量;
while(新容量和新容量<新大小)
新容量=第条下一容量(新容量);
如果(!new_capacity)返回false;
条款*const new_条款=realloc(条款,条款尺寸(新容量));
如果(!new_子句)返回false;
*条款=新条款;
}
*子句\u ptr->literals[new\u size]=0;//零终止
返回true;
}
bool子句\u push \u back(子句**子句\u ptr,条款概述文字){
断言(第条);
assert(literal);//子句中不允许有零个文本
如果(!子句_grow(子句_ptr,1))返回false;
(*子句_ptr)->文字[(*子句_ptr)->大小+]=文字;
返回true;
}
我们现在有了一种在阅读时增加条款的方法。那我们来读吧

#include <stdio.h>

typedef struct CNF {
  size_t variable_count;
  size_t clause_count;
  Clause *clauses[1];
};

static inline size_t CNF_max_clause_count() {
  return (SIZE_MAX-sizeof(CNF))/sizeof(Clause*);
}

static size_t CNF_size_for_(size_t const clause_count) {
  if (clause_count >= CNF_max_clause_count()) return 0;
  return sizeof(CNF) + clause_count * sizeof(Clause*);
}

static CNF *new_CNF(size_t variable_count, size_t clause_count) {
  assert(variable_count <= ClauseLiteralMax);
  size_t const cnf_size = CNF_size_fir(clause_count);
  CNF *cnf = calloc(cnf_size);
  if (!cnf) return NULL;
  cnf->variable_count = variable_count;
  cnf->clause_count = clause_count;
  return cnf;
}

static void free_CNF(CNF *const cnf) {
  if (!cnf) return;
  for (Clause **clause_ptr = &cnf->clauses[0]; *clause_ptr && clause+ptr < &cnf->clauses[clause_count]; clause_ptr++)
    free_Clause(*clause_ptr);
  free(cnf);
}

static CNF *read_p_line(FILE *file) {
  assert(file);
  size_t variable_count, clause_count;
  int match_count = fscanf(file, "p cnf %zd %zd", &variable_count, &clause_count);
  if (match_count != 2) return NULL;
  if (variable_count > ClauseLiteralMax) return NULL;
  return new_CNF(variable_count, clause_count);
}

static bool read_c_line(FILE *file) {
  assert(file);
  char c = fgetc(file);
  if (c != 'c') return false;
  while ((c = fgetc(file)) != EOF)
    if (c == '\n') return true;
  return false;
}  

static bool read_clauses(FILE *file, CNF *cnf) {
  assert(file);
  if (!cnf) return false;
  size_t const variable_count = cnf->variable_count;
  for (Clause **clause_ptr = &cnf->clauses[0]; clause_ptr < &cnf->clauses[clause_count];) {
    int literal;
    int match_count = fscanf(file, "%d", &literal);
    if (match_count != 1) return false;
    if (literal == 0) {
      if (!*clause_ptr) return false; // We disallow empty clauses.
      clause_ptr++;
    } 
    else if (literal >= -variable_count && literal <= variable_count) {
      if (!Clause_push_back(clause_ptr, literal)) return false;
    }
    else return false;
  }
  return true;
}

CNF *read_CNF(FILE *file) {
  assert(file);
  CNF *cnf = NULL;
  for (;;) {
    char const c = fgetc(file);
    if (c == EOF) goto error;
    if (isspace(c)) continue; // skip leading whitespace
    if (ungetc(c, file) == EOF) goto error;
    if (c == 'p' && !(cnf = read_p_line(file))) goto error;
    else if (c == 'c' && !read_c_line(file)) goto error;
    else if (isdigit(c)) break;
    goto error;
  }
  if (!read_clauses(file, cnf)) goto error;
  return cnf;
error:
  free_CNF(cnf);
  return NULL;
}
#包括
类型定义结构CNF{
大小变量计数;
尺寸条款数量;
第*条第[1]款;
};
静态内联大小\u t CNF\u max\u子句\u count(){
退货(尺码最大尺寸(CNF))/sizeof(条款*);
}
静态大小(大小常数子句计数){
如果(子句计数>=CNF\u max\u子句计数())返回0;
返回sizeof(CNF)+子句_count*sizeof(子句*);
}
静态CNF*新CNF(大小变量计数、大小子句计数){
断言(变量计数变量计数=变量计数;
cnf->子句计数=子句计数;
返回cnf;
}
静态无空隙(CNF*常数CNF){
如果(!cnf)返回;
对于(子句**子句_ptr=&cnf->子句[0];*子句_ptr&&子句+ptr<&cnf->子句[子句_计数];子句_ptr++)
自由条款(*条款ptr);
免费(cnf);
}
静态CNF*读取p_行(文件*文件){
断言(文件);
大小变量计数、子句计数;
int match_count=fscanf(文件,“p cnf%zd%zd”、&variable_count和子句_count);
if(match_count!=2)返回NULL;
如果(变量计数>最大值)返回NULL;
返回新的CNF(变量计数、子句计数);
}
静态布尔读卡行(文件*文件){
断言(文件);
char c=fgetc(文件);
如果(c!=“c”)返回false;
而((c=fgetc(文件))!=EOF)
如果(c=='\n')返回true;
返回false;
}  
静态bool read_子句(FILE*FILE,CNF*CNF){
断言(文件);
如果(!cnf)返回false;
大小常数变量计数=cnf->变量计数;
对于(子句**子句_ptr=&cnf->子句[0];子句_ptr<&cnf->子句[子句_count];){
整型文字;
int match_count=fscanf(文件“%d”,文字(&T);
if(match_count!=1)返回false;
如果(文字==0){
如果(!*子句_ptr)返回false;//我们不允许空子句。
子句_ptr++;
} 

否则如果(literal>=-variable\u count&&literal文件未显示…到目前为止您尝试了什么?看起来您需要:1/打开一个文件,2/从打开的文件读取,3/标记并解析输入。您已经可以做哪些操作了?很抱歉,我在排版时出错,我会更正它。这没关系-有一些提示。请