从零开始编写SAT求解器(二)
从零开始编写SAT求解器(二)
- 从零开始编写SAT求解器(二)
- 上一篇地址
- 文件解析器
- assert宏
从零开始编写SAT求解器(二)
上一篇地址
文件解析器
上代码:
//
// Dimacs parser.
//filename:DimacsParser.h
//
#include
#include
#include
#include
#include "common.h"#ifndef DPLL_DIMACSPARSER_H
#define DPLL_DIMACSPARSER_Hclass DimacsParser {
public:/*** Parse a dimacs file.* @param file_name dimacs file name* @return a parsed formula (if succeeds)*/static formula parse(const std::string &file_name) {std::ifstream fin(file_name);if (!fin) {std::cerr << "file not found: " << file_name << "'" << std::endl;std::exit(1);}int n = 0, m = 0;while (!fin.eof()) {char ch;fin >> ch;if (ch == 'c') { // c-line: commentchar buf[1024];fin.getline(buf, 1024);} else if (ch == 'p') { // p-line: clauses will beginstd::string buf;fin >> buf;assert(buf == "cnf");fin >> n >> m;break;} else { // unexpected linestd::cerr << "parse error at char '" << ch << "'" << std::endl;std::exit(1);}}// clauses beginstd::vector<clause> clauses;for (int i = 0; i < m; i++) {clause c;while (!fin.eof()) {int v;fin >> v;if (v == 0) {clauses.push_back(c);break;}assert(VAR(v) <= n);c.push_back(v);}}assert(clauses.size() == m);return formula(n, clauses);}
};#endif //DPLL_DIMACSPARSER_H
assert宏
assert宏的原型定义在
#include
void assert( int expression );
assert的作用是现计算表达式 expression ,如果其值为假(即为0),那么它先向stderr打印一条出错信息,然后通过调用 abort 来终止程序运行。
请看下面的程序清单badptr.c:
#include
#include
#include
int main( void )
{FILE *fp;fp = fopen( "test.txt", "w" );//以可写的方式打开一个文件,如果不存在就创建一个同名文件assert( fp ); //所以这里不会出错fclose( fp );fp = fopen( "noexitfile.txt", "r" );//以只读的方式打开一个文件,如果不存在就打开文件失败assert( fp ); //所以这里出错fclose( fp ); //程序永远都执行不到这里来return 0;
}
执行这个文件,输出:
[root@localhost error_process]# gcc badptr.c
[root@localhost error_process]# ./a.out
a.out: badptr.c:14: main: Assertion `fp'' failed.
使用assert的缺点是,频繁的调用会极大的影响程序的性能,增加额外的开销。
在调试结束后,可以通过在包含#include
#include
#define NDEBUG
#include
用法总结与注意事项:
- 在函数开始处检验传入参数的合法性
如:
int resetBufferSize(int nNewSize)
{
//功能:改变缓冲区大小,
//参数:nNewSize 缓冲区新长度
//返回值:缓冲区当前长度
//说明:保持原信息内容不变 nNewSize<=0表示清除缓冲区
assert(nNewSize >= 0);
assert(nNewSize <= MAX_BUFFER_SIZE);
...
}
- 每个assert只检验一个条件,因为同时检验多个条件时,如果断言失败,无法直观的判断是哪个条件失败
不好:
assert(nOffset>=0 && nOffset+nSize<=m_nInfomationSize);
好:
assert(nOffset >= 0);
assert(nOffset+nSize <= m_nInfomationSize);
- 不能使用改变环境的语句,因为assert只在DEBUG个生效,如果这么做,会使用程序在真正运行时遇到问题
错误:
assert(i++ < 100)
这是因为如果出错,比如在执行之前i=100,那么这条语句就不会执行,那么i++这条命令就没有执行。
正确:
assert(i < 100)i++;
- assert和后面的语句应空一行,以形成逻辑和视觉上的一致感
- 有的地方,assert不能代替条件过滤
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
