-2

i'm trying to get this code working with no success the past week. Actually it is a mess and i don't know which way to run. Here's a part of my code:

void mfy_st(ifstream& FILE_E, ofstream& FILE_O)
{
    int option = 0;
    double amount;
    char unit;
    currency curr;

    cout<< "1- Enter cash \n"<<"2- Withdraw \n";
    cin>>option;

    switch(option)
    {
        case 1:
            cout<<"Enter the amount you would like to enter, followed by the unit: \n";
            open_file();
            cin>>amount>>unit;
            curr.amount = amount;
            curr.unit = unit;
            FILE_E<<curr.amount<<curr.unit;
            FILE_E.close();
            break;
        case 2: cout<<"Enter the amount you would like to withdraw, followed by the unit: \n";
            open_file();
            cin>>amount>>unint;
            curr.amount = amount;
            curr.unit = unit;
            FILE_O<<curr.amount<<curr.unit;
            FILE_O.close();
            break;
        default:
            cout<<"Option invalid";
            break;
    }
}

I'm having problem writing on the files. And the compiler throws error: no match for 'operator<<' (operand types are 'std::ifstream {aka std::basic_ifstream}' and 'double').

I know the code is a bit messy, I'll fix that when the program works! Hope you can help me.

ChrisD
  • 674
  • 6
  • 15
  • 1
    You need to put some sort of white space between the output otherwise you do not know where one ends and the other begins. ie `out << var1 << " " << var2;` – NathanOliver Feb 02 '16 at 17:32
  • Try std::cout or include std namespace – Suneesh Feb 02 '16 at 17:34
  • 2
    On problem is that reading should use `>>`, not `<<`. Like `FILE_E >> curr.amount >> curr.unit;` The operator points in the direction of the data flow. – Bo Persson Feb 02 '16 at 17:38
  • @Suneesh Not related, doesn't help. What's _" include std namespace"_ BTW? I hope you didn't mean `using namespace std;`. – πάντα ῥεῖ Feb 02 '16 at 18:33

3 Answers3

2

Serialization

Writing a structure or class to a file is called serialization. There are many libraries that do this for you, such as Boost.

Choose Your Format

There are many data formats to use for your data content, such as XML, INI, binary, CSV or other text format. Each has different strengths and weaknesses. For example, the binary method is a mirror image of the internal representation and may not be valid across all platforms. The XML language is more verbose, but can be read on many platforms and read by a text editor.

POD vs. non-POD contents

When using binary format, you can only write the entire structure if it contains only POD (Plain Old Data) types. Anything that uses a pointer, such as std::string or std::vector will not copy correctly because there is no guarantee that your program will have the same memory addresses when program is invoked again. Also, there is no guarantee that other platforms will use the same addressing scheme (for example, some platforms may use segmented memory addressing vs. linear).

Let the Structure Write its Members

Unless you have a serialization library, I recommend implementing methods in the structure or class that write the members to the stream (output) and read from the stream (input). The structure knows the details about its members, and the concept of data hiding should be followed.

Padding: Size of a Struct ?= Sum of members

Compilers are allowed to add spacing between members, usually for alignment purposes. If you are following a protocol, writing the structure may not follow the protocol because of the padding. In this case, the preferred method is to read or write each member individually to avoid padding issues (also the Little-Endian and Big-Endian issues can be handled this way too).

Summary

While debugging, choose a data format that is human readable by a text editor. Only change the format as necessary (such as efficiency or size), when necessary. Binary (internal respresentation) of numbers are more difficult to debug than their textual representations, especially floating point numbers.

The concept of reading and writing data structures is called serialization. Many libraries already exist that perform this functionality. If you are searching the data, you may want to consider using a database.

Thomas Matthews
  • 56,849
  • 17
  • 98
  • 154
1

Two problems with your code:

  1. You don't write appropriate delimiters:

     FILE_O << ' ' << curr.amount << ' ' << curr.unit << std::endl;
    
  2. You use the wrong operator to read the data in:

     FILE_E >> curr.amount >> curr.unit;
         // ^^             ^^
    

Also you should consider to provide implementations of the I/O operators for your struct currency:

 std::ostream& operator<<(std::ostream& os, const currency& curr) {
     os << ' ' << curr.amount << ' ' << curr.unit;
     return os;
 } 

 std::istream& operator>>(std::istream& is, currency curr) {
     is >> curr.amount >> curr.unit;
     return is;
 }

This will work with all kinds of streams.

πάντα ῥεῖ
  • 1
  • 13
  • 116
  • 190
0

Even though this is a trivial case, you might want to think about implementing this via operator overloading as described here.

This way, the functionality would be cleanly capsuled away and changes won't affect the calling code using this struct.

Community
  • 1
  • 1
tike
  • 2,234
  • 17
  • 19