125: // необходимо, чтобы конструктор-копировщик и оператор соответствовали друг другу!
126: void Iterate(void (Part::*f)()const) const;
127: Part* Find(int & position, int PartNumber) const;
128: Part* GetFirst() const;
129: void Insert(Part *);
130: Part* operator[](int) const;
131: int GetCount() const { return itsCount;}
132: static PartsList& GetGlobalPartsList()
133: {
134: return GiobalPartsList;
135: }
136: private:
137: PartNode * pHead;
138: int itsCount;
139: static PartsList GiobalPartsList;
140: };
141:
142: PartsList PartsList::GlobalPartsList;
143:
144:
145: PartsList::PartsList():
146: pHead(0),
147: itsCount(0)
148: { }
149:
150: PartsList::~PartsList()
151: {
152: delete pHead;
153: }
154:
155: Part* PartsList::GetFirst() const
156: {
157: if (pHead)
158: return pHead->GetPart();
159: else
160: return NULL; // ловушка ошибок
161: }
162:
163: Part * PartsList::operator[](int offSet) const
164: {
165: PartNode* pNode = pHead;
166:
167: if (!pHead)
168: return NULL; // ловушка ошибок
169:
170: if (offSet > itsCount)
171: return NULL; // ошибка
172:
173: for (int i=0;i
174: pNode = pNode->GetNext();
175:
176: return pNode->GetPart();
177: }
178:
179: Part* PartsList::Find(
180: int & position,
181: int PartNumber) const
182: {
183: PartNode * pNode = 0;
184: for (pNode = pHead, position = 0;
185: pNode!=NULL;
186: pNode = pNode->GetNext(), position++)
187: {
188: if (pNode->GetPart()->GetPartNumber()== PartNumber)
189: break;
190: }
191: if (pNode == NULL)
192: return NULL;
193: else
194: return pNode->GetPart();
195: }
196:
197: void PartsList::Iterate(void (Part::*func)()const) const
198: {
199: if (!pHead)
200: return;
201: PartNode* pNode = pHead;
202: do
203: (pNode->GetPart()->*func)();
204: while (pNode = pNode->GetNext());
205: }
206:
207: void PartsList::Insert(Part* pPart)
208: {
209: PartNode * pNode = new PartNode(pPart);
210: PartNode * pCurrent - pHead;
211: PartNode * pNext = 0;
212:
213: int New = pPart->GetPartNumber();
214: int Next = 0;
215: itsCount++;
216:
217: if (!pHead)
218: {
219: pHead = pNode;
220: return;
221: }
222:
223: // если это значение меньше головного узла,
224: // то текущий узел становится головным
225: if (pHead->GetPart()->GetPartNumber()->New)
226: {
227: pNode->SetNext(pHead);
228: pHead = pNode;
229: return;
230: }
231:
232: for (;;)
233: {
234: // если нет следующего, вставляется текущий
235: if (!pCurrent->GetNext())
236: {
237: pCurrent->SetNext(pNode);
238: return;
239: }
240:
241: // если текущий больше предыдущего, но меньше следующего, то вставляем
242: // здесь. Иначе присваиваем значение указателя Next
243: pNext = pCurrent->GetNext();
244: Next = pNext->GetPart()->GetPartNumber();
245: if (Next > New)
246: {
247: pCurrent->SetNext(pNode);
248: pNode->SetNext(pNext);
249: return;
250: }
251: pCurrent = pNext;
252: }
253: }
254:
255:
256:
257: class PartsCatalog
258: {
259: public:
260: void Insert(Part *);
261: int Exists(int PartNumber);
262: Part * Get(int PartNumber);
263: operator+(const PartsCatalog &);
264: void ShowAll() { thePartsList.Iterate(Part::Display); }
265: private:
266: PartsList thePartsList;
267: };
268:
269: void PartsCatalog::Insert(Part * newPart)
270: {
271: int partNumber = newPart->GetPartNumber();
272: int offset;
273:
274: if (!thePartsList,Find(offset, partNumber))
275:
276: thePartsList.Insert(newPart);
277: else
278: {
279: cout << partNumber << " был ";
280: switch (offset)
281: {
282: case 0: cout << "first "; break;
283: case 1: cout << "second "; break;
284: case 2: cout << "third "; break;
285: default; cout << offset+1 << "th ";
286: }
287: cout << "entry. Rejected!\n";
288: }
289: }
290:
291: int PartsCatalog::Exists(int PartNumber)
292: {
293: int offset;
294: thePartsList.Find(offset,PartNumber);
295: return offset;
296: }
297:
298: Part * PartsCatalog::Get(int PartNumber)
299: {
300: int offset;
301: Part * thePart = thePartsList.Find(offset, PartNumber);
302: return thePart;
303: }
304:
305:
306: int main()
307: {
308: PartsCatalog pc;
309: Part * pPart = 0;
310: int PartNumber;
311: int value;
312: int choice;
313:
314: while (1)
315: {
316: cout << "(0)Quit (1)Car (2)Plane: ";
317: cin >> choice;
318:
319: if (!choice)
320: break;
321:
322: cout << "New PartNumber?: ";
323: cin >> PartNumber;
324:
325: if (choice == 1)
326: {
327: cout << "Model Year?: ";
328: cin >> value;
329: pPart = new CarPart(value,PartNumber);
330: }
331: else
332: {
333: cout << "Engine Number?: ";
334: cin >> value;
335: pPart = new AirPlanePart(value,PartNumber);
335: }
337: pc.Insart(pPart);
338: }
339: pc.ShowAli();
340: return 0;
341: }
Результат:
(0)Qult (1)Car (2)Plane: 1
New PartNumber?: 1234
Model Year?: 94
(0)Quit (1)Car (2)Plane: 1
New PartNumber?: 4434
Model Year?: 93
(0)Quit (1)Car (2)Plane: 1
New PartNumber?: 1234
Model Year?: 94
1234 was the first entry. Rejected!
(0)Quit (1)Car (2)Plane: 1
New PartNumber?: 2345
Model Year?: 93
(0)Quit (1)Car (2)Plane: 0
Part Number: 1234
Model Year: 94
Part Number: 2345
Model Year: 93
Part Number: 4434
Model Year: 93
Примечание: Некоторые компиляторы не смогут откомпилировать строку 264, хотя она вполне соответствует стандартам C++. Если ваш компилятор возразит против записи этой строки, замените ее строкой
264: void ShowAll() { thePartsList.Iterate(&Part::Display): }
(Обратите внимание на добавление амперсанта (знак &) перед Part:Display.) Если это сработает, свяжитесь с фирмой, поставившей вам этот компилятор, и поинтересуйтесь, где они его "откопали".
Анализ:В листинге 15.5 используются классы Part, PartNode и PartsList, с которыми вы уже познакомились при подведении итогов второй недели.
Читать дальше