【问题标题】:How do I go about printing a vector of objects?如何打印对象向量?
【发布时间】:2018-10-06 08:46:33
【问题描述】:

我猜我可能不得不使用指针,但在课堂上还没有深入研究它们,还没有尝试在我的程序中实现它们。到目前为止,我有这个,打印功能朝向程序的中间。我不太确定如何打印出向量中的元素,因为我的方法不起作用。

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

using namespace std;

class rolodex
{
  string name;
  string street, town, state;
  string zip;
  string phone;
  vector <rolodex> entries;

  public:
     rolodex();
     void getmenu();
     void add_entry();
     void set_name();
     void set_address();
     void set_phone();
     void printinfo();
};

rolodex :: rolodex() : name(""), street(""), town(""), state(""), zip(""), 
phone(""), entries()
{
}


void rolodex :: getmenu()
{
  cout << "\n\n1)Add Entry";
  cout << "\n5)Print All Entries";
  cout << "\n6)Exit" << endl;
}


void rolodex :: add_entry()
{
  rolodex temp;
  cout << "\n\nEnter Name: ";
  temp.set_name();
  temp.set_address();
  cout << "\n\nEnter Your Phone Number: ";
  temp.set_phone();

  entries.push_back(temp);

}

void rolodex :: set_name()
{
  cin.ignore();
  getline(cin, name);

}


void rolodex :: set_address()
{
  cout << "\n\nNow we'll enter address information.";
  cout << "\n\nStreet: ";
  getline(cin, street);
  cout << "\n\nTown: ";
  getline(cin, town);
  cout << "\n\nState: ";
  getline(cin, state);
  cout << "\n\nZip: ";
  getline(cin, zip);
}


void rolodex :: set_phone()
{
  getline(cin, phone);
}


void rolodex :: printinfo()
{

  for(unsigned int i = 0; i < entries.size(); i++)
  {
     cout << entries[i] << endl;  //This is where I'm stuck since I've only
                                  //worked with vectors of non-object data
                                  //type
  }

}


int main()
{
  rolodex person, menu;
  short choice;
  bool done = false;


 do
 {
   menu.getmenu();
   cout << "\n\nEnter a choice: ";
   cin >> choice;

   switch(choice)
   {
      case 1:
         person.add_entry();
         break;
      case 5:
         person.printinfo();
         break;
      case 6:
         done = true;
         break;

      default:
         cout << "\n\nInvalid Entry." << endl << endl;
     }

   } while(!done && isdigit(choice));

   return 0;
}

【问题讨论】:

  • 提供一个重载的std::ostream&amp; operator&lt;&lt;(std::ostream, const rolodex&amp;)
  • 关于您的设计的一个小注释(但与您的问题无关):一个 rolodex 是一个 persons 的集合。 rolodex 不是单个人人的集合的组合。并且将诸如“用户界面”之类的东西分开,它也不是真正的 rolodex 的一部分。

标签: c++ object pointers for-loop vector


【解决方案1】:

πάντα ῥεῖ 是对的,但要添加更多细节...

您需要指定您希望流如何处理您的对象。这是通过添加&lt;&lt; 运算符来完成的。例如:

std::ostream& operator<<(std::ostream& s, const rolodex& r){
  // Or however you want to format it.
  s << "Name: " << r.name << " : ";
  s << "Street: " << r.street << " : ";
  s << "Town: " << r.town << " : ";
  s << "State: " << r.state << " : ";
  s << "Zip: " << r.zip << "\n";
}

不幸的是,上面的函数试图访问你的类的私有字段,但它不能,因为它不是类定义的一部分。

解决这个问题的一种简单方法是在类定义中将此函数声明为“朋友”,如下所示:

 friend std::ostream& operator<<(std::ostream&, const rolodex&);

...既然您可能会喜欢它,那么您可以直接使用一个大的可复制粘贴块,它应该可以使您的功能正常工作:

