关于将元素插入向量的 C++ 问题

Posted

技术标签:

【中文标题】关于将元素插入向量的 C++ 问题【英文标题】:C++ question regarding inserting elements into vectors 【发布时间】:2011-01-26 10:17:36 【问题描述】:

我正在研究 Accelerated C++ 中的示例。 其中一个问题要求读者将通过考试的学生的记录复制到一个称为学生的向量的开头。 fgrade 是在别处定义的返回失败学生的函数。 然后必须使用调整大小功能从学生中删除多余的元素,使其仅包含通过的人。 我已经尝试过这段代码,但它不起作用。谁能告诉我错误是否出在下面的代码中?

#include "stdafx.h" 
#include <vector>
#include "Student_info.h"
#include "grade.h"

using std::vector;

// second try: correct but potentially slow
vector<Student_info> extract_fails(vector<Student_info>& students)

    vector<Student_info> fail;
#ifdef _MSC_VER
    std::vector<Student_info>::size_type i = 0;
    std::vector<Student_info>::size_type count = 0;
#else
    vector<Student_info>::size_type i = 0;
    vector<Student_info>::size_type count = 0;
#endif

    while (i != students.size())  
        if (!fgrade(students[i]))  
            students.insert(students.begin(), students[i++]);
            count++;
        
        i++; 
    
    students.resize(count); 
    return students;

【问题讨论】:

循环中有两次 i++,因此您的代码将跳过所有奇怪的学生。如果 students.size() 不是偶数,则循环将永远进行。 在这种状态下,您将一个学生放入向量中,如果条件匹配,您将 same 学生插入向量中。所以你在向量中有两次......也许你需要使用'失败'向量...... 在迭代时修改向量真的是个好主意吗?尤其是因为您使用索引来遍历每个学生,将通过的学生复制到向量的开头,所以您依靠那里复制的 i++ 来保存您的培根。如果是我,我会使用第二个向量。 【参考方案1】:

您可以使用 std::algorithm 中的 remove_if,但函子应返回未通过的人 (f_not_grade),而不是通过的人:

std::remove_if(students.begin(), students.end(), f_not_grade)

或者您可以寻找否定仿函数 here 或 here 的方法,以使用不加修改的 f_grade 函数和 remove_if。

容器的大多数常见操作都是在 STL 中实现的,因此请使用语言的强大功能!花点时间寻找这类函数,让我们的代码更少更好。

编辑删除了不正确的“()”。

【讨论】:

他仍然需要调整大小,但这应该不是问题,可以使用remove_if返回的迭代器来计算新序列的长度。这比我的解决方案更优雅。 抱歉,我说的不准确。 fgrade 返回一个布尔值,指示学生是否失败。我已经尝试使用上面的 fgrade() 作为最终参数,但这失败了。同样 fgrade == false;我知道这个最后的评论看起来很愚蠢,但我真的被困在这里。 Accelerated C++ 一书很好,但例子对我们中的一些人来说真的很难。 我认为作者希望我们使用 insert() 和 resize()。我重写如下。我已将学生放入一个名为 pass 的向量中。它运行但不会调整向量的大小以消除所有失败的学生 - 他们将在最后。 while (i !=students.size()) if (!fgrade(students[i])) pass.push_back(students[i]);计数++; 否则 ++i; student.insert(students.begin(),pass.begin(), pass.end());学生.resize(count);返校生; 嗨史蒂夫,我评论中 f_not_grade 后面的“()”不正确。正确的行是 std::remove_if(students.begin(), students.end(), fgrade);很抱歉给您带来不便。【参考方案2】:

您在循环中将i 增加两次。

一个很酷的方法是为std::sort 使用自定义谓词:

bool CompareStudentsByFailure(const Student_info & left, 
                              const Student_info & right) 
   return fgrade(left) > fgrade(right);

然后像这样使用它:

std::sort(students.begin(), students.end(), CompareStudentsByFailure);
students.resize(std::distance(students.begin(), 
                std::find_if(students.rbegin(), 
                             students.rend(), fpgrade).base()));

不过,Jon`s answer 稍微简单一些。

【讨论】:

【参考方案3】:

正如 Space_C0wb0y 和 Artium 指出的那样,您将 i 增加了两次。此外,您声明向量失败,但从不使用它(除非您稍后使用它做某事)。此外,函数中的宏看起来有点矫枉过正——它基本上说了两次同样的事情(减去“std::”),你不妨只使用整数——更容易让下一个人阅读和理解。

【讨论】:

非常感谢所有帮助过我的人。你是最有帮助的。

以上是关于关于将元素插入向量的 C++ 问题的主要内容,如果未能解决你的问题,请参考以下文章

C++ 向量和列表插入

关于C++中的二维向量

C ++将元素插入向量

将元素插入已排序的向量中

C++ 将元素从一个向量移动到另一个向量

C ++:在向量中插入啥 - 指针或引用,向量何时复制它的元素?