【问题标题】:C++, How to read data from file and insert in container: MapC++,如何从文件中读取数据并插入到容器中:Map
【发布时间】:2018-10-16 02:10:27
【问题描述】:

我在使用信息填充容器地图时遇到问题。我用 operator>> 阅读了这些信息,但它在我的二等 CDealer 中给了我这些错误。 no operator ">>" matches these operandsbinary">>": no operator found which takes a right-hand operand of type 'const CStock'(or these is no acceptable conversion) 我有三个班级:拥有map<CStock, pair<unsigned, double>> Stock; 的CStock、CDealer 和拥有vector<CDealer*> Dealers; 的CShop 如果有人可以帮助我,我将非常感激。

这是我在 CStock 中的运算符 >

  ostream &operator << (ostream &toStream, const CStock &S){
        toStream << "Name Stock: " << S.m_strName_stock << " Producer: " << S.m_strProducer <<
            "Date: " << S.Date;

        return toStream;
    }

    istream &operator >> (istream &fromStream, CStock &S)
    {return fromStream >> S.m_strName_stock >> S.m_strProducer >> S.Date;}

这是我在 CDealer 中的运算符 > `

ostream &operator << (ostream &toStream, CDealer &D) 
{
    toStream << "Name Dealer: " << D.m_strName_Dealer << " Agent: " << D.m_strAgent <<
        "Address: " << D.m_strAddress;

    map<CStock, pair<unsigned, double>>::const_iterator it = D.Stock.begin();
    while (it != D.Stock.end())
    {
        toStream << it->first <<it->second.first << it->second.second;
    }
    return toStream;
}

istream &operator >> (istream &fromStream, CDealer &D)
{
    map<CStock, pair<unsigned, double>>::iterator it = D.Stock.begin();
    fromStream >> D.m_strName_Dealer >> D.m_strAgent >> D.m_strAddress;

    while (it!= D.Stock.end())
    {fromStream >> it->first >> it->second.first >> it->second.second;}
    return fromStream
}

这是带有参数的构造函数:文件名和这些运算符>

CShop::CShop(const string &fname)
{
    CDealer c;
    fstream File(fname, ios::in);
    if (File.is_open())
    {
        File >> m_strNameShop;
        File >> m_strCity;

        while (File>>c)
        {   
            Dealers.push_back(new CDealer(c));
        }
        File.close();   

    }

    else
        throw "ERROR! ";
}
ostream &operator << (ostream &toStream, const CShop &S)
{
    toStream << "Name Shop: " << S.m_strNameShop << " City: " << S.m_strCity;

    vector<CDealer* >::const_iterator it = S.Dealers.begin();


    while (it != S.Dealers.end())
    {
        CDealer* dealerPtr = *it++;
        toStream << *dealerPtr<< endl;
    }
    return toStream;
}
    istream &operator >> (istream &fromStream, CShop &D)
    {
        return fromStream >> D.m_strNameShop >> D.m_strCity;

    }

最后是 main()

#include"CDealer.h"
#include"CShop.h"
#include<iostream>
#include<string>
#include <stdlib.h>  
#include<vector>
using namespace std;

int main()

{
    CShop SS1("data.txt");
    cout << SS1;
    system("pause");
    return 0;
}

【问题讨论】:

  • 欢迎来到 StackOverflow。请查看How to Ask,并提供minimal reproducible example。照原样,这里有很多代码 - 其中大部分与您的问题完全无关。如果有一个简短的程序会有所帮助,直接指出问题。

标签: c++ c++11 stl containers


【解决方案1】:

istream &amp;operator &gt;&gt; (istream &amp;fromStream, CDealer &amp;D)的实现 考虑不周。

该函数的目标是从输入流中读取数据并充实CDealer 对象的内容。通常operator&lt;&lt;operator&gt;&gt; 函数协同工作,因此您使用operator&lt;&lt; 编写的内容可以使用operator&gt;&gt; 读回。

从这个角度来看,即使是 operator&lt;&lt; 函数也需要改进。

这是一个只要字符串对象中没有空格就可以工作的实现。如果您的字符串对象中有空格,则需要更改代码。

std::ostream& operator<<(std::ostream &toStream, CDealer cosnt& D) 
{
   // Write the name of the dealer, without any decorative text.
   // Add a space character to the output so you can read the name back.
   toStream << D.m_strName_Dealer << " ";

   // Do the same for name of the agent and address.
   toStream << D.m_strAgent << " ";
   toStream << D.m_strAddress << " ";

   // Write the number of items in Stock first.
   // This will be necessary when reading the data.
   toStream << D.Stock.size() << " ";

   // Now write the Stock items, which spaces between each field you write.
    map<CStock, pair<unsigned, double>>::const_iterator it = D.Stock.begin();
    while (it != D.Stock.end())
    {
        toStream << it->first << " " << it->second.first << " " << it->second.second << " ";
    }
    return toStream;
}

std::istream &operator>>(std::istream &fromStream, CDealer &D)
{
   // Read the name of the dealer.
   fromStream >> D.m_strName_Dealer;

   // Read the name of the agent.
   fromStream >> D.m_strAgent;

   // Read the address.
   fromStream >> D.m_strAddress;

   // Read the number of items.
   size_t num;
   fromStream >> num;

   // Now read the Stock items.
   for ( size_t i = 0; i < num; ++i )
   {
      // Obtained the types for key, val1, and val2 from
      // the error message posted in a comment by OP.
      CStock key;
      int val1;
      double val2;
      fromStream >> key >> val1 >> valu2;

      // Add the item to Stock.
      D.Stock.insert(std::make_pair(key, std::make_pair(val1, val2)));
   }

    return fromStream
}

【讨论】:

  • 很好,但它给了我这个错误: 严重性代码描述项目文件行抑制状态错误(活动)E0304 没有重载函数实例“std::map<_kty _ty _pr _alloc>: :insert [with _Kty=const CStock, _Ty=std::pair, _Pr=std::less, _Alloc=std::allocator<:pair cstock std: :pair int double>>>]" 匹配参数列表
  • @Kristiyan,您必须为keyval1val2 使用正确的类型。似乎key 的类型是CStockval1 的类型是intval2 的类型是double
  • @R Sahu 非常感谢!你太棒了!
【解决方案2】:

问题

问题可以归结为以下情况:

#include <map>
 
int main(void) {
    std::map<int, int> val;
 
    auto it = val.begin();
    it->first = 10;
}

std::map 中的键值为const(键值对定义为std::pair&lt;const Key, T&gt;),所以对于

 map<CStock, pair<unsigned, double>>

我们有一个包含pairs 的map

std::pair<const CStock, pair<unsigned, double>>

这使得it-&gt;first

fromStream >> it->first >> it->second.first >> it->second.second;

const CStock 并导致报告错误。

这一切都是有道理的,因为 map 是按密钥排序的,所以如果您可以随时更改密钥,map 很快就会变得不连贯。

Documentation on std::map

解决方案

没有简单的解决方案。你不能做这个。您必须要么制作项目,然后将它们放在map 中,要么使用emplace 系列函数之一直接在map 中构造它们。一旦它们在map 中,您就可以更改值,但不能更改键。您可以删除该项目,从而删除密钥,然后使用不同的密钥重新插入,但您为什么要这样做呢?我建议重新考虑您的逻辑。

【讨论】:

    猜你喜欢
    • 2023-03-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多