免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 10904 | 回复: 13
打印 上一主题 下一主题

关于list容器的remove() [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2007-08-13 10:16 |只看该作者 |倒序浏览
main()
{

        char* as = "aaaaaa";
        char* bs = "bbbbbb";
        char* cs  = "aaaaaa";

        list<char*> S;
        list<char*>::iterator j;
        S.push_back(as);
        S.push_back(bs);
        S.push_back(cs);

        for(j=S.begin(); j != S.end(); ++j) cout << *j << " ";
        cout << endl;

        S.remove("aaaaaa");
        for(j=S.begin(); j != S.end(); ++j) cout << *j << " ";
        cout << endl;

   return 0;
}
看来sgi中版本的list的remove()是这样实现的
void list<T>::remove(const T& value)
{
    iterator first = begin();
    iterator last = end();
    while (first != last)
    {
                iterator next = ++first;
                if (*first == value) erase(first);
                first = next;
        }
}
我的问题是:push_back()推到container中的是字符串地址, 当删除container中的某个element时, 在remove中使用*first来判断是否等于value, *first返回的是iterator所指node的data, 此时的data是字符串地址,怎么和remove()中的实参使用等号进行比较呢?

[ 本帖最后由 SybaseLU 于 2007-8-13 10:24 编辑 ]

论坛徽章:
0
2 [报告]
发表于 2007-08-13 10:43 |只看该作者
用remove_if

论坛徽章:
0
3 [报告]
发表于 2007-08-13 11:15 |只看该作者
从代码来看==应该是重载了的,看==的重载代码

论坛徽章:
0
4 [报告]
发表于 2007-08-13 11:42 |只看该作者
不应该是重载==,因为list的迭代器iterator的重载的*代码如下
  1. return node->data;
复制代码

除非node.data是一个class,在这个class中重载了==【这样调用void operator==(value) { ... }】, 而现在我的element是char*字符串地址,返回的就是一个普通的字符串地址,如何重载==?

论坛徽章:
0
5 [报告]
发表于 2007-08-13 12:06 |只看该作者
那就不知道了,期待高人回答~

论坛徽章:
0
6 [报告]
发表于 2007-08-13 16:59 |只看该作者
本来list通常放string的。
如果用char*,当然没法用remove

变通一下可以用remove_if

  1. #include <iostream>
  2. #include <fstream>
  3. #include <list>
  4. #include <iterator>
  5. #include <functional>
  6. #include <cstring>

  7. using namespace std;

  8. int main(void)
  9. {
  10.         char *ss[] = {"aaaa", "bbbb", "cccc"};
  11.         list<char*> S(ss, ss+sizeof(ss)/sizeof(*ss));
  12.         S.remove_if(bind2nd(not2(ptr_fun(strcmp)), "aaaa"));
  13.         copy(S.begin(), S.end(), ostream_iterator<char*>(cout, "\n"));
  14.         return 0;
  15. }
复制代码

论坛徽章:
0
7 [报告]
发表于 2007-08-13 17:13 |只看该作者
目的并不是为了使用标准的STL库,而是在为了Linux/Embeded系统中动态的存放需要的各种类型数据,所以自己定制一个tiny STL list库,代码如下:

节点:

  1. #include <stdlib.h>
  2. #include <stdio.h>

  3. /* list's node implementation */
  4. template<class T>
  5. struct _list_node {
  6.         struct _list_node *prev;
  7.         struct _list_node *next;
  8.         T        data;
  9. };
复制代码

迭代器:

  1. /* iterator implementation */
  2. template<class T>
  3. struct        _list_iterator {
  4.         typedef _list_node<T> NODE;
  5.         typedef _list_iterator<T> self;
  6.        
  7.         /* the member node can be  used kept down the NODE's address */
  8.         NODE *node;
  9.        
  10.         self& operator = (const self& x)
  11.         {
  12.                 if (node == x.node)
  13.                         return *this;
  14.                 node = x.node;
  15.                 node->data = x.node->data;
  16.                 node->next = x.node->next;

  17.                 /* as for  iterator, it's address never be altered or midified */
  18.                 return *this;
  19.         }
  20.         bool operator != (const self& x) const
  21.         {
  22.                 return node != x.node;       
  23.         }
  24.         bool operator == (const self& x) const
  25.         {
  26.                 return node == x.node;       
  27.         }

  28.         self& operator++()
  29.         {
  30.                 node = node->next;
  31.                 return *this;
  32.         }
  33.        
  34.         self operator++(int)
  35.         {
  36.                 self tmp = *this;
  37.                 node = node.next;
  38.                 return tmp;
  39.         }
  40.         T& operator*() const
  41.         {
  42.                 return node->data;
  43.         }       
  44. };
复制代码


链表:

  1. template<class T>
  2. class AList
  3. {
  4. public:
  5.           AList();
  6.           ~AList() {}
  7.         typedef _list_node<T> NODE;
  8.         typedef _list_iterator<T> iterator;
  9.        
  10.           void push_back(const T value);
  11.         void pussh_front(const T value);
  12.        /* Note that! pop_back not mean remove element, just pop element what I need*/
  13.           const T  pop_back();       
  14.         const T  pop_front();
  15.         void remove(const T value);
  16.         int  eof() const { return !m_index; }
  17.         void erase(iterator position);
  18.         int  size() {return m_size; }
  19.         void destroy();
  20.         iterator begin() const { return start; }
  21.         iterator end() const { return finish; }

  22. private:
  23.           iterator start;
  24.           iterator finish;
  25.         iterator m_prev;
  26.         iterator m_now;

  27.         NODE        *m_headnode;
  28.         NODE         *m_tailnode;
  29.         int                m_index;
  30.         int         m_size;
  31. };



  32. template<class T>
  33. AList<T>::AList()
  34. {
  35.         m_headnode = new NODE();  
  36.         if (m_headnode == NULL)
  37.         {
  38.                     return;
  39.         }
  40.         m_headnode->next = NULL;  
  41.         m_tailnode = m_headnode;

  42.         start.node = m_headnode;
  43.         finish.node = m_tailnode;
  44.         m_index = 0;
  45.         m_size = 0;
  46. }

  47. template<class T>
  48. void AList<T>::push_back(const T value)
  49. {
  50.             NODE *element =  new NODE();
  51.             if (element == NULL)
  52.             {
  53.                 return;
  54.             }
  55.             element->data = value;
  56.         element->next = m_headnode;
  57.         m_headnode = element;
  58.         start.node = m_headnode;
  59.         m_index++;
  60.         m_size++;
  61. }

  62. template<class T>
  63. const T AList<T>::pop_back()
  64. {
  65.         if (m_index == size())
  66.         {
  67.                 m_now = begin();
  68.                 m_index--;
  69.                 return m_now.node->data;
  70.         }
  71.         else
  72.         {
  73.                 if (!eof())
  74.                 {
  75.                         ++m_now;
  76.                         m_index--;
  77.                         return m_now.node->data;
  78.                 }
  79.         }

  80. }

  81. template<class T>
  82. void AList<T>::remove(const T value)
  83. {
  84.         iterator first = begin();
  85.         iterator last = end();
  86.         m_prev = first;
  87.         while (first != last)
  88.         {
  89.                 iterator next = first;
  90.                 ++next;
  91.                 if (*first == value)
  92.                         erase(first);
  93.                 else
  94.                         m_prev = first;
  95.                 first = next;
  96.         }
  97. }

  98. template<class T>
  99. void AList<T>::erase(iterator position)
  100. {
  101.         if (position == start)
  102.         {
  103.                 start = position;
  104.                 ++start;
  105.                 delete position.node;
  106.         } else
  107.         {
  108.                 m_prev.node->next = position.node->next;
  109.                 delete position.node;
  110.         }
  111.         m_size--;
  112.         m_index = m_size;                       
  113. }       

  114. template<class T>
  115. void AList<T>::destroy()
  116. {
  117.           NODE *p = NULL;
  118.           while (m_headnode->next != NULL )
  119.           {
  120.                 p = m_headnode->next;
  121.                 m_headnode = m_headnode->next;       
  122.                 delete (p);
  123.           }
  124.         delete m_headnode;
  125. }

复制代码


测试:


  1. typedef AList<char*>         strLoader;
  2. typedef AList<char*>::iterator strIte;
  3. strLoader x;
  4. strIte          xi;

  5. typedef AList<int>        intLoader;
  6. typedef AList<int>::iterator intIte;
  7. intLoader y;
  8. intIte          yi;

  9. typedef AList<AString>        asLoader;
  10. typedef AList<AString>::iterator asIte;
  11. asLoader z;
  12. asIte          zi;


  13. typedef AList<DataDirectHeadend> lHeadend;
  14. typedef AList<DataDirectHeadend>::iterator iteHeadend;
  15. lHeadend HeadendLoader;
  16. iteHeadend ite;

  17. int
  18. main(int argc, char** argv)
  19. {
  20.             DataDirectHeadend headend;
  21.             sprintf(headend.zipcode, "%s", "510010");
  22.             sprintf(headend.headendname, "%s", "GZTV");
  23.             headend.channels  = 64;

  24.         for (int j=0; j<5; j++)
  25.         {
  26.                     headend.headendid = j;
  27.                 HeadendLoader.push_back(headend);
  28.         }
  29.         for (ite = HeadendLoader.begin(); ite != HeadendLoader.end(); ++ite)
  30.         {
  31.                 printf("zipcode:%s,headendid:%d,headendname:%s,channels:%d\n",\
  32.                                         (*ite.node).data.zipcode, \
  33.                                         (*ite.node).data.headendid, \
  34.                                         (*ite.node).data.headendname, \
  35.                                         (*ite.node).data.channels);
  36.         }

  37.         printf("===========headend==============\n");
  38.         char context[][10] = {
  39.                 "aaaaaa",
  40.                 "bbbbbb",
  41.                 "aaaaaa",
  42.                 "cccccc",
  43.                 "dddddd"
  44.         };

  45.         for (int i=0; i<5; i++)
  46.         {
  47.                 x.push_back(context[i]);
  48.         }

  49.         for (xi = x.begin(); xi != x.end(); ++xi)
  50.         {
  51.                 printf("strIte:%s\n", (*xi.node).data);
  52.         }
  53.         x.remove("dddddd");
  54.         while (1)
  55.         {
  56.                 if (!x.eof())
  57.                         printf("pop:%s\n", x.pop_back());
  58.                 else {
  59.                         printf("Is empty\n");
  60.                         break;
  61.                 }
  62.         }       

  63.         printf("==========char*==============\n");
  64.         for (int k=0; k<3; k++)
  65.                 y.push_back(k);

  66.         for (yi = y.begin(); yi != y.end(); ++yi)
  67.                 printf("intIte:%d\n", (*yi.node).data);

  68.         y.remove(1);
  69.         while (1)
  70.         {       
  71.                 if (!y.eof())
  72.                         printf("pop:%d\n", y.pop_back());
  73.                 else {
  74.                         printf("Is empty\n");
  75.                         break;
  76.                 }
  77.         }

  78.         printf("==========int=============\n");
  79.         char context2[10];
  80.         for (int m=0; m<5; m++)
  81.         {
  82.                 sprintf(context2, "%d.mp3", m);
  83.                 AString as(context2);
  84.                 z.push_back(as);
  85.         }

  86.         for (zi = z.begin(); zi != z.end(); ++zi)
  87.                 printf("asIte:%s\n", (*zi.node).data.c_str());

  88.         #if 0
  89.         while (1)
  90.         {       
  91.                 if (!z.eof())
  92.                         printf("pop:%s\n", (z.pop_back()).c_str());
  93.                 else {
  94.                         printf("Is empty\n");
  95.                         break;
  96.                 }
  97.         }
  98.         #endif



  99.            exit(0);
  100. }
复制代码


其他都可以,除了char*类型无法正确匹配.

[ 本帖最后由 SybaseLU 于 2007-8-13 17:18 编辑 ]

论坛徽章:
0
8 [报告]
发表于 2007-08-13 17:22 |只看该作者
我觉得这个结果是理所当然的。
这句

  1. if (*first == value)
复制代码

两边都是char*,怎么比啊。
你的测试例子中一边是局部字符串地址,一边字面字符串的地址,不会相等的。
而string之类的对象重载了==,当然就相等了,char*又没办法重载。
还是实现一个remove_if函数吧。

论坛徽章:
0
9 [报告]
发表于 2007-08-13 17:29 |只看该作者
比较和调试了标准STL和我的tiny STL, 标准的STL测试代码如下:

  1. main()
  2. {
  3.         char* as = "aaa";
  4.         char* bs = "bbb";
  5.         char* cs  = "aaa";

  6.         list<char*> S;
  7.         list<char*>::iterator j;
  8.         S.push_back(as);
  9.         S.push_back(bs);
  10.         S.push_back(cs);

  11.         for(j=S.begin(); j != S.end(); ++j) cout << *j << " ";
  12.         cout << endl;

  13.         S.remove("aaa");
  14.         for(j=S.begin(); j != S.end(); ++j) cout << *j << " ";
  15.         cout << endl;
复制代码

在remove设置断点的GDB部分调试结果:

  1. (gdb) print __value
  2. $3 = (char * const&) @0xbfffe15c: 0x80490e0 "aaa"
  3. (gdb) print *__first
  4. $4 = (char *&) @0x804a7c0: 0x80490e0 "aaa"

  5. (gdb) step
  6. std::_List_iterator<char*, char*&, char**>::operator*() const (this=0xbfffe120)
  7.     at stl_list.h:138
  8. 138           { return ((_Node*) _M_node)->_M_data; }

  9. (gdb) print ((_Node*) _M_node)->_M_data
  10. $5 = 0x80490e0 "aaa"
复制代码

不明白的地方:
1 0xbfffe15c: 0x80490e0这两个分别是什么地方的地址?我认为前者是data段中的地址, 而后者是栈中地址。
2 标准STL使用list<char*>存放的是什么地址,是data段中的地址吗?


我的tiny STL部分GDB调试:

  1. (gdb) print context[2]
  2. $1 = "aaa\000\000\000\000\000\000"
  3. (gdb) print &context[2]
  4. $2 = (char (*)[10]) 0xbffff4f4
  5. (gdb) print value
  6. $3 = (char * const&) @0xbffff4d4: 0x804b56d "aaa"
  7. (gdb) print &value
  8. $4 = (char * const *) 0xbffff4d4
  9. ...
  10. (gdb) print *first
  11. $10 = (char *&) @0x804e6b8: 0xbffff4f4 "aaa"
复制代码

我存放的是data段中的地址,返回的也是data段中的地址【0xbffff4f4】, 而标准的STL返回应该的是局部的栈中的地址。

说错了,标准STL和tiny STL存放的都应该是函数main栈中的地址【只要是在函数体外的变量才是在data段中】

[ 本帖最后由 SybaseLU 于 2007-8-13 18:10 编辑 ]

论坛徽章:
0
10 [报告]
发表于 2007-08-13 17:42 |只看该作者
1. 嗯。我也这么认为的。
2. list<char*>中的字符串地址是push_back过来的。push_back("aaaa")和a[]="aaa";S.push_back(a)的char*是不同的。
我觉得楼主在设计这个List的时候,主要目的是要按容器的值语义来使用这个List的。所以用这个List来管理指针型数据时,remove_if是少不了的。也可以在构造list时传入比较函数。

[ 本帖最后由 jigloo 于 2007-8-13 17:44 编辑 ]
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP