如何在C中读取.cnf文件(合取范式)?
该文件如下所示。我需要读取它们并将它们存储在数据结构中(可能是邻接列表)。但我不知道如何忽略无用的注释,在“p 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 ... 这是我的密码,只有
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/标记并解析输入。您已经可以做哪些操作了?很抱歉,我在排版时出错,我会更正它。这没关系-有一些提示。请