class rolodex
{
  string name;
  string street, town, state;
  string zip;
  string phone;
  vector <rolodex> entries;

  public:
     rolodex();
     void getmenu();
     void add_entry();
     void set_name();
     void set_address();
     void set_phone();
     void printinfo();

     friend std::ostream& operator<<(std::ostream&, const rolodex&);
};

std::ostream& operator<<(std::ostream& s, const rolodex& r){
  // Or however you want to format it.
  s << "Name: " << r.name << " : ";
  s << "Street: " << r.street << " : ";
  s << "Town: " << r.town << " : ";
  s << "State: " << r.state << " : ";
  s << "Zip: " << r.zip << "\n";
}

【讨论】:

  • 我会在 int main() 中进行实际打印吗?您的反馈帮助很大,但我仍然无法输出任何内容。它只打印“名称:”和“:”任何进一步的反馈将不胜感激
  • 如果“名称:”和“:”出现,但它们之间没有任何内容,则表示对象中的字段为空。我刚刚尝试编译程序,尝试设置人员信息后程序退出。我不认为 isdigit 函数真的是你想要让你保持在那个循环中的东西。编辑:事实上,只是从 while 条件中删除 &amp;&amp; isdigit(choice) 使它的行为就像我认为你想要的那样。
  • 是的,isdigit 一开始的工作方式不同,并且没有退出循环,但是当我意识到它在输入信息后退出时,我将其取出。理想情况下,我想制作一个临时对象并在类中检索姓名、地址和电话号码,然后将它们输入到向量中,这样我就可以拥有一个对象向量。问题是我不知道如何正确访问该类中这些对象中的单个元素。我选择了 3 个并行字符串向量,我认为效率较低。感谢您的帮助,我会尝试两种方式
【解决方案2】:

遵循 πάντα ῥεῖ 的建议,这是一种方法,尽可能少地改变你的设计:

1) 为您的 rolodex 类创建一个非成员重载运算符

std::ostream& operator<< (std::ostream& os, const rolodex& rol)
{
    os << rol.name << ":"    << std::endl
       << "\t" << rol.street << std::endl
       << "\t" << rol.town   << std::endl
       << "\t" << rol.state  << std::endl
       << "\t" << rol.zip    << std::endl
       << "\t" << rol.phone  << std::endl;
    return os;
}

.. 但是编译器会责备您尝试从类外部访问私有成员(默认情况下,成员是私有的),因此您必须稍微放宽规则:

class rolodex
{
  ...
public:
     ...
     friend std::ostream& operator<< (std::ostream& os, const rolodex& rol);
};

您不能在类本身中包含运算符does-overloading-operator-works-inside-the-class。

但是,无论如何,将 getter 函数添加到公共接口几乎总是更好的设计。您将在类 def 的 public: 部分中有 get_name() 等,这些函数最初只会返回私有成员变量的值,然后您的 operatorfriend 声明。

我赞成一些程序员老兄对你的设计的评论

让用户输入数据的代码真的不应该在 rolodex 类中,因为它使类难以重用。例如,想要从图形界面重用 rolodex 的图像,让 rolodex 在矢量内包含自身的实例并不是一个好主意。

我会推荐一个

1) 包含人员所有属性的 Person 类,公共 getter get_name() 和 setter set_name() 不使用特定的入口方法,只需将数据作为参数,例如set_name(std::string&amp; name).

2) 非成员操作符

3) 具有私有 std::vector&lt;Person&gt; 的 Rolodex 类以及添加人员、将所有人员写入输出流等方法。

祝你好运并享受:-)

编辑:恕我直言,终端上的菜单结构应留在 main() 函数内或封装到另一个类中。但当然不要把它留在 Rolodex 或更糟的地方,Person。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-13
    • 2018-07-28
    • 2020-09-29
    • 1970-01-01
    • 2019-03-02
    • 2016-04-16
    相关资源
    最近更新 更多