开发者

C++ problem to write vector data to file

I want to write the content of the vector v to a file开发者_开发技巧. Problem is that not the content but the address will be placed inside the textfile.

When I write *pos inplace of &pos I get the error: error C2679: binary '<<' : no operator found which takes a right-hand operand of type 'entry'

How does it work correct?

#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <limits>

/*
Data.txt 

John
6543
23

Max
342
2

A Team
5645
23
*/

struct entry
{
    // passengers data
    std::string name;
    int weight; // kg
    std::string group_code; 
};

void reservations(std::vector<entry> v)
{
    std::ofstream outfile;
    outfile.clear();
    outfile.open("reservations.txt");
    // print data in vector
    std::vector<entry>::iterator pos;
        for (pos = v.begin(); pos!= v.end();++pos)
        {
            outfile << &pos << std::endl;
            std::cout << &pos << std::endl;
        }
    outfile.close();
}

entry read_passenger(std::ifstream &stream_in)
{
    entry passenger;
    if (stream_in)
    {
        std::getline(stream_in, passenger.name); 
        stream_in >> passenger.weight;
        stream_in.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
        std::getline(stream_in, passenger.group_code);
        stream_in.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
        return passenger;
    }

    return passenger; 
}

int main(void)
{
    std::ifstream stream_in("data.txt"); 
    std::vector<entry> v; // contains the reservations
    std::vector<entry> a; // contains the cancellations
    const int limit_total_weight = 10000;   // kg
    int total_weight = 0;                   // kg
    entry current;
    while (stream_in)
    {
        current = read_passenger(stream_in);
        if (total_weight + current.weight >= limit_total_weight)
        {
            // push data (cancellations) to vector
            a.push_back(current);
        }
        else
        {
            total_weight = total_weight + current.weight;
            // push data (reservations) to vector
            v.push_back(current);
        }
    }
    reservations(v); // write reservations to file
    std::cout << "Rest " << limit_total_weight - total_weight << "kg" <<std::endl;
    return 0;
}


You should overload operator << for entry:

std::ostream& operator << (std::ostream& o, const entry& e) 
{
   return o << e.name 
     << " " << e.weight 
     << " " << e.gruop_code;
}

Now you can write:

outfile << *pos << std::endl;
std::cout << *pos << std::endl;


First you were writing a pointer, and then you didn't tell C++ how an entry should be represented in text.

Create an operator<< overload for it.


Since entry is a plain struct, and you haven't defined any operator<< method to write its contents to an output stream, the compiler complains when you try to write out *pos directly.

Either you need to define a suitable operator<< method, or write out the members of the struct one by one, like

        outfile << pos->name << std::endl;
        outfile << pos->weight << std::endl;
        outfile << pos->group_code << std::endl;


Try something like:

std::ostream& operator<<(std::ostream& os,const entry& toPrint)
{
  os << "name :" << toPrint.name << '\n';
  os << "weight :" << toPrint.weight << "(kg) \n";
  os << "group_code :" << toPrint.group_code << '\n';
  return os;
}

also you may want change the signature of the reservation function to

void reservations(const std::vector<entry>& v)


The reason your output looks like addresses with the present code is because you're outputting the address of the iterator.

The reason why you get the error "no operator found which takes a right-hand operator of type 'entry'" is because there is no << operator which takes an entry as its right hand operand. You can easily define one:

std::ostream&
operator<<( std::ostream& dest, entry const& obj )
{
    dest << obj.name;
    return dest;
}

But this is a bit specialized; in other contexts, you might want to output other fields of entry. Classically, in fact, an operator<< for entry would output all relevant fields. An alternative solution would be to define a transformer functional object, and use it:

struct EntryToName
{
    std::string operator()( entry const& obj ) const
    {
        return obj.name;
    }
};

Then in reservations:

std::transform( 
    v.begin(), v.end(),
    std::ostream_iterator<std::string>( outfile, "\n" ),
    EntryToName() );

And BTW, it's generally considered preferrable to pass vectors by const reference, rather than by value.


You will either have to do outfile << pos->name << " " << pos->weight << /* etc */, or implement a output operator, operator<<.

It will look something like

   std::ostream& operator<<(std::ostream& os, const entry&) {
        return os << entry.name << " " << entry.weight << " " << entry.group_code;
   }

Format as needed.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