代码之家  ›  专栏  ›  技术社区  ›  jkeys

与C++中的循环值相比,这是一种好的形式吗?

  •  1
  • jkeys  · 技术社区  · 15 年前

    毫无疑问,你们中有些人看过我最近的帖子,都是关于同一个项目的。我一直在碰到它的问题。重申一下:仍在学习,不太先进,不太了解指针,不上课,根本不了解OOP概念等。这段代码只是将两个排序向量farray和sarray合并成一个排序向量。至少,我希望这就是它所做的。告诉我:

        //int num is to find the size of the original vector and
        //build up farray and sarray; not used in the merge process
        int num = original.size() 
        std::vector<int> final;
    
        std::vector<int>::iterator it = farray.begin();
        std::vector<int>::iterator iter = sarray.begin();
    
        //farray.size() == (0 thru (num / 2))
        //sarray.size() == ((num / 2) thru num)
        for (;it != farray.end() && iter != sarray.end();) {
            if (*it > *iter) {
                final.push_back(*it);
                it++;
            }    
            else
            {
                final.push_back(*iter);
                iter++;
            }
    
                if (it == farray.end()) {
                    for (int i = 0; iter < sarray.end(); i++) {
                        final.push_back(*iter);
                    }
                }
    
                if (iter == sarray.end()) {
                    for (int i = 0; it < farray.end(); i++) {
                        final.push_back(*iter);
                    }
                }
            }
    

    我重写了合并排序函数的合并部分,以便……好吧,让它工作。我对这个代码有几个问题:

    1. 如果for循环在下一个过程中可能会更改它们,那么与std::vector::iterators进行比较是不是很好的形式?
    2. 在这个循环的最后一次传递中,iter和it的值是否会改变,并弄乱我的代码?将最后一个if语句放在*it和*iter比较之前吗?
    3. end()成员函数是否引用调用它的对象的最后一个值?它似乎可以以某种方式延伸过去。

    编辑:明天我会回复所有回复,如果您想了解更多信息,请稍后再试。已经过了午夜。晚上。

    5 回复  |  直到 15 年前
        1
  •  3
  •   CB Bailey    15 年前

    1.比较与for循环条件来自同一容器的迭代器是很好的,但是这只在您移动增量部分(如果是for循环语句)或for循环本身主体中的一个或其他迭代器时才有意义。在这个for循环中,你比较 iter 反对 sarray.end() 但是for循环永远不会改变 伊特尔 .这意味着要么没有迭代,要么for循环永远不会终止。另外,您可能想使用 != 而不是 < 用于比较。 == != 为所有迭代器工作, < 不。

                for (int i = 0; iter != sarray.end(); i++) {
                    final.push_back(*iter);
                }
    

    AS 伊特尔 从您希望循环开始的位置开始,您可能需要如下内容:

                for (; iter != sarray.end(); ++iter) {
                    final.push_back(*iter);
                }
    

    因为你还在学习(尽管我们不是所有人!),通过这样的算法工作可能很有指导意义,但是您应该知道 std::merge 这可能是你想要的。

    std::merge( farray.begin(), farray.end(), sarray.begin(), sarray.end(), std::back_inserter( final ) );
    

    (你需要 #include <iterator> <algorithm> )

    2。在外部for循环中,我看不到递增的iter或i t使后面for循环中的逻辑失效,1中的点。旁白。

    三。 end() 指向容器末尾的一个,因此可以使用它进行循环终止检查,但不应尝试取消对迭代器的引用,该迭代器是“ = “to” .end() “。

        2
  •  3
  •   Gal Goldman    15 年前

    我没有检查你的算法的实现,我只是参考你的三个问题:

    1. 迭代器很像指向容器值的指针。这就像在for循环中使用大小t i和++i。你觉得比较法拉利和沙雷有问题吗?可能不会,所以没关系。
    2. 我在这里看到你在代码中所做的,就是你刚刚读了*i t和*iter的值,你实际上并没有改变它们,所以它们不会改变。
    3. end()指向无效的位置。它不是指向最后一个值,而是指向“在它之后”。如果您愿意,这就像“空”,因此如果(iter==sarray.end())是真的,那么如果您要写*iter,就会崩溃,因为您不能取消对等于end()的迭代器的引用。
        3
  •  1
  •   NickZoic    15 年前

    一些一般性的建议:您需要考虑变量名。将迭代器称为“it”和“iter”在某个时刻会使您感到困惑。实际上,如果你仔细观察,它已经有了。如果“farray”和“sarray”是有意义的名字,那么“fiter”和“siter”如何?

    另外,思考一下合并排序正在做什么。最后两个块只是为了“耗尽”迭代器剩下的东西。所以他们不需要进入第一个循环。

    我可能会把它写成(伪代码):

    while not (list1.empty and list2.empty):
        if list1.empty:
            result.push(list2.pop)
        else if list2.empty:
            result.push(list1.pop)
        else if list1.top > list2.top:
            result.push(list2.pop)
        else:
            result.push(list1.pop)
    

    或者在一些锈蚀的货物中C++:

    std::vector<int>::iterator fiter = farray.begin();
    std::vector<int>::iterator siter = sarray.begin();
    
    while (fiter != farray.end() || siter != sarray.end()) {
        if (fiter == farray.end())      final.push_back(*siter++);
        else if (siter == sarray.end()) final.push_back(*fiter++);
        else if (*fiter > *siter)       final.push_back(*siter++);
        else                            final.push_back(*siter++);
    }
    
        4
  •  0
  •   John Dibling    15 年前

    你有一些事情要考虑。

    首先,如果要合并两个范围,最好使用 std::merge 功能,而不是滚动你自己。

    您的代码有点难阅读,因为您使用不同的缩进样式和大括号。选择一种风格并坚持下去。

    for循环的第一部分似乎是合并的正确实现:

    for (;it != farray.end() && iter != sarray.end();) {
        if (*it > *iter) {
            final.push_back(*it);
            it++;
        }    
        else
        {
            final.push_back(*iter);
            iter++;
        }
    

    …这应该是你完成工作所需要的全部。

    循环的第二部分有几个问题:

       for (;it != farray.end() && iter != sarray.end();) {
             :   :
                if (it == farray.end()) {
                    for (int i = 0; iter < sarray.end(); i++) {
                        final.push_back(*iter);
                    }
                }
    
                if (iter == sarray.end()) {
                    for (int i = 0; it < farray.end(); i++) {
                        final.push_back(*iter);
                    }
                }
            }
    

    首先,for()条件是这样编写的 it iter 不能指向 end() 或者循环结束。所以 不能指向 sarray.end() , 伊特尔 不能指向 farray.end() 而且两者都不 if 声明永远不会被激发。它们都是死的(无法访问)代码。

    但即使它们不是死代码,它们也有缺陷。中的条件 for(...) 当迭代器指向集合的结尾时中断循环,但此迭代器从未移动过,因此您有一个无限循环。

    这两个都是 为了(…) 因为迭代器永远不能指向向量的末尾,所以s是非种子死码。

        5
  •  0
  •   Andrew Jaffe    15 年前

    一个简单的评论:为什么不使用 while (condition) 而不是 for(; !condition; ) .

    后者施工不规范,难以理解!