2012-11-10 37 views
1

使用了各种搜索引擎(以及美妙的计算器数据库)后,我发现了一些类似的情况,但它们要么复杂得多,要么不像我想要的那么复杂完成。对于使用模板的循环链接列表

C++ List Looping Link Error Using Templates C++:Linked List Ordering Pointer Address Does Not Change In A Link List

我想带链接列表和节点模板的工作进行保存和打印非标准类对象(在这种情况下,分类联系人的集合)。特别是,我想从具有不同类别的一组对象中打印出多个具有相同类别的对象。按类别打印时,我将一个子对象tmpCategory(=“business”)与分类联系人的类别部分进行比较。

但如何提取这些数据在int main()中进行比较?

这是我在想什么。我在LinkList.tem中创建了一个GetItem成员函数。这将初始化指针游标,然后运行For循环,直到函数输入与迭代数相匹配。在这一点上,GetItem使用(cursor - > data)返回对象类型。

template <class Type> 
Type LinkList<Type>::GetItem(int itemNumber) const 
{ 
    Node<Type>* cursor = NULL; 

    for(cursor = first; 
     cursor != NULL; 
     cursor = (cursor -> next)) 
    { 
     for(int i = 0; i < used; i++) 
     { 
      if(itemNumber == i) 
      { 
       return(cursor -> data); 
      } 
     } 
    } 
} 

这里是int main()进来的地方。我将比较对象tmpCategory设置为某个值(在本例中为“Business”)。然后,我运行一个For循环,其循环次数等于我拥有的节点数(由函数GetUsed()确定)。在该循环中,我使用当前的迭代编号调用GetItem。理论上,这将让int主循环从LinkList.tem返回相应的节点。从那里,我从该节点的数据(当前工作)中的对象中调用该类别,并将其与tmpCategory进行比较。如果有匹配,循环将打印出整个Node的数据对象。

tmpCategory = "Business"; 

for(int i = 0; i < myCategorizedContact.GetUsed(); i++) 
{ 
    if(myCategorizedContact.GetItem(i).getCategory() == tmpCategory) 
     cout << myCategorizedContact.GetItem(i); 
} 

问题是,当前设置(虽然它运行),它什么也没有返回。经过进一步测试(cout < < myCategorizedContact.GetItem(i).getCategory()),我发现它只是一遍又一遍地打印出第一个节点的类别。我希望整体方案针对每个节点进行评估并打印出匹配的数据,而不仅仅是吐出同一个节点。

任何想法/建议,非常感谢。

回答

0

请看看这个非常小心:

template <class Type> 
Type LinkList<Type>::GetItem(int itemNumber) const 
{ 
    Node<Type>* cursor = NULL; 

    // loop over all items in the linked list  
    for(cursor = first; 
     cursor != NULL; 
     cursor = (cursor -> next)) 
    { 
     // for each item in the linked list, run a for-loop 
     // counter from 0 to (used-1). 
     for(int i = 0; i < used; i++) 
     { 
      // if the passed in itemNumber matches 'i' anytime 
      // before we reach the end of the for-loop, return 
      // whatever the current cursor is. 
      if(itemNumber == i) 
      { 
       return(cursor -> data); 
      } 
     } 
    } 
} 

你不走光标向下列表itemNumber倍。第一项cursor参考文献将启动内循环。循环索引达到itemNumber的那一刻你会返回。 如果链表至少有itemNumber列表中的项目,则永远不会向前移动光标。。事实上,它们中的两个(cursor和itemNumber)在你实现这个函数时完全不相关。而要真正增加的讽刺,因为usedcursor是完全无关的,如果used是有史以来itemNumber,它永远是这样,因为used不改变时前进cursor通过外循环。因此cursor最终变为NULL,并且此函数的结果未定义(无返回值)。总之,按照书面方式,您总是会返回第一个项目(如果itemNumber < used),或者由于您没有返回值,将返回未定义的行为。

我相信你需要这样的东西,而不是执行以下操作:

template< class Type > 
Type LinkList<Type>::GetItem(int itemNumber) const 
{ 
    const Node<Type>* cursor = first; 
    while (cursor && itemNumber-- > 0) 
     cursor = cursor->next; 

    if (cursor) 
     return cursor->data; 

    // note: this is here because you're definition is to return 
    // an item COPY. This case would be better off returning a 
    // `const Type*` instead, which would at least allow you to 
    // communicate to the caller that there was no item at the 
    // proposed index (because the list is undersized) and return 
    // NULL, which the caller could check. 
    return Type(); 
} 
+0

这是当你编写过深夜发生了什么。我很担心连接和比较int main中的函数输出,我忘记了真正考虑游标和输入itemNumber之间的关系。猜猜昨天晚上我刚刚在大脑上发现了For循环。再次感谢。 –

+0

@DanteoftheInferno没有开玩笑。多次走过那条路。认真考虑我在提案中提到的关于返回指向该项目的指针,以及调用者检查它是否为NULL。或者,你可以让它抛出一个OO范围的异常,并改变函数返回一个const Type&。无论哪种方式,除非您真的想要做什么,否则不要复印。对于用作Type的复杂对象,它可能会非常昂贵。 – WhozCraig