import glob
fileList=glob.glob(“E:PythonWork*.exe”)
for filename in fileList:
带参数调用filename
source:
http://bbs.csdn.net/topics/90198608
Category: 不学无术
Lex与Yacc快速入门
附件:Yacc与Lex快速入门
http://orz.dayandcarrot.net/wordpress/wp-content/uploads/2013/05/Yacc与Lex快速入门.pdf
Lex 和 Yacc 是 UNIX 两个非常重要的、功能强大的工具。事实上,如果你熟练掌握
Lex 和 Yacc 的话,它们的强大功能使创建 FORTRAN 和 C 的编译器如同儿戏。
Ashish Bansal 为您详细的讨论了编写自己的语言和编译器所用到的这两种工具,包
括常规表达式、声明、匹配模式、变量、Yacc 语法和解析器代码。最后,他解释了
怎样把 Lex 和 Yacc 结合起来。
详见附件
词法分析:如何将NFA转换为DFA
- 本文来源及参考资料:
- http://hi.baidu.com/beanchx/item/b153390de0691827a1312d49
- http://www.2cto.com/kf/201302/191521.html
- http://dev.21tx.com/2009/09/26/11354.html
1. 子集构造(Subset Construction)
这是一个转换NFA到DFA的算法。我们知道NFA和DFA的区别最主要的就是一个状态和一个input symbol是否能够确定一个状态的问题,对于NFA,它将确定一个组状态,而DFA将确定一个状态,因此,我们有一个很好的办法就是把NFA的状态集对应每个DFA的状态,这就是subset construction的思想,不过这只是大概泛泛而论,我们需要更加明确的认识
1) NFA在任何一个input symbol下,映射的状态集(通过move函数,这个集合通常用T字母表示)应该被知道
2) 必须保证1)中状态集都对应了DFA中的一个状态
具体算法:
Input : 一个NFA N
Output : 接受相同语言的DFA D
Method : 为D构架一个transition table(转换表) Dtran,每个DFA的状态是一个NFA的状态集合(这里一定要注意前面说过的1)2)两点)。我们定义一些操作:
s 表示NFA的状态,T 表示NFA的状态集合,a表示一个input symbol
ε-transition(ε转换)就是说input symbol为ε时的transition(转换)
| 操作(operation) |
描述(description) |
| ε-closure(s) |
从NFA的状态s出发,只通过ε-transition到达的NFA的状态集合 |
| ε-closure(T) |
NFA的集合T中的状态p,只通过ε-transition到达的NFA的状态集合,再求这些集合的交集。用数学表达就是 {p|p 属于 ε-closure(t) , t属于T} |
| move(T,a) |
NFA的集合,这个集合在input symbol为a,状态为T中任意状态情况下,通过一个转换得到的集合 |
注意一下,所有的操作都是针对NFA的状态或者状态集合,得到的时NFA的状态集合,或者说是DFA看为一个状态
Subset Construction
初始Dstates,它仅仅含有状态(D的状态)ε-closure(s0),并且状态未被标记,s0表示开始状态,注意,Dstates放的是D的状态
while ( Dstates 有未标记的状态 T ) { // T是D中的一个状态,也是N中一个状态集
标记 T;
for ( input symbol a ){ // 遍历所有的input symbol
U = ε-closure(move(T, a)); // move为NFA的move函数
if ( U 不在 Dstates 中 )
把U作为尚未标记的状态加入Dstates;
Dtran[T, a] = U
}
}
注意,状态s,ε-closure(s)一定包含s
我们先来熟悉上面的操作operation,再来看上面的算法

ε-closure(0) = {0, 1, 2, 4, 7} // 从0状态出发的,input symbol为ε的所有状态的集合
ε-closure(3) = {1, 2, 3, 4, 6, 7}
ε-closure(8) = {8}
ε-closure( {3, 8} ) = ε-closure(3) U ε-closure(8) = {1, 2, 3, 4, 6, 7, 8}
move(0,a) = 空
move(7,a) = {8}
move(8,b) = {9}
move( {0, 1, 2, 4, 7}, a) = move(0,a) U move(1,a) U move(2,a) U move(4,a) U move(7,a) = {3, 8}
现在可以回去理解一下算法了。
这里再说说求ε-closure(T)的算法:
把T的所有状态压入stack(栈);
ε-closure(T)的初始值为 T 中的所有元素 ; // 也就是一定包含他们本身
while( 栈非空 ) {
弹出栈顶元素 t ;
for( 每个属于 move(t, ε) 的状态 u ){
if( u 不在 ε-closure(T) 中 ){
u 加入 ε-closure(T);
把 u 入栈;
}
}
}
下面对上图如何使用Set Construction算法来构建DFA做一个详细的描述:
1. 初始化Dstates 把集合 ε-closure(s0) = {0, 1, 2, 4, 7}作为第一个状态,设此状态为 A
2. 现在转化,input symbol {a, b},因此,求:
ε-closure(move(A, a));
ε-closure(move(A, b));
这里会得到2个状态
ε-closure(move(A, a)) = {1, 2, 3, 4, 6, 7, 8},设其为 B
ε-closure(move(A, b)) = {1, 2, 4, 5, 6, 7}, 设其为C
B,C放入Dstates
改写 Dtrans
最终得到的 Dtrans 为:
A = {0, 1, 2, 4, 7}
B = {1, 2, 3, 4, 6, 7, 8}
C = {1, 2, 4, 5, 6, 7}
D = {1, 2, 4, 5, 6, 7, 9}

