其实到了这个层次的lua语法(用一个类去实现另一个类),我已经不是太了解了,Programming in lua中也没有出现类似的语法,只简单的提到了怎么去New,书中是用这种方式去实现继承的。第19行的语法纯粹是自己摸索出来的,一开始用self:Size(),结果并没有从CList中去找,而是陷入了纯粹的递推自身调用。
1 g='hi~' 2 local g='hello!' 3 for i=1,2do 4 g = g .. '1' 5 print(g) 6 end 7 print(g)
输出:
hello!1
hello!11
hello!11
证明内部变量g的使用,实际是用了外部的变量g
最后来个复杂点的例子:
test5:
1 g='hi~' 2 local g='hello!' 3 for i=1,2do 4 print(x) 5 x = x and x .. '1'or g .. '1' 6 print(x) 7 local x = x .. '1' 8 print(x) 9 local x = x .. '1' 10 print(x) 11 end 12 print(x)
1 g
= {} 2 for i=1,2do 3 io.write("global
g:") 4 print(g) 5 local g = {} 6 io.write("first
local g:") 7 print(g) 8 local g = {} 9 io.write("second
local g:") 10 print(g) 11 end 12 print(g)
1 #!/usr/bin/env lua 2 3 g = '1' 4 for i=1,2do 5 g = g .. '2' 6 local g = '3' 7 local g = g .. '4' 8 g = g .. '5' 9 local i = 1 10 whiletruedo 11 local name,value = debug.getlocal(1,i) 12 ifnot name then 13 break 14 end 15 16 print(name, value) 17 i
= i + 1 18 end 19 end
这里想提出的一点就是lua中实在是没有一个可用的debug工具,注意我的措辞,是连一个可用的都没有,更别提好用的了。相对而言C++有VS+gdb,python用pydb,bash有bashdb,而lua什么都没有!lua for windows的那个scite别提多不好用了,clidebug,xdblua, RemDebug等等我都用过,甚至官网提到的几个IDE我都试用了一下,通通的不能用,可能是因为lua升级了的原因(记得scite在原来是可用的),郁闷死我了。作为一个两百多行的list代码,没有一个可用的调试工具,简直就是噩梦(也许没有那么夸张,但是的确浪费了我很多本来简单调试就可以发下你的问题),唉。。。。。在没有好用的lua调试工具之前,我甚至都有点不想给自己找罪受了。再也不写太多的lua代码了。最多在小程序中用print和assert勉强写写吧。其实感觉lua本身对于调试的支持是很到位的了,为什么却没有好用的工具呢?唉。。。。。。。。。。这就是普及的好处了。。。。。真有时间,哥们自己DIY一个用用算了。
1 #!/usr/bin/env lua 2 3 --
require "std" 4 5 --
Node prototype 6 CNode = {} 7 function CNode:New(data,
prev, next) 8 local o = {} 9 o.data
= data 10 o.prev =
prev 11 o.next = next 12 o.type = "CNode" 13 setmetatable(o, self) 14 self.__index
= self 15 return o 16 end 17 18 --
iterator of list prototype like in C++ 19 CListIterator = {} 20 function CListIterator:New(a) 21 assert(a ~= niland 22 type(a) == "table"and 23 a.type ~= niland 24 ((a.type == "CList") or (a.type == "CNode")), 25 "Argument to new a CListIterator must be a CList
object or a CNode object") 26 27 local o = {} 28 -- give it a type name 29 o.type = "CListIterator" 30 31 -- if a is a CList object then create a begin iterator for
the object 32 -- if a is a CNode object then return a iterator point to
the node 33 if a.type == "CList"then 34 o.pos
= a.head.next 35 elseif a.type == "CNode"then 36 o.pos
= a 37 end 38 39 setmetatable(o, self) 40 self.__index
= self 41 return o 42 end 43 44 function CListIterator:IsEnd() 45 returnnot self.pos.data 46 end 47 48 function CListIterator:Cur() 49 return self.pos 50 end 51 52 function CListIterator:MoveNext() 53 self.pos =
self.pos.next 54 return self 55 end 56 57 function CListIterator:MovePrev() 58 self.pos =
self.pos.prev 59 return self 60 end 61 62 -- List
prototype 63 CList = {} 64 function CList:CreateIterator() 65 return CListIterator:New(self) 66 end 67 68 function CList:New() 69 local o = {} 70 o.head =
CNode:New() 71 o.head.prev
= o.head 72 o.head.next = o.head 73 74 -- give it a type def 75 o.type = "CList" 76 setmetatable(o, self) 77 self.__index
= self 78 return o 79 end 80 81 function CList:Insert(it,
data) 82 assert(it ~= nil, "Must pointer where to Insert") 83 assert(type(it) == "table", "Fisrt
Argument must be a CListIterator(now it even not a table)") 84 assert(type ~= nil, "Fisrt
Argument must be a CListIterator(now it.type == nil)") 85 assert(it.type == "CListIterator", "Fisrt Argument must be a CListIterator") 86 87 local iter = CListIterator:New(self) 88 local node = CNode:New(data, it.pos.prev,
it.pos) 89 it.pos.prev.next = node 90 it.pos.prev
= node 91 return CListIterator:New(node) 92 end 93 94 function CList:Begin() 95 return self:CreateIterator() 96 end 97 98 function CList:End() 99 return CListIterator:New(self.head) 100 end 101 102 103 function CList:PushFront(data) 104 self:Insert(self:Begin(),
data) 105 end 106 107 function CList:PushBack(data) 108 self:Insert(self:End(),
data) 109 end 110 111 function CList:IsEmpty() 112 return self:Begin().pos == self:End().pos 113 end 114 115 function CList:Erase(it) 116 assert(not it.data, "you can't erase the head") 117 it.pos.prev.next = it.pos.next 118 it.pos.next.prev = it.pos.prev 119 it = nil 120 end 121 122 function CList:PopFront() 123 assert(not self:IsEmpty(), "Can't PopFront to a Empty list") 124 self:Erase(self:Begin()) 125 end 126 127 function CList:PopBack() 128 assert(not self:IsEmpty(), "Can't PopBack to a Empty list") 129 self:Erase(self:End():MovePrev()) 130 end 131 132 function CList:Clear() 133 whilenot self:IsEmpty() do 134 self:Erase(self:Begin()) 135 end 136 end 137 138 -- redefine
global print to support the CList 139 p = _G.print 140 functionprint(o) 141 if o ~= nilandtype(o)
== "table"and 142 o.type ~= niland o.type == "CList"then 143 -- iterate like in C++ using CList and CListIterator feature 144 local it = o:CreateIterator() 145 whilenot it:IsEnd() do 146 io.write(it:Cur().data) 147 io.write(" ") 148 it:MoveNext() 149 end 150 io.write("/n") 151 else 152 p(o) 153 end 154 end 155 156 -- test
PushFront 157 print("/ntest: test PushFront and PopFront") 158 newlist = CList:New() 159 newlist:PushFront(10) 160 print(newlist) 161 newlist:PushFront(20) 162 print(newlist) 163 newlist:PushFront(30) 164 print(newlist) 165 newlist:PopFront() 166 print(newlist) 167 it = newlist:CreateIterator() 168 newlist:Erase(it) 169 print(newlist) 170 newlist:Clear() 171 print(newlist) 172 173 174 -- test
PushBack 175 print("/ntest: test PushBack and popBack") 176 newlist = CList:New() 177 newlist:PushBack(10) 178 print(newlist) 179 newlist:PushBack(20) 180 print(newlist) 181 newlist:PushBack(30) 182 print(newlist) 183 newlist:PopBack() 184 print(newlist) 185 newlist:PopFront() 186 print(newlist) 187 188 189 -- test: insert
at begin 190 print("/ntest: insert at begin ") 191 newlist = CList:New() 192 it = newlist:CreateIterator() 193 iter = newlist:Insert(it, 10); 194 io.write("cur iterator:" .. tostring(it.pos.data) .. "
return iterator:" .. tostring(iter.pos.data)
.. "/n") 195 print(newlist) 196 iter = newlist:Insert(it, 20); 197 io.write("cur iterator:" .. tostring(it.pos.data) .. "
return iterator:" .. tostring(iter.pos.data)
.. "/n") 198 print(newlist) 199 iter = newlist:Insert(it, 30); 200 io.write("cur iterator:" .. tostring(it.pos.data) .. "
return iterator:" .. tostring(iter.pos.data)
.. "/n") 201 print(newlist) 202 203 -- test: insert
at back 204 print("/ntest: insert at back") 205 newlist = CList:New() 206 it = newlist:CreateIterator() 207 it = newlist:Insert(it, 10); 208 io.write("cur iterator:" .. tostring(it.pos.data).."/n") 209 it = newlist:Insert(it, 20); 210 io.write("cur iterator:" .. tostring(it.pos.data).."/n") 211 it = newlist:Insert(it, 30); 212 io.write("cur iterator:" .. tostring(it.pos.data).."/n") 213 print(newlist) 214 215 -- iterate like
in C++ 216 print("/niterate like in C++") 217 it = newlist:CreateIterator() 218 whilenot it:IsEnd() do 219 io.write(it:Cur().data .. "
") 220 it:MoveNext() 221 end 222 print("/n") 223 224 -- closure list
iterator to iterate 225 print("/nclosure list iterator to iterate") 226 function list_iter(list) 227 local cur = list.head 228 returnfunction() 229 if cur.next.data
~= nilthen 230 cur
= cur.next 231 return cur.data 232 end 233 end 234 end 235 236 for v in list_iter(newlist) do 237 io.write(v .. "
") 238 end 239 240
--《数据结构b与算法分析c++描述》 Mark Allen Weiss著人民邮电大学出版中文版第78-81面,堆栈的应用(1) 队列(queue)的链表(list)实现及循环数组(circular array) C++实现,需要注意的是,仅仅为了说明问题,没有详细探究代码的健壮,比如,我没有加入错误检测,这点在循环数组的实现是非常容易出现的。并且为了说明问题,我用了一个很小的数组来实现,以完成真正的从尾部到头部的跳转。
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <stack> 4 #include <string> 5 #include <iostream> 6 #include <sstream> 7 #include "ExprComputer.h" 8 usingnamespace std; 9 10 int main(int argc, char*
argv[]) 11 { 12 CExprComputer
loExprComputer; 13 // all these below can work right,comment is same as the
content 'couted'. 14 stringstream lss; 15 lss << "1 + 2 * 3 ="; 16 17 cout <<"test trans stringstream in and cout." <<endl; 18 loExprComputer.TransInfix2Postfix(lss,
cout); 19 20 cout <<"test trans cin and cout." <<endl; 21 loExprComputer.TransInfix2Postfix(cin,
cout); 22 23 stringstream
lss2; 24 cout <<"test trans cin and stringstream out." <<endl; 25 loExprComputer.TransInfix2Postfix(cin,
lss2); 26 cout
<<lss2.str() <<endl; 27 28 lss.seekg(0); 29 cout <<"test stringstream in computeInfix." <<endl; 30 cout
<<lss.str(); 31 cout
<<loExprComputer.ComputeInfix(lss) <<endl; 32 33 cout <<"test cin in computeInfix." <<endl; 34 cout
<<loExprComputer.ComputeInfix(cin) <<endl; 35 36 stringstream
lssPostfix; 37 lssPostfix
<< "1 2 3 * + ="; 38 cout <<"test stringstream in ComputePostfix." <<endl; 39 cout
<<lssPostfix.str(); 40 cout
<<loExprComputer.ComputePostfix(lssPostfix) <<endl; 41 42 cout <<"test cin in ComputePostfix." <<endl; 43 cout
<<loExprComputer.ComputePostfix(cin) <<endl; 44 45 cout <<"Test completed." <<endl; 46 exit(0); 47 } 48
ExprComputer头文件:
1 #ifndef __EXPR_COMPUTE_H__ 2 #define
__EXPR_COMPUTE_H__ 3 #include <iostream> 4 #include <sstream> 5 #include <stack> 6 usingnamespace std; 7 8 // argument
to input 9 #define
_IN_ 10 11 // argument to
output 12 #define _OUT_ 13 14 class CExprComputer 15 { 16 public: 17 int ComputeInfix(_IN_ istream&
aisExpr); 18 int ComputePostfix(_IN_ istream&
aisExpr); 19 20 // Transform a infix expression to Postfix expression 21 int TransInfix2Postfix(_IN_ istream&
aisInfix, 22 _OUT_
ostream& aosPostfix); 23 24 private: 25 // Stack should be empty,Dump the information still in Stack
and exit 26 void DumpStack(); 27 28 // Output all information still in Stack 29 void OutputStack(); 30 31 // Make sure Stack is not empty when it should not. 32 void CheckStack(); 33 34 // I don't know why Stack operator is so few.And why I need
to 35 // clear the Stack in this example? GOD knows. 36 void ClearStack(); 37 38 // Read a int or a operator from a stream 39 bool ReadStream(_IN_ istream&
aisExpr, _OUT_ int&
aiReaded, _OUT_ bool&
abIsChar); 40 41 // Process a Operator 42 void ProcessOperator(char ac, _OUT_ ostream& aosPostfix); 43 44 void ComputeOperator(char ac); 45 46 stack<int> miSta; 47 }; 48 49 50 51 52 53 #endif 54