QQ空间互踩 | 代码交流官方QQ群: ①4164128 ②13937921网络证件中心 | 更多QQ空间日志编辑器 | 火星文字
发新话题
打印

[〖其他语言交流专区〗] C++ Advanced STL Programming (3)

本主题由 花少 于 2009-1-6 10:02 移动

C++ Advanced STL Programming (3)

copy_if
没错,STL 里面压根没有 copy_if ,这就是为什么我们需要这个:
template<typename InputIterator, typename OutputIterator, typename Predicate>
OutputIterator copy_if(
    InputIterator begin, InputIterator end, OutputIterator destBegin, Predicate p)
{
    while (begin != end)
    {
        if (p(*begin))
*destBegin++ = *begin;
        ++begin;
    }
    return destBegin;
}

把它放在自己的工具箱里,是一个明智的选择。
=====================================================
惯用手法:erase(iter++)
如果你要去除一个 list 中的某些元素,那可千万小心:(下面的代码是错的!!!)

#include <iostream>
#include <algorithm>
#include <iterator>
#include <list>

int main()
{
    int arr[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    std::list<int> lst(arr, arr + 10);

    for ( std::list<int>::iterator iter = lst.begin();
          iter != lst.end(); ++iter)
        if ( *iter % 2 == 0 )
            lst.erase(iter);
            
    std::copy(lst.begin(), lst.end(),
        std:: ostream_iterator<int>(std::cout, " "));
}


iter erase 掉的时候,它已经失效,而后面却还会做 ++iter ,其行为无可预期!如果你不想动用 remove_if ,那么唯一的选择就是:

#include <iostream>
#include <algorithm>
#include <iterator>
#include <list>

int main()
{
    int arr[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    std::list<int> lst(arr, arr + 10);

    for ( std::list<int>::iterator iter = lst.begin();
          iter != lst.end(); )
        if ( *iter % 2 == 0 )
            lst.erase(iter++);
        else
            ++iter;
           
    std::copy(lst.begin(), lst.end(),
        std:: ostream_iterator<int>(std::cout, " "));
}


但是上面的代码不能用于 vector, string deque ,因为对于这些容器, erase 不光令 iter 失效,还令 iter 之后的所有 iterator 失效!
=====================================================
erase(remove...) 惯用手法
上面的循环如此难写,如此不通用,如此不容易理解,还是用 STL 算法来的好,但是注意,光 remove_if 是没用的,必须使用 erase(remove...) 惯用手法:

#include <iostream>
#include <algorithm>
#include <iterator>
#include <list>
#include <functional>
#include <boost/bind.hpp>

int main()
{
    int arr[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    std::list<int> lst(arr, arr + 10);

    lst.erase(remove_if(lst.begin(), lst.end(),
        boost::bind(std::modulus<int>(), _1, 2) == 0),
        lst.end()
    );
           
    std::copy(lst.begin(), lst.end(),
        std:: ostream_iterator<int>(std::cout, " "));
}


当然,这里借助了 boost.bind ,让我们不用多写一个没用的 functor
=====================================================
简单常识——关于stream
从文件中读入一行
简单,这样就行了:
ifstream ifs("input.txt");
char buf[1000];

ifs.getline(buf, sizeof buf);
string input(buf);
当然,这样没有错,但是包含不必要的繁琐和拷贝,况且,如果一行超过1000个字符,就必须用一个循环和更麻烦的缓冲管理。下面这样岂不是更简单?
string input;
input.reserve(1000);
ifstream ifs("input.txt");
getline(ifs, input);

不仅简单,而且安全,因为全局函数 getline 会帮你处理缓冲区用完之类的麻烦,如果你不希望空间分配发生的太频繁,只需要多 reserve 一点空间。
这就是简单常识的含义,很多东西已经在那里,只是我一直没去用。
=====================================================

[ 本帖最后由 cckidd 于 2008-8-6 22:03 编辑 ]

        

TOP

来顶咯

提示: 作者被禁止或删除 内容自动屏蔽

TOP

你的家乡有滨海路吗?!

提示: 作者被禁止或删除 内容自动屏蔽

TOP

网球场2

提示: 作者被禁止或删除 内容自动屏蔽

TOP

发新话题