【问题标题】:C++ Populating a vector of objects with user inputC++ 使用用户输入填充对象向量
【发布时间】:2015-10-23 09:00:05
【问题描述】:

我是向量的新手,也是类的新手。话虽如此,我发现了一些关于如何创建对象向量的帖子。我想知道如何从用户输入创建对象向量?假设程序要求用户提供他/她想要创建的员工(班级)数量。用户想要添加 5 名员工。所以用户必须输入员工的姓氏和名字。我有一个 for 循环,但我不确定如何获取用户输入(也许使用 getline 和 push_back?)并将其存储在向量中。

//Lets say class.h looks like this
class Employee
{
private:
    string lastName;
    string firstName;
public:
    void setLastname(string);
    void setFirstname(string);
    string getLastname() const;
    string getFirstname() const;
}

【问题讨论】:

  • std::cinstd::getlinestd::vector 应该这样做。
  • 基本技能是将大问题分解为子问题。例如以绝对不提及如何获得用户输入(如果有)的方式为您的程序设计循环,只要您这样做,同样不提及您的如何创建一个Employee 对象,也不知道如何将它存储在向量中。

标签: c++ vector


【解决方案1】:

你的Employee 类应该有一个构造函数。收集输入时,您需要所有构造函数参数。然后,要将Employee 添加到vector<Employee>,请调用employees.emplace_back( ctor-arguments )

【讨论】:

  • 我使用 C# 进行开发,并且只知道 C++98 作为用于 ACM 竞赛的程序语言。你能解释一下 - 使用emplace_back 或实例化一个对象然后应用push_back 有什么区别吗?谢谢。
  • @YeldarKurmangaliyev,它避免了不必要的对象复制。
  • @YeldarKurmangaliyev:它甚至可以防止不必要的移动对象。 (push_back 将移动一个对象,如果允许的话。)
【解决方案2】:

std::vector 有一个很好的方法叫做emplace_back,它

将一个新元素附加到容器的末尾。元素是通过std::allocator_traits::construct 构造的,它通常使用placement-new 在容器提供的位置就地构造元素。

所以你唯一缺少的就是能够使用它的是一个合适的构造函数。

#include <iostream>
#include <string>
#include <vector>

using namespace std;

class Employee
{
private:
    string firstName;
    string lastName;
public:
    void setLastname(string);
    void setFirstname(string);
    string getLastname() const{return lastName;}
    string getFirstname() const{return firstName;}

    //create a constructor
    Employee(string firstName, string lastName)
        : firstName(firstName), lastName(lastName)
    {}
};

int main()
{
    vector<Employee> emp;
    int count = 0;
    cout << "Enter the amount of employees to add:" << endl;
    cin >> count;

    string firstName, lastName;
    for(int i = 0; i < count; ++i)
    {
        cout << "Please enter the first and last names" << endl;

        cin >> firstName;
        cin >> lastName;

        emp.emplace_back(firstName, lastName);
    }

    for(const Employee & e : emp)
    {
        cout << "Employee:" << endl;
        cout << e.getFirstname() << " " << e.getLastname() << endl;
    }
}

【讨论】:

  • 既然你事先已经在向量中包含了元素的数量,最好做一个 .reserve :)
  • 使用“提前指定尺寸”模式可能是个坏主意;鉴于我们使用的是vector,它并没有真正提供任何简化……或者,至少,如果您进行所有适当的 I/O 检查,它不会提供任何简化。
  • 谢谢!这个构造函数的定义是什么?
  • @ZhangBing,构造函数体中不需要任何内容​​,因为它使用了member initializer list
  • @Hurkyl,问题指出应首先输入员工数量。我的代码只演示了填充向量的实际过程,所以我没有包括 IO 检查。我相信 OP 可以自己做,也可以修改 IO 代码以适应他的实际需求(比如类中的附加字段等)。
【解决方案3】:

其他用户提供了一个很好的例子来解释如何在现代 C++ 中使用emplace_back
如果您使用 C++11 之前的版本,则没有 emplace_back 方法。在这种情况下,您可以使用旧式push_back 手动收集vector 中的数据。您可以简单地定义一个向量:

vector<Employee> employees;

然后,您可以逐行读取数据,创建新对象,根据您的业务逻辑填充它们并附加到您的vector

int n;

int main() 
{
    cout << "Enter number of employyes: "; cin >> n;

    for (int i = 0; i < n; i++)
    {
        std::string s;
        Employee employee; // Create object

        cout << "Employee " << i << ". First name: "; cin >> s;
        employee.setFirstname(s); // Fill object

        cout << "Employee " << i << ". Last name: "; cin >> s;
        employee.setLastname(s); // Keep filling it

        cout << "Welcome, " << employee.getFirstname() << " " << employee.getLastname() << endl;
        employees.push_back(employee); // Add to vector
    }
}

您还可以定义一个将firstnamelastname 作为参数的构造函数,以使其更易于使用。

【讨论】:

  • 你的意思是Employee employee; - 去掉new Employee()
  • 您可能想要push_back(std::move(employee))。您不再需要本地副本。
  • @MSalters std::move 不是 C++11 的一部分吗?我试图为 pre-C++11 提供一个示例。以前的版本应该怎么做?
  • 使用“提前指定尺寸”模式可能是个坏主意;鉴于我们使用的是vector,它并没有真正提供任何简化……或者,至少,如果您进行所有适当的 I/O 检查,它不会提供任何简化。
  • @YeldarKurmangaliyev:公平点。 C++98没有移动,会复制。
【解决方案4】:
class Employee
{
private:
    string lastName;
    string firstName;
public:
    Employee(string paramLastName, string paramFirstName) : lastName(move(paramLastName)), firstName(move(paramFirstName)) {}
    void setLastname(string);
    void setFirstname(string);
    string getLastname() const;
    string getFirstname() const;
}

您需要一个将两个字符串作为输入的构造函数。显然你可以不这样做,但这会减少冗长。

Employee(string paramLastName, string paramFirstName): 姓(move(paramLastName)), firstName(move(paramFirstName)) {}

你需要用这种方式调用它。

vector<Employee> inp;
string tmp1, tmp2;
while(std::cin>>tmp1 >> tmp2) {
    inp.emplace_back(tmp1, tmp2);
}

(这是假设您将使用 c++11 支持进行编译)

【讨论】:

  • 对于emplace_back,您不需要{ }
  • @MSalters 谢谢。更新了我的答案
  • 你的用户输入逻辑错误;当你检查std::cin时,已经太晚了。
  • @Hurkyl 啊。咖啡还没有开始。已更新。
猜你喜欢
  • 1970-01-01
  • 2016-04-22
  • 1970-01-01
  • 2017-03-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多