programming language
Révision | f82455fb9478f929e27626b07c89ef6ae193ea82 (tree) |
---|---|
l'heure | 2020-11-22 21:53:44 |
Auteur | dhrname <dhrname@user...> |
Commiter | dhrname |
Add the insertBefore method
@@ -23,6 +23,8 @@ | ||
23 | 23 | |
24 | 24 | #include <iostream> |
25 | 25 | #include <string> |
26 | +#include <typeinfo> | |
27 | +#include <stdexcept> | |
26 | 28 | |
27 | 29 | /*Nodeの抽象クラス |
28 | 30 | * 5方向リンクのリスト |
@@ -31,13 +33,24 @@ class Node | ||
31 | 33 | { |
32 | 34 | public: |
33 | 35 | virtual Node* getParent() = 0; |
36 | + virtual void setParent(Node*) = 0; | |
37 | + | |
34 | 38 | virtual Node* getNext() = 0; |
39 | + virtual void setNext(Node*) = 0; | |
40 | + | |
35 | 41 | virtual Node* getPrev() = 0; |
42 | + virtual void setPrev(Node*) = 0; | |
43 | + | |
36 | 44 | virtual Node* getFirstChild() = 0; |
45 | + virtual void setFirstChild(Node*) = 0; | |
46 | + | |
37 | 47 | virtual Node* getLastChild() = 0; |
48 | + virtual void setLastChild(Node*) = 0; | |
49 | + | |
38 | 50 | virtual Node* removeChild(Node* const) = 0; |
39 | 51 | virtual Node* insertBefore(Node* const, Node* const) = 0; |
40 | 52 | virtual Node* appendChild(Node* const) = 0; |
53 | + | |
41 | 54 | virtual bool isNode() = 0; |
42 | 55 | }; |
43 | 56 |
@@ -45,11 +58,16 @@ public: | ||
45 | 58 | class EmptyNode: public Node |
46 | 59 | { |
47 | 60 | public: |
48 | - Node* getParent(){return this;}; | |
49 | - Node* getNext(){return this;}; | |
50 | - Node* getPrev(){return this;}; | |
51 | - Node* getFirstChild(){return this;}; | |
52 | - Node* getLastChild(){return this;}; | |
61 | + Node* getParent() {return this;}; | |
62 | + Node* getNext() {return this;}; | |
63 | + Node* getPrev() {return this;}; | |
64 | + Node* getFirstChild() {return this;}; | |
65 | + Node* getLastChild() {return this;}; | |
66 | + void setParent(Node* node){}; | |
67 | + void setNext(Node* node){}; | |
68 | + void setPrev(Node* node){}; | |
69 | + void setFirstChild(Node* node){}; | |
70 | + void setLastChild(Node* node){}; | |
53 | 71 | Node* removeChild(Node*){return this;}; |
54 | 72 | Node* insertBefore(Node*, Node*){return this;}; |
55 | 73 | Node* appendChild(Node*){return this;}; |
@@ -59,13 +77,13 @@ public: | ||
59 | 77 | } |
60 | 78 | }; |
61 | 79 | |
62 | -Node* const emptynode = new EmptyNode(); | |
80 | +EmptyNode* const emptynode = new EmptyNode(); | |
63 | 81 | |
64 | 82 | /*BaseNodeの基底クラス |
65 | 83 | * Node抽象クラスに対する内部実装*/ |
66 | 84 | class BaseNode: public EmptyNode |
67 | 85 | { |
68 | -private: | |
86 | +protected: | |
69 | 87 | Node* parentNode; |
70 | 88 | Node* nextSibling; |
71 | 89 | Node* previousSibling; |
@@ -83,46 +101,87 @@ public: | ||
83 | 101 | |
84 | 102 | virtual ~BaseNode(){} |
85 | 103 | |
86 | - virtual void throwArgumentError(Node* const node, const std::string& str); | |
87 | - virtual void setParent(Node* node); | |
88 | - virtual void setNext(Node* node); | |
89 | - virtual void setPrev(Node* node); | |
90 | - virtual void setFirstChild(Node* node); | |
91 | - virtual void setLastChild(Node* node); | |
104 | + virtual void throwNULLArgumentError(Node* const, const std::string&); | |
105 | + virtual void throwArgumentError(Node* const, const std::string&); | |
106 | + | |
107 | + virtual void setParent(Node*); | |
108 | + virtual void setNext(Node*); | |
109 | + virtual void setPrev(Node*); | |
110 | + virtual void setFirstChild(Node*); | |
111 | + virtual void setLastChild(Node*); | |
112 | + | |
92 | 113 | virtual Node* getParent(); |
93 | 114 | virtual Node* getNext(); |
94 | 115 | virtual Node* getPrev(); |
95 | 116 | virtual Node* getFirstChild(); |
96 | 117 | virtual Node* getLastChild(); |
118 | + | |
97 | 119 | virtual Node* removeChild(Node*); |
98 | 120 | virtual Node* insertBefore(Node*, Node*); |
99 | 121 | virtual Node* appendChild(Node*); |
100 | - virtual bool isNode() | |
122 | + | |
123 | + virtual bool isNode() const | |
101 | 124 | { |
102 | 125 | return true; |
103 | 126 | } |
104 | 127 | }; |
105 | 128 | |
106 | -inline void BaseNode::throwArgumentError(Node* const node, const std::string& str) | |
129 | +/*throwNULLArgumentError 関数 | |
130 | + * 引数のNULLチェックをして、nullptrだったら例外を投げる | |
131 | + * @param node 木構造の節 | |
132 | + * @param name 引数の例外が発生したメンバ関数名*/ | |
133 | +inline void BaseNode::throwNULLArgumentError(Node* const node, const std::string& name) | |
134 | +{ | |
135 | + if (nullptr == node) | |
136 | + { | |
137 | + /*バグの放置を防ぐため、例外を投げる前に、エラーを出力して報告*/ | |
138 | + std::cerr << "NULL Argument Error on the member " << name << std::endl; | |
139 | + throw std::invalid_argument("error!"); | |
140 | + } | |
141 | +} | |
142 | + | |
143 | +/*throwArgumentError 関数 | |
144 | + * 引数のチェックをして、nullptrか、emptynode(空ノード)だったら例外を投げる | |
145 | + * @param node 木構造の節 | |
146 | + * @param str 引数の例外が発生したメンバ関数名*/ | |
147 | +inline void BaseNode::throwArgumentError(Node* const node, const std::string& name) | |
107 | 148 | { |
108 | - /*例外を投げる前に、エラーを出力して報告*/ | |
109 | - std::cout << "Argument Error on the member " << str << std::endl; | |
110 | - throw; | |
149 | + this->throwNULLArgumentError(node, name); | |
150 | + if ( !node->isNode() ) | |
151 | + { | |
152 | + /*バグの放置を防ぐため、例外を投げる前に、エラーを出力して報告*/ | |
153 | + std::cerr << "Argument Error on the member " << name << std::endl; | |
154 | + throw std::invalid_argument("error!"); | |
155 | + } | |
111 | 156 | } |
112 | 157 | |
113 | -void BaseNode::setParent(Node* node){ | |
158 | +void BaseNode::setParent(Node* node) | |
159 | +{ | |
160 | + this->throwNULLArgumentError(node, "setParent"); | |
114 | 161 | this->parentNode = node; |
115 | 162 | } |
116 | -void BaseNode::setNext(Node* node){ | |
163 | + | |
164 | +void BaseNode::setNext(Node* node) | |
165 | +{ | |
166 | + this->throwNULLArgumentError(node, "setNext"); | |
117 | 167 | this->nextSibling = node; |
118 | 168 | } |
119 | -void BaseNode::setPrev(Node* node){ | |
169 | + | |
170 | +void BaseNode::setPrev(Node* node) | |
171 | +{ | |
172 | + this->throwNULLArgumentError(node, "setPrev"); | |
120 | 173 | this->previousSibling = node; |
121 | 174 | } |
122 | -void BaseNode::setFirstChild(Node* node){ | |
175 | + | |
176 | +void BaseNode::setFirstChild(Node* node) | |
177 | +{ | |
178 | + this->throwNULLArgumentError(node, "setFirstChild"); | |
123 | 179 | this->firstChild = node; |
124 | 180 | } |
125 | -void BaseNode::setLastChild(Node* node){ | |
181 | + | |
182 | +void BaseNode::setLastChild(Node* node) | |
183 | +{ | |
184 | + this->throwNULLArgumentError(node, "setLastChild"); | |
126 | 185 | this->lastChild = node; |
127 | 186 | } |
128 | 187 |
@@ -130,6 +189,7 @@ Node* BaseNode::getParent() | ||
130 | 189 | { |
131 | 190 | return this->parentNode; |
132 | 191 | } |
192 | + | |
133 | 193 | Node* BaseNode::getNext() |
134 | 194 | { |
135 | 195 | return this->nextSibling; |
@@ -146,14 +206,109 @@ Node* BaseNode::getLastChild() | ||
146 | 206 | { |
147 | 207 | return this->lastChild; |
148 | 208 | } |
149 | -Node* BaseNode::removeChild(Node* const node) | |
209 | + | |
210 | +/*removeChild メンバ関数 | |
211 | + *自分からchildノードを引き離して、子ノードとして扱わないようにさせる | |
212 | + *@param child 引き離される子ノード | |
213 | + *@return 引き離された子ノード | |
214 | + **/ | |
215 | +Node* BaseNode::removeChild(Node* const child) | |
150 | 216 | { |
151 | - this->throwArgumentError(node, "removeChild"); | |
152 | - return this->parentNode; | |
217 | + this->throwArgumentError(child, "removeChild"); | |
218 | + | |
219 | + child->setParent(emptynode); | |
220 | + | |
221 | + if (this->lastChild == child) | |
222 | + { | |
223 | + /*末子ノードがchildである場合は自分のlastChildメンバを書きかえておく*/ | |
224 | + this->setLastChild(child->getPrev()); | |
225 | + } | |
226 | + if (this->firstChild == child) | |
227 | + { | |
228 | + /*長子ノードがchildである場合は自分のfirstChildメンバを書きかえておく*/ | |
229 | + this->setFirstChild(child->getNext()); | |
230 | + } | |
231 | + | |
232 | + /*nodeが抜けた後、隣接ノードに関するメンバは書き換えておく*/ | |
233 | + if (child->getPrev()->isNode()) | |
234 | + { | |
235 | + child->getPrev()->setNext(child->getNext()); | |
236 | + } | |
237 | + if (child->getNext()->isNode()) | |
238 | + { | |
239 | + child->getNext()->setPrev(child->getPrev()); | |
240 | + } | |
241 | + | |
242 | + child->setNext(emptynode); | |
243 | + child->setPrev(emptynode); | |
244 | + | |
245 | + return child; | |
153 | 246 | } |
154 | 247 | Node* BaseNode::insertBefore(Node* const node, Node* const prev) |
155 | 248 | { |
156 | - return this->parentNode; | |
249 | + this.throwArgumentError(node, "insertBefore"); | |
250 | + | |
251 | + /*prevはemptynodeの可能性が含まれる*/ | |
252 | + this.throwNULLArgumentError(prev, "insertBefore"); | |
253 | + | |
254 | + /*祖先ノードの中に、今挿入しつつあるnodeと一致するものがあれば、参照エラー | |
255 | + * というのは、循環参照を引き起こすため*/ | |
256 | + Node* p = this; | |
257 | + | |
258 | + while (p.isNode()) | |
259 | + { | |
260 | + if (p == node) | |
261 | + { | |
262 | + throw std::invalid_argument("Reference error on the insertBefore"); | |
263 | + } | |
264 | + | |
265 | + p = p->getParent(p); | |
266 | + } | |
267 | + | |
268 | + Node* pnode = node->getParent(); | |
269 | + | |
270 | + if (pnode->isNode()) | |
271 | + { | |
272 | + /*nodeがすでに、他の枝に挿入されていた(子ノードであった)場合、引き離しておく*/ | |
273 | + pnode->removeChild(node); | |
274 | + } | |
275 | + | |
276 | + node->setParent(this); | |
277 | + | |
278 | + if (!prev->isNode()) | |
279 | + { | |
280 | + /*prevノードがemptynodeの場合、末子ノードとしてnodeが追加される | |
281 | + *末子ノードが存在するときは、そのノードのメンバも書きかえておく*/ | |
282 | + Node* lastChild = this->getLastChild(); | |
283 | + if (lastChild->isNode()) | |
284 | + { | |
285 | + lastChild->setNext(node); | |
286 | + node->setPrev(lastChild); | |
287 | + } | |
288 | + /*末子ノードとして挿入*/ | |
289 | + this->setLastChild(node); | |
290 | + } | |
291 | + else | |
292 | + { | |
293 | + Node* prevOfPrev = prev->getPrev(); | |
294 | + if (prevOfPrev->isNode()) | |
295 | + { | |
296 | + /*prevの隣接ノードのnextSiblingメンバを書きかえておく*/ | |
297 | + prevOfPrev->setNext(node); | |
298 | + } | |
299 | + node->setPrev(prevOfPrev); | |
300 | + prev->setPrev(node); | |
301 | + node->setNext(prev); | |
302 | + } | |
303 | + | |
304 | + if (this->getFirstChild() == prev) | |
305 | + { | |
306 | + /*長子ノードがprevの場合、firstChildメンバをnodeに書きかえておく | |
307 | + *これはprevがemptynodeの場合でも同様*/ | |
308 | + this->setFirstChild(node); | |
309 | + } | |
310 | + | |
311 | + return node; | |
157 | 312 | } |
158 | 313 | Node* BaseNode::appendChild(Node* const node) |
159 | 314 | { |
@@ -162,7 +317,14 @@ Node* BaseNode::appendChild(Node* const node) | ||
162 | 317 | |
163 | 318 | int main(int argc, char **argv) |
164 | 319 | { |
165 | - std::string str1 = "ABCD"; | |
320 | + std::string str1 = "ABC"; | |
166 | 321 | std::cout << "A" << str1 << std::endl; |
322 | + try | |
323 | + { | |
324 | + } | |
325 | + catch(std::invalid_argument e) | |
326 | + { | |
327 | + } | |
328 | + delete emptynode; | |
167 | 329 | return 0; |
168 | 330 | } |