我正在尝试输出地图的内容,但是不确定如何去做。我在头文件中为地图和迭代器设置了以下声明为私有
typedef map<long, string> Student;
Student newstudent;
typedef Student::const_iterator studentItr;
studentItr itr;
并且我的.cpp中有以下声明
map<long, string> classname::GetMap()
{
for(itr = newstudent.begin(); itr !=newstudent.end(); itr++)
{
cout << itr->first << " => " <<itr->second << '\n';
}
return newstudent;
}
这就是我试图将其传递给重载的运算符<<函数
的方式ostream & operator <<( ostream & os, classname & R)
{
os << " " << R.GetMap() << '\n';
return os;
}
通常这对其他任何功能都有效,但由于它是地图,因此出现以下错误:
与'operator <<'不匹配(操作数类型为'std :: basic_ostream
'和'std :: map >')| >
有人能指出我做错了正确的方向吗
编辑:感谢您提出建议,我感谢您的帮助,但是我认为无论是我的编译器还是我所说的话,都是不对的。
每次我尝试使用Student
作为一种类型时,它都不会注册为一种类型,并且我会收到关于它的错误。
例如,如果我声明此声明
ostream & operator <<( ostream & os, const Student & R)
OR
Student & classname::GetMap()
我得到了错误:
“学生”没有命名类型
此错误最终导致我的陈述中没有任何意义,而且我不确定如何解决此问题
答案 0 :(得分:3)
因此,由于某种原因,您似乎已经将输出代码放入GetMap
函数中。您需要一个名为GetMap
的例程来获取地图,或者想要一个名为PrintMap
的例程来输出地图。你有一半。这是一种方法
void classname::PrintMap() const
{
for(itr = newstudent.begin(); itr !=newstudent.end(); itr++)
{
cout << itr->first << " => " <<itr->second << '\n';
}
}
ostream & operator <<( ostream & os, classname & R)
{
os << " ";
R.printMap();
os << '\n';
return os;
}
这可以改进,例如您可以将要输出的流传递给PrintMap
函数。像这样
void classname::PrintMap(ostream & os) const
{
for(itr = newstudent.begin(); itr !=newstudent.end(); itr++)
{
os << itr->first << " => " <<itr->second << '\n';
}
}
ostream & operator <<( ostream & os, classname & R)
{
os << " ";
R.printMap(os);
os << '\n';
return os;
}
最后,您可以遵循通用约定,将PrintMap
重命名为operator<<
,并使其成为朋友函数而不是成员函数。
Student& classname::GetMap()
{
return newstudent;
}
ostream & operator<<(ostream & os, const Student& s)
{
for(itr = s.begin(); itr !=s.end(); itr++)
{
os << itr->first << " => " <<itr->second << '\n';
}
return os;
}
ostream & operator <<( ostream & os, classname & R)
{
os << " " << R.getMap() << '\n';
}
答案 1 :(得分:3)
您可以为地图类型设置运算符<<。 (完全未经测试的代码)
ostream & operator <<( ostream & os, const Student & R) {
for(studentIter itr = R.begin(); itr !=R.end(); itr++){
os << itr->first << " => " <<itr->second << '\n';
}
return os;
}
编辑: 更改名称以匹配您的问题。
答案 2 :(得分:1)
最初,您尝试将std::map
直接插入operator<<()
中。这将不起作用,因为std::map
不知道如何转换为std::ostream
对象,并且std::ostream
的{{1}}不知道如何接受地图。
您始终可以为地图类型编写operator<<()
的重载,但是,如果地图内部的类型是非平凡的类型,例如具有多个字段的类或结构,则该类必须具有其重载类型也拥有自己关联的operator<<()
。因此,为类型本身编写它们并在地图或集合上进行迭代更容易。
因此,既然该类与operator<<()
有工作关系,您就可以遍历任何类型的容器,无论是矢量,数组,列表还是队列等。operator<<()
都不在乎哪种容器,只在乎容器中的对象。
请不要养成将operator<<()
或operator<<()
声明为类成员的习惯,请养成编写运算符的习惯,就像将一个独立的运算符函数适用于您的类型!
如果您的编译器支持operator>>()
代替using
;您可以尝试该程序并检查其预期输出。不应有任何错误,但是在修复格式时可能会忽略一个错字。如果您找到一个,请告诉我,我会进行相应的更新。
main.cpp
typedefs
Students.h
#include "Students.h"
int main() {
using namespace "your namespace here";
Student JacobKnight("Jacob Knight", 233);
Student SaraAndrews("Sara Andrews", 245);
Student AllenReed("Allen Reed", 259);
Students students;
addStudent(JacobKnight, students);
addStudent(SarahAndrews, students);
addStudent(AllenReed, students);
using It = std::map<long, Student>::const_iterator;
for (It it = students.cbegin(); it != students.cend(); ++it) {
std::cout << "Map ID: " << std::setfill('0') << std::setw(8)
<< it->first << "\nStudent: " << it->second;
}
return EXIT_SUCCESS;
}
输出
#pragma once // if your compiler doesn't like this then use header guards!
#include <iomanip>
#include <iostream>
#include <map>
#include <string>
namespace "your namespace here" {
struct Student {
long id_;
std::string name_;
Student() = default;
Student(const std::string name, long id) : name_{name}, id_{id} {}
};
using Students = std::map<long, Student>;
void addStudent(const Student& student, Students& students) {
students.insert( std::make_pair( student.id_, student ) );
}
std::ostream& operator<<(std::ostream& os, const Student& student) {
return os << std::setfill('0') << std::setw(8) << student.id_
<< " " << student.name_ << "\n\n";
}
} // your namespace
在这里,我想将一个学生视为一个对象,它包含该对象的详细信息,数字ID和字符数组或字符串名称。因此,我将这些作为公共成员放入了结构中。您总是可以将其更改为一个类,使用辅助函数将其私有化以封装数据,但是为了快速演示,我在这里做了一个简单的结构或类,没有什么太复杂的。
接下来,我使用using指令定义类型的类型名。现在,我以后可以轻松地使用它声明我的对象。我用它来简化Map ID: 00000233
Student: 00000233 Jacob Knight
Map ID: 00000245
Student: 00000245 Sarah Andrews
Map ID: 00000259
Student: 00000259 Allen Reed
的用法。我还在main中再次使用using指令将迭代器类型名称定义为It。然后,我用它来声明地图的迭代器。
我写了一个简单的函数,可以填充学生的地图。对我来说,这是更直观和更具表现力的,因为地图包含多个对象,在这种情况下为学生,因此是复数的,其中单个实体的结构本身只是一个学生!这使代码更具表现力和可读性,并有助于暗示您的意图。
然后,我简单地写了一个重载的std::map<T1,T2>
,其中包含operator<<()
的{{1}}。然后将输出格式化为我喜欢的格式或所需的布局。然后将其返回给流运算符,以插入到作为控制台或文件的标准流输出中。
我希望这个答案能回答您的问题,并为您提供一些指导...
编辑
在main.cpp中,我将映射的迭代器从for循环中的Student
和const ref
更改为begin()
和end()
。这应该没什么大不同,但是由于我地图的迭代器被声明为cbegin()
。我更喜欢与遍历的迭代器类型保持一致。