因此,NFA转化成为DFA:

=========================================
DFA的状态
struct DFA_State
{
set content;
bool bFlag;
#ifdef _DEBUG
uint idx;
#endif
DFA_State(const set& x) : content(x), bFlag(false)
{
#ifdef _DEBUG
idx = inc();
#endif
}
inline const bool operator==(const DFA_State& x)const
{
if (&x == this) return true;
return content == x.content;
}
#ifdef _DEBUG
inline uint inc()
{
static uint i = 0;
return i++;
}
#endif
};
struct DFA_Edge
{
struct
{
Char_Type char_value;
String_Type string_value;
}data;
enum Edge_Type
{
TUnknown = 0,
TNot = 1,
TChar = 2,
TString = 4
};
uchar edge_type;
DFA_State* pFrom;
DFA_State* pTo;
DFA_Edge(const Char_Type& x, bool bNot, DFA_State* pFrom, DFA_State* pTo) : pFrom(pFrom), pTo(pTo)
{
data.char_value = x;
edge_type = bNot ? (TChar | TNot) : TChar;
}
DFA_Edge(const String_Type& x, bool bNot, DFA_State* pFrom, DFA_State* pTo) : pFrom(pFrom), pTo(pTo)
{
data.string_value = x;
edge_type = bNot ? (TString | TNot) : TString;
}
inline const bool isNot()const
{
return (edge_type & TNot) == TNot;
}
inline const bool isChar()const
{
return (edge_type & TChar) == TChar;
}
inline const bool isString()const
{
return (edge_type & TString) == TString;
}
const Edge_Type edgeType()const
{
if (isChar()) return TChar;
else if (isString()) return TString;
else return TUnknown;
}
const bool operator<(const DFA_Edge& x)const
{
return (ulong)pFrom + pTo < (ulong)x.pFrom + x.pTo;
}
const bool operator==(const DFA_Edge& x)const
{
return pFrom == x.pFrom && pTo == x.pTo;
}
};
DFA_State* pDFAStart; setpDFAEnds; set dfa_Edges;
void epsilonClosure(const set& k, EpsilonClosureInfo& info) { for (typename set ::const_iterator i = k.begin(), m = k.end(); i != m; ++i) { info.states.insert(*i); set tmp; tmp.insert(*i); while (!tmp.empty()) { EpsilonNFA_State* pState = *tmp.begin(); for (typename vector ::const_iterator j = epsilonNFA_Edges[pState].begin(), n = epsilonNFA_Edges[pState].end(); j != n; ++j) { if (j->isEpsilon()) { if (info.states.insert(j->pTo).second) tmp.insert(j->pTo); } else if (j->isChar()) info.chars.insert(pair (j->data.char_value, j->isNot())); else if (j->isString()) info.strings.insert(pair (j->data.string_value, j->isNot())); } tmp.erase(pState); } } }
struct EpsilonClosureInfo
{
set states;
set > chars;
set > strings;
EpsilonClosureInfo() {}
EpsilonClosureInfo(const set& states,
const set >& chars,
const set >& strings)
: states(states)
, chars(chars)
, strings(strings) {}
EpsilonClosureInfo(const EpsilonClosureInfo& x)
{
states = x.states;
chars = x.chars;
strings = x.strings;
}
};
setmove(const DFA_State& t, const Char_Type& c, bool bNot) { set result; for (typename set ::const_iterator i = t.content.begin(), m = t.content.end(); i != m; ++i) { for (typename vector ::const_iterator j = epsilonNFA_Edges[*i].begin(), n = epsilonNFA_Edges[*i].end(); j != n; ++j) { if (j->isChar() && j->data.char_value == c && j->isNot() == bNot) result.insert(j->pTo); } } return result; } set move(const DFA_State& t, const String_Type& s, bool bNot) { set result; for (typename set ::const_iterator i = t.content.begin(), m = t.content.end(); i != m; ++i) { for (typename vector ::const_iterator j = epsilonNFA_Edges[*i].begin(), n = epsilonNFA_Edges[*i].end(); j != n; ++j) { if (j->isString() && j->data.string_value == s && j->isNot() == bNot) result.insert(j->pTo); } } return result; }
void buildDFA()
{
set start;
start.insert(pEpsilonStart);
typedef pair c_type;
map > c;
queue c2;
pDFAStart = DFA_State_Alloc::allocate();
EpsilonClosureInfo info;
epsilonClosure(start, info);
construct(pDFAStart, info.states);
c_type ct(pDFAStart, info);
c[info.states.size()].push_back(ct);
c2.push(ct);
if (isEndDFAStatus(pDFAStart)) pDFAEnds.insert(pDFAStart);
context.dfa_States.insert(pDFAStart);
while (!c2.empty())
{
DFA_State* t = c2.front().first;
set > chars = c2.front().second.chars;
set > strings = c2.front().second.strings;
t->bFlag = true;
for (typename set >::const_iterator i = chars.begin(), m = chars.end(); i != m; ++i)
{
EpsilonClosureInfo info;
epsilonClosure(move(*t, i->first, i->second), info);
DFA_State* p = getDFAState(info.states, c);
if (p) // 如果这个状态已存在
{
dfa_Edges.insert(DFA_Edge(i->first, i->second, t, p));
}
else
{
DFA_State* pState = DFA_State_Alloc::allocate();
construct(pState, info.states);
context.dfa_States.insert(pState);
if (isEndDFAStatus(pState)) pDFAEnds.insert(pState);
c_type ct(pState, info);
c[info.states.size()].push_back(ct);
c2.push(ct);
dfa_Edges.insert(DFA_Edge(i->first, i->second, t, pState));
}
}
for (typename set >::const_iterator i = strings.begin(), m = strings.end(); i != m; ++i)
{
EpsilonClosureInfo info;
epsilonClosure(move(*t, i->first, i->second), info);
DFA_State* p = getDFAState(info.states, c);
if (p) // 如果这个状态已存在
{
dfa_Edges.insert(DFA_Edge(i->first, i->second, t, p));
}
else
{
DFA_State* pState = DFA_State_Alloc::allocate();
construct(pState, info.states);
context.dfa_States.insert(pState);
if (isEndDFAStatus(pState)) pDFAEnds.insert(pState);
c_type ct(pState, info);
c[info.states.size()].push_back(ct);
c2.push(ct);
dfa_Edges.insert(DFA_Edge(i->first, i->second, t, pState));
}
}
c2.pop();
}
}
void printDFA()
{
printf("---------- DFA Start ----------n");
set tmp;
for (typename set::const_iterator i = dfa_Edges.begin(), m = dfa_Edges.end(); i != m; ++i)
{
printf("%03d -> %03d", i->pFrom->idx, i->pTo->idx);
switch (i->edgeType())
{
case DFA_Edge::TChar:
printf("(%c)", i->data.char_value);
break;
case DFA_Edge::TString:
printf("(%s)", i->data.string_value.c_str());
break;
default:
break;
}
if (i->isNot()) printf("(not)");
printf("n");
tmp.insert(i->pFrom);
tmp.insert(i->pTo);
}
printf("start: %03d -> ends: ", pDFAStart->idx);
for (typename set::const_iterator i = pDFAEnds.begin(), m = pDFAEnds.end(); i != m; ++i)
{
printf("%03d ", (*i)->idx);
}
printf("n");
#if DEBUG_LEVEL == 3
printf("-------------------------------n");
for (typename set::const_iterator i = tmp.begin(), m = tmp.end(); i != m; ++i)
{
printf("State: %03dn", (*i)->idx);
for (typename set::const_iterator j = (*i)->content.begin(), n = (*i)->content.end(); j != n; ++j)
{
printf("%03d ", (*j)->idx);
}
printf("n");
}
#endif
printf("----------- DFA End -----------n");
}
Rule_Type::Context context;
Rule_Type a('a', context), b('b', context), d('d', context);
Rule_Type result = (a - d).opt() + (+b | !(a + b));
result.buildDFA();
#ifdef _DEBUG
result.printEpsilonNFA();
result.printDFA();
#endif


