通过迭代器输出映射值及CComplex类代码相关技术咨询
map的迭代器指向的是std::pair<const Key, T>类型的元素,我们可以通过迭代器的first(键)和second(值)成员来访问内容,下面是几种常用的遍历方式:
普通迭代器遍历(可修改元素)
如果需要遍历同时修改map的值,用普通迭代器就行:#include <iostream> #include <map> #include <string> int main() { std::map<int, std::string> fruitMap = {{1, "Apple"}, {2, "Banana"}, {3, "Cherry"}}; // 声明迭代器类型 std::map<int, std::string>::iterator it; for (it = fruitMap.begin(); it != fruitMap.end(); ++it) { std::cout << "键: " << it->first << ", 值: " << it->second << std::endl; // 如果要修改值:it->second = "New Value"; } return 0; }const迭代器遍历(只读场景)
当map是const引用或者你不想修改元素时,用const_iterator更安全,避免误修改:void printConstMap(const std::map<int, std::string>& targetMap) { std::map<int, std::string>::const_iterator it; // 也可以用cbegin()/cend()直接获取const迭代器 for (it = targetMap.cbegin(); it != targetMap.cend(); ++it) { std::cout << "键: " << it->first << ", 值: " << it->second << std::endl; } }反向迭代器遍历(从后往前)
要是需要从map的最后一个元素开始往前遍历,用reverse_iterator:std::map<int, std::string>::reverse_iterator it; for (it = fruitMap.rbegin(); it != fruitMap.rend(); ++it) { std::cout << "键: " << it->first << ", 值: " << it->second << std::endl; }
先把你的构造函数代码贴出来,方便分析:
CComplex(string filename, string nComplex) { string str; m_complex = nComplex; fstream file(filename, ios::in); if (file.is_open()) { string str; bool dfFlag = false; //CHotel temp(" ", 0, 0); //while (file >> temp) while (getline(file,str)) { CHotel temp(str); m_hoteli.push_back(str); // 这里有明显错误! } file.close(); } else throw "ERROR! "; }
结合你给出的文件内容Marina 5 500 Joe|21|1|...,我整理了几个关键问题:
容器元素类型不匹配
m_hoteli是vector<CHotel>类型,但你调用push_back(str)时传入的是string对象,这完全不兼容!应该把构造好的CHotel对象传进去,改成:m_hoteli.push_back(temp);或者用
emplace_back直接在容器里构造对象,减少一次拷贝:m_hoteli.emplace_back(str);文件读取的细节优化
- 用
getline读取每行时,如果文件存在空白行,会创建空的CHotel对象,建议加判断跳过:while (getline(file, str)) { if (str.empty()) continue; // 跳过空白行 CHotel temp(str); m_hoteli.push_back(temp); } - 你抛出的是C风格字符串
"ERROR! ",建议改用C++标准异常类型,比如std::runtime_error,这样能携带更详细的错误信息:else throw std::runtime_error("无法打开文件: " + filename); - 其实
fstream对象离开作用域时会自动关闭文件,手动调用close()不是必须的,不过保留也没问题。
- 用
成员变量初始化效率问题
构造函数里直接用m_complex = nComplex;赋值,建议改用初始化列表初始化成员变量,这样能避免一次默认构造+赋值的开销:CComplex(string filename, string nComplex) : m_complex(nComplex) { // 剩下的文件读取代码 }关于注释掉的
operator>>尝试
你之前注释了while (file >> temp),说明你想通过重载operator>>来直接读取CHotel对象。如果要实现这个,需要在CHotel类中或全局范围定义这个运算符,比如假设每行的格式是名称 数字1 数字2,可以这么写:std::istream& operator>>(std::istream& is, CHotel& hotel) { string name; int num1, num2; is >> name >> num1 >> num2; // 把读取到的值赋值给hotel的成员变量(需要CHotel提供setter或者成员变量可访问) hotel.m_name = name; hotel.m_num1 = num1; hotel.m_num2 = num2; return is; }这样就能用
while (file >> temp)来循环读取了,这种方式会自动跳过空白符(包括换行),如果每行是一个完整的CHotel数据,用起来会比getline更简洁。
内容的提问来源于stack exchange,提问作者TimothyY

