【问题标题】:How can I iterate over a string in 128-bit chunks?如何迭代 128 位块中的字符串?
【发布时间】:2012-10-26 16:21:18
【问题描述】:

我有一个函数可以对任意长度字符串中的 128 位数据块进行操作。如果字符串不能均匀地分割成 128 位的块,则会被相应地填充。

目的是转换输入函数的字符串中的数据。

我最初想到的是循环遍历字符串 a 这样的:

//This might have stupid errors.  Hopefully it stillg gets the point across.
for (int i = 0; i < strn.size(); i += 16)
{
    string block = strn.substr(i, i + 15);
    strn.replace(i, i + 15, block);
}

我想这会起作用,但我认为必须有一种更优雅的方式来做到这一点。想到的一个想法是将strn 封装在一个类中并实现我自己的迭代器,该迭代器可以以128 位块的形式读取其内容。这很吸引人,因为构造函数可以处理填充,并且我当前使用的一些函数可以设为私有,从而避免潜在的误用。这看起来是一种富有成效的方法吗?如果是这样,如何实现他自己的迭代器?非常欢迎详细解释,因为我对 C++ 非常缺乏经验。

还有其他可能更好的方法吗?

谢谢!

【问题讨论】:

    标签: c++ iterator stdstring


    【解决方案1】:

    有很多方法。一个更简单直接的方法是这样的: 您可以创建自己的类型,大小正好为 128 位;简单的struct 就可以完成这项工作。

    typedef struct
    {
        char buf[16];
    } _128bit;
    

    并用它来迭代你的字符串。 将字符串的开头转换为该结构类型:_128bit* start = (_128bit*)buffer; 并开始使用整数指针算法对其进行迭代。 start 上的所有操作都将根据其大小进行操作。例如。 ,start++ 将向前移动 128 位; start-- 将向后移动 128 位。到达所需位置后,将其重铸为所需类型并执行您的操作。

    【讨论】:

    • 这听起来像一个简单而优雅的方法!只是几个问题:1)_128bit 中的下划线是否有原因? 2)为什么是typedef?我猜这让我可以将其他变量和常量作为它的类型......我的直觉是否正确? 3) 在这个例子中++ 操作符是怎么被重载的?为什么我不必明确地这样做?非常感谢并为我对更精细的 C++ 结构的无知深表歉意! =)
    • 1.如果我没记错的话,变量名称不能以数字开头。 2. 嗯,在C++中其实不需要,在C中这可以缩短代码:)。 3.这就是指针算法的优点,它是根据指向的元素来操作的,更多细节请看这里:stackoverflow.com/questions/394767/pointer-arithmetic BTW,这是一个纯C的解决方案,没有使用C++特性
    • 好吧,这是有道理的。不过,我仍然对 typedef 有点不清楚。 typedef 关键字不允许您创建新的类型名称吗?因此,您的示例不应该为您定义的结构指定名称吗? ...类似于typedef struct{...} ?
    • 这正是它的作用:typedef struct {/* new type definition */} new_type_name;
    • @icepick,facepalm。是的,是的……你完全正确!感谢您的帮助!
    【解决方案2】:

    我可能会使用迭代器而不是索引来执行此操作,仍然使用您自己的 for 循环:

    const int NUM_BITS_IN_CHUNK = 128;
    const int CHUNK_SIZE = NUM_BITS_IN_CHUNK / CHAR_BIT;
    
    for(std::string::const_iterator iter = str.begin(); iter < str.end(); iter += CHUNK_SIZE)
    {
        your_func(iter, iter + CHUNK_SIZE);
    }
    

    boost::iterator_adaptor 代码看起来像这样。请注意,为了简单起见,在示例中我每个块只获得 4 个字节而不是 16 个字节。:

    #include <iostream>
    #include <string>
    
    #include <boost/iterator_adaptors.hpp>
    
    struct string_chunk_iterator : public boost::iterator_adaptor<string_chunk_iterator, std::string::const_iterator>
    {
        string_chunk_iterator(const std::string::const_iterator& base) : iterator_adaptor(base) { }
    
    private:
        friend class boost::iterator_core_access;
        void increment() { this->base_reference() = this->base() + 4; }
        void advance(typename iterator_adaptor::difference_type n)
        {
            this->base_reference() = this->base() + (4 * n);
        }
    };
    
    int main()
    {
        const std::string tester(20, 'A');
    
        string_chunk_iterator iter(tester.begin());
        string_chunk_iterator str_end(tester.end());
    
        for(; iter != str_end; ++iter)
        {
            std::string chunk(&*iter, &*(iter + 1));
    
            std::cout << chunk << std::endl;
        }
    
        return 0;
    }
    

    【讨论】:

    • 有没有办法继承std::string::const_iterator 以便用++ 增加它或调用iter.next() 将增加128 位?另外,我有点困惑。我原以为 iter += 128 会将指针移动 128 个 bytes (或索引)。我错过了什么?
    • @blz 我相信你可以使用boost::iterator_adapter 来创建这样的迭代器,但我对 boost 的那部分经验很少。你是对的,iter += 128 确实会增加 128 个字节。幸运的是,这不是我在代码中所做的:我增加了 16(字节)。这就是我创建常量的原因,以确保它即使在具有 16 位 char 的系统上仍然有效。
    猜你喜欢
    • 2019-07-15
    • 2013-08-09
    • 1970-01-01
    • 1970-01-01
    • 2021-04-30
    • 1970-01-01
    • 1970-01-01
    • 2010-10-24
    • 2010-09-19
    相关资源
    最近更新 更多