re -> NFA 正则表达式->不确定自动机
文章来自http://www.360doc.com/content/09/0219/10/98111_2586955.shtml
以及http://hi.baidu.com/tcet030840zxp/item/c923fe885ddd0329100ef3ec
最近得做一些跟自动机有关的东东,其中一部分可以简要地看作是由一套正则文法生成状态自动机的过程。
什么是正则表达式?首先我们看看什么是正则表达式。这个东东呢,一般用于描述一个字符串的集合——直接说就是一个正则表达式可能可以匹配一大堆字符串,而这一大堆字符串可以形成一个集合,它们的共同特征就是可以被这个正则表达式匹配。就像去死去死团,但是不同的是去死去死团的团员的共同特征是不被任何异性所匹配——但是这没关系,我们不妨取去死去死团的补集就行了。 Mar(y|k|cus) is son of bitch. 真是非常de省力,唯一的缺点是可能对方不知道你在说什么。
下面是第三个基本结构,被称为Kleene star (或者 Kleene 闭包)的。因为这个操作是Stephen Cole Kleene发明的。啊啊,其实正则表达式这个东西就是Kleene发明的。这个同学真是非常的牛B,因为他是更加牛B的 阿隆佐 – 丘奇 ( Alonzo Church )——历史上和阿兰 – 图灵 ( Alan Turing ) 并称的人物——的学生。有多牛B呢,这个Kleene还和他的老师,还有图灵,就递归论发表了论文,奠定了可计算理论的根基。啊哈哈哈,真是牛B啊。
当然咯,还有一些别的操作,比如我们知道的+,?,集合[]等等,但是这些操作都可以通过上面三个基本操作的组合来完成。 什么是NFA?要说NFA嘛,我得先说说DFA。所谓DFA,就是Deterministic Finite state Automata的简称。是状态机的一种。通俗的说,就是一大堆状态的集合,里面有一个初始状态和若干终止状态,每个状态可以有若干个输出边前往别的状态。但是要求每个状态的同一种输出边至多只有一个,所以自动机被称为是”Deterministic”的。 如何转换?刚才Shellex说了,正则表达式有三种基本结构。如果能先将这三种基本结构转换成对应的NFA,然后在用这三种基本结构去拼装成完整的NFA是不是很省力呢? PUSH a To automaton stack PUSH b To automaton stack UNION STAR PUSH c To automaton stack CONCAT PUSH d To automaton stack CONCAT POP result 里面的UNION,STAR 和 CONCAT就是三种基本结构的生成操作了。而这三种基本操作的实现是这样的: POP T from automaton stack CREATE state A, B ADD transition from A to B with 'ε' ADD transition from A to T.entry with 'ε' ADD transition from T.exit to A with 'ε' ADD transition from T.exit to B with 'ε' ADD state A, B to T PUSH T to automaton stack Concat: POP F, S from automaton stack ADD transition from F.exit to S.entry with 'ε' JOIN S to F SET F.exit = S.exit SET F.inputSet += S.inputSet PUSH F to automaton stack Union: POP F, S from automaton stack CREATE state A, B ADD transition from A to F.entry with 'ε' ADD transition from A to S.entry with 'ε' ADD transition from T.exit to B with 'ε' ADD transition from T.exit to B with 'ε' JOIN S to F ADD state A, B to T SET F.exit = S.exit SET F.inputSet += S.inputSet PUSH F to automaton stack |
/* Regular expression implementation.
* Supports only ( | ) * + ?. No escapes.
* Compiles to NFA and then simulates NFA
* using Thompson's algorithm.
*
* See also http://swtch.com/~rsc/regexp/ and
* Thompson, Ken. Regular Expression Search Algorithm,
* Communications of the ACM 11(6) (June 1968), pp. 419-422.
*
* Copyright (c) 2007 Russ Cox.
* Can be distributed under the MIT license, see bottom of file.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
/*
* Convert infix regexp re to postfix notation.
* Insert . as explicit concatenation operator.
* Cheesy parser, return static buffer.
*/
char*
re2post(char *re)
{
int nalt, natom;
static char buf[8000];
char *dst;
struct {
int nalt;
int natom;
} paren[100], *p;
p = paren;
dst = buf;
nalt = 0;
natom = 0;
if(strlen(re) >= sizeof buf/2)
return NULL;
for(; *re; re++){
switch(*re){
case '(':
if(natom > 1){
--natom;
*dst++ = '.';
}
if(p >= paren+100)
return NULL;
p->nalt = nalt;
p->natom = natom;
p++;
nalt = 0;
natom = 0;
break;
case '|':
if(natom == 0)
return NULL;
while(--natom > 0)
*dst++ = '.';
nalt++;
break;
case ')':
if(p == paren)
return NULL;
if(natom == 0)
return NULL;
while(--natom > 0)
*dst++ = '.';
for(; nalt > 0; nalt--)
*dst++ = '|';
--p;
nalt = p->nalt;
natom = p->natom;
natom++;
break;
case '*':
case '+':
case '?':
if(natom == 0)
return NULL;
*dst++ = *re;
break;
default:
if(natom > 1){
--natom;
*dst++ = '.';
}
*dst++ = *re;
natom++;
break;
}
}
if(p != paren)
return NULL;
while(--natom > 0)
*dst++ = '.';
for(; nalt > 0; nalt--)
*dst++ = '|';
*dst = 0;
return buf;
}
/*
* Represents an NFA state plus zero or one or two arrows exiting.
* if c == Match, no arrows out; matching state.
* If c == Split, unlabeled arrows to out and out1 (if != NULL).
* If c < 256, labeled arrow with character c to out.
*/
enum
{
Match = 256,
Split = 257
};
typedef struct State State;
struct State
{
int c;
State *out;
State *out1;
int lastlist;
};
State matchstate = { Match }; /* matching state */
int nstate;
/* Allocate and initialize State */
State*
state(int c, State *out, State *out1)
{
State *s;
nstate++;
s = malloc(sizeof *s);
s->lastlist = 0;
s->c = c;
s->out = out;
s->out1 = out1;
return s;
}
/*
* A partially built NFA without the matching state filled in.
* Frag.start points at the start state.
* Frag.out is a list of places that need to be set to the
* next state for this fragment.
*/
typedef struct Frag Frag;
typedef union Ptrlist Ptrlist;
struct Frag
{
State *start;
Ptrlist *out;
};
/* Initialize Frag struct. */
Frag
frag(State *start, Ptrlist *out)
{
Frag n = { start, out };
return n;
}
/*
* Since the out pointers in the list are always
* uninitialized, we use the pointers themselves
* as storage for the Ptrlists.
*/
union Ptrlist
{
Ptrlist *next;
State *s;
};
/* Create singleton list containing just outp. */
Ptrlist*
list1(State **outp)
{
Ptrlist *l;
l = (Ptrlist*)outp;
l->next = NULL;
return l;
}
/* Patch the list of states at out to point to start. */
void
patch(Ptrlist *l, State *s)
{
Ptrlist *next;
for(; l; l=next){
next = l->next;
l->s = s;
}
}
/* Join the two lists l1 and l2, returning the combination. */
Ptrlist*
append(Ptrlist *l1, Ptrlist *l2)
{
Ptrlist *oldl1;
oldl1 = l1;
while(l1->next)
l1 = l1->next;
l1->next = l2;
return oldl1;
}
/*
* Convert postfix regular expression to NFA.
* Return start state.
*/
State*
post2nfa(char *postfix)
{
char *p;
Frag stack[1000], *stackp, e1, e2, e;
State *s;
// fprintf(stderr, "postfix: %sn", postfix);
if(postfix == NULL)
return NULL;
#define push(s) *stackp++ = s
#define pop() *--stackp
stackp = stack;
for(p=postfix; *p; p++){
switch(*p){
default:
s = state(*p, NULL, NULL);
push(frag(s, list1(&s->out)));
break;
case '.': /* catenate */
e2 = pop();
e1 = pop();
patch(e1.out, e2.start);
push(frag(e1.start, e2.out));
break;
case '|': /* alternate */
e2 = pop();
e1 = pop();
s = state(Split, e1.start, e2.start);
push(frag(s, append(e1.out, e2.out)));
break;
case '?': /* zero or one */
e = pop();
s = state(Split, e.start, NULL);
push(frag(s, append(e.out, list1(&s->out1))));
break;
case '*': /* zero or more */
e = pop();
s = state(Split, e.start, NULL);
patch(e.out, s);
push(frag(s, list1(&s->out1)));
break;
case '+': /* one or more */
e = pop();
s = state(Split, e.start, NULL);
patch(e.out, s);
push(frag(e.start, list1(&s->out1)));
break;
}
}
e = pop();
if(stackp != stack)
return NULL;
patch(e.out, &matchstate);
return e.start;
#undef pop
#undef push
}
typedef struct List List;
struct List
{
State **s;
int n;
};
List l1, l2;
static int listid;
void addstate(List*, State*);
void step(List*, int, List*);
/* Compute initial state list */
List*
startlist(State *start, List *l)
{
l->n = 0;
listid++;
addstate(l, start);
return l;
}
/* Check whether state list contains a match. */
int
ismatch(List *l)
{
int i;
for(i=0; i<l->n; i++)
if(l->s[i] == &matchstate)
return 1;
return 0;
}
/* Add s to l, following unlabeled arrows. */
void
addstate(List *l, State *s)
{
if(s == NULL || s->lastlist == listid)
return;
s->lastlist = listid;
if(s->c == Split){
/* follow unlabeled arrows */
addstate(l, s->out);
addstate(l, s->out1);
return;
}
l->s[l->n++] = s;
}
/*
* Step the NFA from the states in clist
* past the character c,
* to create next NFA state set nlist.
*/
void
step(List *clist, int c, List *nlist)
{
int i;
State *s;
listid++;
nlist->n = 0;
for(i=0; i<clist->n; i++){
s = clist->s[i];
if(s->c == c)
addstate(nlist, s->out);
}
}
/* Run NFA to determine whether it matches s. */
int
match(State *start, char *s)
{
int i, c;
List *clist, *nlist, *t;
clist = startlist(start, &l1);
nlist = &l2;
for(; *s; s++){
c = *s & 0xFF;
step(clist, c, nlist);
t = clist; clist = nlist; nlist = t; /* swap clist, nlist */
}
return ismatch(clist);
}
int
main(int argc, char **argv)
{
int i;
char *post;
State *start;
if(argc < 3){
fprintf(stderr, "usage: nfa regexp string...n");
return 1;
}
post = re2post(argv[1]);
if(post == NULL){
fprintf(stderr, "bad regexp %sn", argv[1]);
return 1;
}
start = post2nfa(post);
if(start == NULL){
fprintf(stderr, "error in post2nfa %sn", post);
return 1;
}
l1.s = malloc(nstate*sizeof l1.s[0]);
l2.s = malloc(nstate*sizeof l2.s[0]);
for(i=2; i<argc; i++)
if(match(start, argv[i]))
printf("%sn", argv[i]);
return 0;
}
/*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated
* documentation files (the "Software"), to deal in the
* Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute,
* sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall
* be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
* KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
* WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
* PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
* OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
2013 数模美赛(MCM) 一等奖论文 一篇
2016.1 链接已更新
其实就是自己组的啦~有需要的拿去看吧,还有很多需要完善的地方,拿了M奖也很是惊喜,哈哈~
Team #18836 The Ultimate Brownie Pan
B+树的一些资料,留着备用
近期数据库老师要求写一个B+树,还是要存储在磁盘上的,暂时收集到下列资料:
- 《图解B+树的插入和删除(一看就懂)》
- 《B+树 (1): 定义与基本操作》 插入那边可能有点问题,还在看,不知道是不是自己理解错了
- 课件:高级数据结构 可惜大二的时候高级数据结构课变成了外教的算法导论…这个东西是该好好学习下,200多页的ppt,里面有讲到B+树,挺详细
1023. Have Fun with Numbers (20)
Notice that the number 123456789 is a 9-digit number consisting exactly the numbers from 1 to 9, with no duplication. Double it we will obtain 246913578, which happens to be another 9-digit number consisting exactly the numbers from 1 to 9, only in a different permutation. Check to see the result if we double it again!
Now you are suppose to check if there are more numbers with this property. That is, double a given number with k digits, you are to tell if the resulting number consists of only a permutation of the digits in the original number.
Input Specification:
Each input file contains one test case. Each case contains one positive integer with no more than 20 digits.
Output Specification:
For each test case, first print in a line “Yes” if doubling the input number gives a number that consists of only a permutation of the digits in the original number, or “No” if not. Then in the next line, print the doubled number.
Sample Input:
1234567899
Sample Output:
Yes 2469135798
====================================
恩恩,having fun….
这道题的险恶用心在于..
int最大值 2147483647
longlong 最大值 9223372036854775807
都不满足20位的标准…因此需要自己手工做乘法计算~
其实乘法也是很好算的嘛~喵
还好时间给的充裕…
====================================
#includeusing namespace std; char digs_in[20]; int digs_out[30]; short old_nums[10]; short new_nums[10]; int main() { cin >> digs_in; //find ' ' int pos = 0; while(true) { if(digs_in[pos++] == ' ') break; } pos--; //手工做*2... int r = 0; int d = 0; int count = 0; while (pos--) { d = (int)digs_in[pos] - 0x30; //ASCII -> digit old_nums[d] ++; d = d << 1; //d*=2 d += r; r = d / 10; d = d % 10; digs_out[count++] = d; new_nums[d] ++; } if( r > 0) { //最高位 digs_out[count] = r; new_nums[r] ++; } else count --; bool flag = true; for(int i=0; i<10; i++) { if(old_nums[i] != new_nums[i]) { flag = false; break; } } if(flag) { cout << "Yes" << endl; } else { cout << "No" << endl; } for(int i=count; i>=0; i--) cout << digs_out[i]; return 0; }
linux环境下pthread链接报错的解决
本人对linux环境很不熟悉,今天做操作系统作业要在linux下用信号量以及pthread编程,使用codeblocks这个IDE,然后链接报错
/tmp/ccMNPEfl.o:在函数‘init_semaphores()’中:
source.cpp:(.text+0x212):对‘sem_init’未定义的引用
source.cpp:(.text+0x22e):对‘sem_init’未定义的引用
source.cpp:(.text+0x24a):对‘sem_init’未定义的引用
/tmp/ccMNPEfl.o:在函数‘ProducerProcess(void*)’中:
source.cpp:(.text+0x2a8):对‘sem_wait’未定义的引用
source.cpp:(.text+0x2b4):对‘sem_wait’未定义的引用
source.cpp:(.text+0x31c):对‘sem_post’未定义的引用
source.cpp:(.text+0x328):对‘sem_post’未定义的引用
/tmp/ccMNPEfl.o:在函数‘ConsumerProcess(void*)’中:
source.cpp:(.text+0x34c):对‘sem_wait’未定义的引用
source.cpp:(.text+0x358):对‘sem_wait’未定义的引用
source.cpp:(.text+0x3bd):对‘sem_post’未定义的引用
source.cpp:(.text+0x3c9):对‘sem_post’未定义的引用
/tmp/ccMNPEfl.o:在函数‘init_threads()’中:
source.cpp:(.text+0x417):对‘pthread_create’未定义的引用
source.cpp:(.text+0x431):对‘pthread_join’未定义的引用
source.cpp:(.text+0x45c):对‘pthread_create’未定义的引用
source.cpp:(.text+0x476):对‘pthread_join’未定义的引用
collect2: 错误: ld 返回 1
后来查了半天发现是链接器要加上参数 -pthread
记录一下,说不定以后又忘了呢。。~
摘自:http://www.china-pub.com 作者: 姚继锋 (2001-08-11 09:05:00)
关键字:Linux 多线程 Pthread semaphore
简单的多线程编程
Linux系统下的多线程遵循POSIX线程接口,称为pthread。编写Linux下的多线程程序,需要使用头文件pthread.h,连接时需要使用库libpthread.a。顺便说一下,Linux下pthread的实现是通过系统调用clone()来实现的。clone()是Linux所特有的系统调用,它的使用方式类似fork,关于clone()的详细情况,有兴趣的读者可以去查看有关文档说明。下面我们展示一个最简单的多线程程序 example1.c。
<pre>
/* example.c*/
#include <stdio.h>
#include <pthread.h>
void thread(void)
{
int i;
for( i = 0;i < 3; i++ )
printf(“This is a pthread.n”);
}
int main(void)
{
pthread_t id;
int i,ret;
ret = pthread_create( &id, NULL, (void *)thread, NULL );
if ( ret!=0 ) {
printf (“Create pthread error!n”);
exit (1);
}
for( i = 0; i < 3; i++ )
printf(“This is the main process.n”);
pthread_join(id,NULL);
return (0);
}
</pre>
我们编译此程序:
gcc example1.c -lpthread -o example1
运行example1,我们得到如下结果:
This is the main process.
This is a pthread.
This is the main process.
This is the main process.
This is a pthread.
This is a pthread.
再次运行,我们可能得到如下结果:
This is a pthread.
This is the main process.
This is a pthread.
This is the main process.
This is a pthread.
This is the main process.
前后两次结果不一样,这是两个线程争夺CPU资源的结果。上面的示例中,我们使用到了两个函数,
pthread_create和pthread_join,并声明了一个pthread_t型的变量。
pthread_t在头文件/usr/include/bits/pthreadtypes.h中定义:
typedef unsigned long int pthread_t;
它是一个线程的标识符。函数pthread_create用来创建一个线程,它的原型为:
extern int pthread_create __P ((pthread_t *__thread, __const pthread_attr_t *__attr,
void *(*__start_routine) (void *), void *__arg));
第一个参数为指向线程标识符的指针,第二个参数用来设置线程属性,第三个参数是线程运行函数的起始地址,最后一个参数是运行函数的参数。这里,我们的函数thread不需要参数,所以最后一个参数设为空指针。第二个参数我们也设为空指针,这样将生成默认属性的线程。对线程属性的设定和修改我们将在下一节阐述。当创建线程成功时,函数返回0,若不为0则说明创建线程失败,常见的错误返回代码为EAGAIN和EINVAL。前者表示系统限制创建新的线程,例如线程数目过多了;后者表示第二个参数代表的线程属性值非法。创建线程成功后,新创建的线程则运行参数三和参数四确定的函数,原来的线程则继续运行下一行代码。
函数pthread_join用来等待一个线程的结束。函数原型为:
extern int pthread_join __P ((pthread_t __th, void **__thread_return));
第一个参数为被等待的线程标识符,第二个参数为一个用户定义的指针,它可以用来存储被等待线程的返回值。这个函数是一个线程阻塞的函数,调用它的函数将一直等待到被等待的线程结束为止,当函数返回时,被等待线程的资源被收回。一个线程的结束有两种途径,一种是象我们上面的例子一样,函数结束了,调用它的线程也就结束了;另一种方式是通过函数pthread_exit来实现。它的函数原型为:
extern void pthread_exit __P ((void *__retval)) __attribute__ ((__noreturn__));
唯一的参数是函数的返回代码,只要pthread_join中的第二个参数thread_return不是NULL,这个值将被传递给 thread_return。最后要说明的是,一个线程不能被多个线程等待,否则第一个接收到信号的线程成功返回,其余调用pthread_join的线程则返回错误代码ESRCH。
信号量
信号量本质上是一个非负的整数计数器,它被用来控制对公共资源的访问。当公共资源增加时,调用函数sem_post()增加信号量。只有当信号量值大于0时,才能使用公共资源,使用后,函数sem_wait()减少信号量。函数sem_trywait()和函数pthread_ mutex_trylock()起同样的作用,它是函数sem_wait()的非阻塞版本。下面我们逐个介绍和信号量有关的一些函数,它们都在头文件 /usr/include/semaphore.h中定义。
信号量的数据类型为结构sem_t,它本质上是一个长整型的数。函数sem_init()用来初始化一个信号量。它的原型为:
extern int sem_init __P ((sem_t *__sem, int __pshared, unsigned int __value));
sem为指向信号量结构的一个指针;pshared不为0时此信号量在进程间共享,否则只能为当前进程的所有线程共享;value给出了信号量的初始值。
函数sem_post( sem_t *sem )用来增加信号量的值。当有线程阻塞在这个信号量上时,调用这个函数会使其中的一个线程不在阻塞,选择机制同样是由线程的调度策略决定的。
函数sem_wait( sem_t *sem )被用来阻塞当前线程直到信号量sem的值大于0,解除阻塞后将sem的值减一,表明公共资源经使用后减少。函数sem_trywait ( sem_t *sem )是函数sem_wait()的非阻塞版本,它直接将信号量sem的值减一。
函数sem_destroy(sem_t *sem)用来释放信号量sem。
下面我们来看一个使用信号量的例子。在这个例子中,一共有4个线程,其中两个线程负责从文件读取数据到公共的缓冲区,另两个线程从缓冲区读取数据作不同的处理(加和乘运算)。
/* File sem.c */
#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>
#define MAXSTACK 100
int stack[MAXSTACK][2];
int size = 0;
sem_t sem;
/* 从文件1.dat读取数据,每读一次,信号量加一*/
void ReadData1( void )
{
FILE *fp = fopen( “1.dat”, “r” );
while ( !feof( fp ) )
{
fscanf( fp, “%d %d”, &stack[size][0], &stack[size][1] );
sem_post( &sem );
++size;
}
fclose(fp);
}
/*从文件2.dat读取数据*/
void ReadData2( void )
{
FILE *fp=fopen(“2.dat”,”r”);
while ( !feof( fp ) )
{
fscanf(fp,”%d %d”,&stack[size][0],&stack[size][1]);
sem_post(&sem);
++size;
}
fclose(fp);
}
/*阻塞等待缓冲区有数据,读取数据后,释放空间,继续等待*/
void HandleData1( void )
{
while( 1 )
{
sem_wait( &sem );
printf( “Plus:%d+%d=%dn”, stack[size][0], stack[size][1],
stack[size][0]+stack[size][1] );
–size;
}
}
void HandleData2(void)
{
while ( 1 )
{
sem_wait( &sem );
printf( “Multiply:%d*%d=%dn”, stack[size][0],stack[size][1],
stack[size][0]*stack[size][1] );
–size;
}
}
int main(void)
{
pthread_t t1,t2,t3,t4;
sem_init( &sem, 0, 0 );
pthread_create( &t1, NULL, (void *)HandleData1, NULL);
pthread_create( &t2, NULL, (void *)HandleData2, NULL);
pthread_create( &t3, NULL, (void *)ReadData1, NULL);
pthread_create( &t4, NULL, (void *)ReadData2, NULL);
/* 防止程序过早退出,让它在此无限期等待*/
pthread_join( t1,NULL );
}
在Linux下,我们用命令gcc -lpthread sem.c -o sem生成可执行文件sem。 我们事先编辑好数据文件1.dat和2.dat,假设它们的内容分别为1 2 3 4 5 6 7 8 9 10和 -1 -2 -3 -4 -5 -6 -7 -8 -9 -10 ,我们运行sem,得到如下的结果:
Multiply:-1*-2=2
Plus:-1+-2=-3
Multiply:9*10=90
Plus:-9+-10=-19
Multiply:-7*-8=56
Plus:-5+-6=-11
Multiply:-3*-4=12
Plus:9+10=19
Plus:7+8=15
Plus:5+6=11
从中我们可以看出各个线程间的竞争关系。而数值并未按我们原先的顺序显示出来这是由于size这个数值被各个线程任意修改的缘故。这也往往是多线程编程要注意的问题。
本文来源:
http://www.chinaunix.net/old_jh/23/408225.html
陈皓
概述
——
什么是makefile?或许很多Winodws的程序员都不知道这个东西,因为那些Windows的IDE都为你做了这个工作,但我觉得要作一个好的和professional的程序员,makefile还是要懂。这就好像现在有这么多的HTML的编辑器,但如果你想成为一个专业人士,你还是要了解HTML的标识的含义。特别在Unix下的软件编译,你就不能不自己写makefile了,会不会写makefile,从一个侧面说明了一个人是否具备完成大型工程的能力。
因为,makefile关系到了整个工程的编译规则。一个工程中的源文件不计数,其按类型、功能、模块分别放在若干个目录中,makefile定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作,因为makefile就像一个Shell脚本一样,其中也可以执行操作系统的命令。
makefile带来的好处就是——“自动化编译”,一旦写好,只需要一个make命令,整个工程完全自动编译,极大的提高了软件开发的效率。make是一个命令工具,是一个解释makefile中指令的命令工具,一般来说,大多数的IDE都有这个命令,比如:Delphi的make,Visual C++的nmake,Linux下GNU的make。可见,makefile都成为了一种在工程方面的编译方法。
现在讲述如何写makefile的文章比较少,这是我想写这篇文章的原因。当然,不同产商的make各不相同,也有不同的语法,但其本质都是在“文件依赖性”上做文章,这里,我仅对GNU的make进行讲述,我的环境是RedHat Linux 8.0,make的版本是3.80。必竟,这个make是应用最为广泛的,也是用得最多的。而且其还是最遵循于IEEE 1003.2-1992 标准的(POSIX.2)。
在这篇文档中,将以C/C++的源码作为我们基础,所以必然涉及一些关于C/C++的编译的知识,相关于这方面的内容,还请各位查看相关的编译器的文档。这里所默认的编译器是UNIX下的GCC和CC。




