使用for_each迭代NULL终止的字符串数组

4 c++

使用for_each迭代NULL终止的字符串是可能的:

const char *name = "Bob";

void func(const char &arg)
{
   cout << arg;
}

int main()
{
    for_each(name, name + strlen(name), func);
}
Run Code Online (Sandbox Code Playgroud)

对于NULL终止的字符串列表,可能类似的事情(不必首先确定列表的总长度),例如:

const char *names[] = { "Bob", "Adam", "Simon", NULL };
Run Code Online (Sandbox Code Playgroud)

eq-*_*eq- 8

std :: for_each在一个范围内"迭代",因此要将它与不确定长度的数组一起使用,您需要使用自定义迭代器来指示数组的结尾(在NULL成员上).如果你坚持使用以NULL结尾的char*数组,你当然可以为它创建自己的for_each函数,例如:

template <typename Function>
void for_each_in_null_terminated_cstring_array(const char** array, Function f)
{
    while (*array) {
        f(*array);
        array++;
    }
}

const char *names[] = { "Bob", "Adam", "Simon", NULL };
for_each_in_null_terminated_cstring_array(names, func);
Run Code Online (Sandbox Code Playgroud)

不过,我并不是真的推荐这个解决方案.

编辑:是的,更普遍的是总是美好,不是吗?

template <typename T, typename Function>
void for_each_in_null_terminated_array(T* array, Function f)
{
    while (*array) {
        f(*array);
        array++;
    }
}
Run Code Online (Sandbox Code Playgroud)

(这里是我之前提到的null终止("false"-terminated)迭代器的实现 - 根据下面的建议进行了一两次更改.它应该是一个真正的InputIterator)

template <class T>
class nt_iterator: public std::iterator<std::input_iterator_tag, T>
{
public:
    typedef typename nt_iterator<T>::pointer pointer;
    typedef typename nt_iterator<T>::value_type value_type;

    nt_iterator(): p(), pte(true) {}
    nt_iterator(pointer p_): p(p_), pte(!p_) {}
    nt_iterator(const nt_iterator<T>& rhs): p(rhs.p), pte(rhs.pte) {}
    nt_iterator<T>& operator++() {
        ++p;
        if (!*p) pte = true; // once past-the-end, always past-the-end
        return *this;
    }
    nt_iterator<T> operator++(int) {
        nt_iterator n(*this);
        operator++();
        return n;
    }
    bool operator==(const nt_iterator<T>& rhs) {
        return pte && rhs.pte || p == rhs.p;
    }
    bool operator!=(const nt_iterator<T>& rhs) {
        return !(operator==(rhs));
    }
    value_type operator*() { return *p; }

private:
    pointer p;
    bool pte; // past-the-end flag
};
Run Code Online (Sandbox Code Playgroud)

它是如何使用的:

void print(const char* str);

int main()
{
    const char* array[] = {"One", "Two", "Three", NULL, "Will you see this?"};
    std::for_each(nt_iterator<const char*>(array),
                  nt_iterator<const char*>(),
                  print);
}
Run Code Online (Sandbox Code Playgroud)

它可能比循环版本慢一点,因为等价检查的数量增加 - 与例如打印文本相比,速度差异当然是微不足道的 - 但是应该注意到,这std::for_each不会神奇地使循环更快(事实上,您可能会惊讶地看到您的编译器供应商如何定义函数 - 也就是说,如果您期望太多).

  • 不,您不需要根据定义*确定长度*.这可以使用自定义迭代器.这很难看,但可以做到. (2认同)