Wrox Programmer Forums
|
BOOK: Professional C++, 2nd Edition
This is the forum to discuss the Wrox book Professional C++, 2nd Edition by Marc Gregoire, Nicholas A. Solter, Scott J. Kleper ; ISBN: 978-1-1181-6995-7
Welcome to the p2p.wrox.com Forums.

You are currently viewing the BOOK: Professional C++, 2nd Edition section of the Wrox Programmer to Programmer discussions. This is a community of software programmers and website developers including Wrox book authors and readers. New member registration was closed in 2019. New posts were shut off and the site was archived into this static format as of October 1, 2020. If you require technical support for a Wrox book please contact http://hub.wiley.com
 
Old May 14th, 2016, 10:49 PM
Authorized User
 
Join Date: Nov 2014
Posts: 91
Thanks: 2
Thanked 1 Time in 1 Post
Default Chapter 15 Demystifying C++ I/O

Marc,

Storing a class object in a container is temporary, and all data is lost when the program terminates. How do you store a class object data in a file and read that data afterwards? Say, the data members are two strings (e.g., mFirstName and mLastName) and a character (e.g. mMiddleInitial).
 
Old May 15th, 2016, 07:01 AM
Wrox Author
 
Join Date: Mar 2011
Posts: 49
Thanks: 0
Thanked 4 Times in 4 Posts
Default

On page 559, there is a section called "Input and Output with Objects" that explains how to add support for operator<< and >> to your own objects.
With these you can then stream your objects to for example a file stream discussed elsewhere in the same chapter.
 
Old May 15th, 2016, 03:43 PM
Authorized User
 
Join Date: Nov 2014
Posts: 91
Thanks: 2
Thanked 1 Time in 1 Post
Default Chapter 15 Demystifying C++ I/O

Sorry Marc, but I was not able to put the pieces together. I need to see an explicit example.
I modified the void output() method to write to a file. It is shown in the code as boldfaced.
Now, how do you read the Muffin.txt file?
Code:
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>

using namespace std;

class Muffin 
{
    public:
        string    getDescription() const;
        void      setDescription(const string& inDesc);
        int       getSize() const;
        void      setSize(int inSize);
        bool      getHasChocolateChips() const;
        void      setHasChocolateChips(bool inChips);

        void      output();
    protected:
        string    mDesc;
        int       mSize;
        bool      mHasChocolateChips;
};

string Muffin::getDescription() const { return mDesc; }
void Muffin::setDescription(const string& inDesc) { mDesc = inDesc; }
int Muffin::getSize() const { return mSize; }
void Muffin::setSize(int inSize) { mSize = inSize; }
bool Muffin::getHasChocolateChips() const { return mHasChocolateChips; }
void Muffin::setHasChocolateChips(bool inChips) { mHasChocolateChips = inChips; }

void Muffin::output()
{
	ofstream outFile("Muffin.txt", ios::out | ios::app);
        if(!outFile.is_open()) {
             cerr << "File could not open!";
             return;
        }
	outFile << getDescription().c_str() << getSize() << getHasChocolateChips() << '\n';
	outFile.clear();
	outFile.close();
}

Muffin createMuffin(istringstream& inStream);

int main()
{
  cout << "First, let's create a muffin in code and output it." << endl;

  Muffin m;
  m.setDescription("Giant_Blueberry_Muffin");
  m.setSize(42);
  m.setHasChocolateChips(false);

  m.output();

  cout << "Now we'll create a muffin from a string stream" << endl;

	istringstream instream("My_Muffin 2 true");
  Muffin m2 = createMuffin(instream);

  m2.output();

  return 0;
}

Muffin createMuffin(istringstream& inStream)
{
  Muffin muffin;
  // Assume data is properly formatted:
  // Description size chips

  string description;
  int size;
  bool hasChips;

  // Read all three values. Note that chips is represented
  // by the strings "true" and "false"
  inStream >> description >> size >> boolalpha >> hasChips;
  muffin.setSize(size);
  muffin.setDescription(description);
  muffin.setHasChocolateChips(hasChips);

  return muffin;
}

The output in the Muffin.txt file was as follows:
Code:
Giant_Blueberry_Muffin420
My_Muffin21

Last edited by phztfte1; May 15th, 2016 at 06:48 PM.. Reason: Correct editorial error and added check if file opened.
 
Old May 16th, 2016, 04:08 AM
Wrox Author
 
Join Date: Mar 2011
Posts: 49
Thanks: 0
Thanked 4 Times in 4 Posts
Default

You'll have to format the data in such a way that you can read it back.
If you look at the createMuffin() method, you see that it is able to parse/read muffins formatted as follows:
Muffin_Name Size Chips
So, name followed by a space, followed by the size, a space and true or false for the chocolade chips.
If you want to use createMuffin to read data from a file, then you should modify output() to write it in that format. So, for example:
Code:
void Muffin::output()
{
	ofstream outFile("Muffin.txt", ios::out | ios::app);
        if(!outFile.is_open()) {
             cerr << "File could not open!";
             return;
        }
	outFile << getDescription() << " " << getSize() << " " << boolalpha << getHasChocolateChips() << '\n';
}
Some notes:
* No need for the clear() or close(). The file is automatically closed.
* booalpha is used to write true/false instead of 1/0
* no need for the .c_str() when writing a std::string to a C++ stream.
* This obviously only works if there are no spaces in the name of the muffin. If you want to support spaces in the name, then you can take a look at the quoted manipulator. (see https://msdn.microsoft.com/en-us/library/dn986842.aspx)
 
Old May 18th, 2016, 11:30 PM
Authorized User
 
Join Date: Nov 2014
Posts: 91
Thanks: 2
Thanked 1 Time in 1 Post
Default Chapter 15 Demystifying C++ I/O

Hi Marc,

I revised the output() method as you suggested and added an input() method. The input() method does not work but at least, it is a start.
1. The input() method does not read the bool value for chips correctly. Instead of reading false, it shows true.
2. The exercise raises a question: how do you get to read the next record?

Code:
include <iostream>
#include <sstream>
#include <string>
#include <fstream>

using namespace std;

class Muffin 
{
    public:
        string    getDescription() const;
        void      setDescription(const string& inDesc);
        
		int       getSize() const;
        void      setSize(int inSize);
        
		bool      getHasChocolateChips() const;
        void      setHasChocolateChips(bool inChips);

        void      output();
		void	  input();
    protected:
        string    mDesc;
        int       mSize;
        bool      mHasChocolateChips;
};

string Muffin::getDescription() const { return mDesc; }
void Muffin::setDescription(const string& inDesc) { mDesc = inDesc; }
int Muffin::getSize() const { return mSize; }
void Muffin::setSize(int inSize) { mSize = inSize; }
bool Muffin::getHasChocolateChips() const { return mHasChocolateChips; }
void Muffin::setHasChocolateChips(bool inChips) { mHasChocolateChips = inChips; }

void Muffin::output()
{
  printf("%s, Size is %d, %s\n", getDescription().c_str(), getSize(),    
     (getHasChocolateChips() ? "has chips" : "no chips"));

  ofstream outFile("Muffin.txt", ios::out | ios::app);
  if (!outFile) {
	  cerr << "File could not open!" << endl;
	  return;
  }
  outFile << getDescription() << '^' << getSize() << '^' << boolalpha << getHasChocolateChips() << '\n';
}


void Muffin::input()
{
	string description;
	int size;
	bool chips;

	ifstream inFile("Muffin.txt", ios::in);
	if (!inFile) {
		cerr << "File could not open!" << endl;
		return;
	}
		getline(inFile, description, '^');
		inFile >> size;
		inFile >> chips;
		cout << "inFile: " << description << " " << size << " " << boolalpha << chips << endl;
}


Muffin createMuffin(istringstream& inStream);

int main()
{
  cout << "First, let's create a muffin in code and output it." << endl;

  Muffin m;
  m.setDescription("Giant Blueberry Muffin");
  m.setSize(42);
  m.setHasChocolateChips(false);
  m.output();

  cout << "Now we'll create a muffin from a string stream" << endl;
  istringstream instream("My_Muffin 2 true");
  Muffin m2 = createMuffin(instream);
  m2.output();

  Muffin muff;
  muff.input();

  return 0;
}

Muffin createMuffin(istringstream& inStream)
{
  Muffin muffin;
  // Assume data is properly formatted:
  // Description size chips

  string description;
  int size;
  bool hasChips;

  // Read all three values. Note that chips is represented
  // by the strings "true" and "false"
  inStream >> description >> size >> boolalpha >> hasChips;
  muffin.setSize(size);
  muffin.setDescription(description);
  muffin.setHasChocolateChips(hasChips);

  return muffin;
}
Here are the contents of the text file.
Code:
Giant Blueberry Muffin^42^false
My_Muffin^2^true
 
Old May 19th, 2016, 02:00 PM
Wrox Author
 
Join Date: Mar 2011
Posts: 49
Thanks: 0
Thanked 4 Times in 4 Posts
Default

One option is to write them as follows:
Code:
outFile << quoted(getDescription()) << ' ' << getSize() << ' ' << boolalpha << getHasChocolateChips() << '\n';
Note that I'm using the quoted() manipulator and replaced the ^ with spaces.
The following is then one way to read the data back:
Code:
	while (!inFile.eof())
	{
		description = "";
		inFile >> quoted(description);
		if (description.empty())
		{
			break;
		}
		inFile >> size >> boolalpha >> chips;
		cout << "inFile: " << description << " " << size << " " << boolalpha << chips << endl;
	}
 
Old May 19th, 2016, 10:20 PM
Authorized User
 
Join Date: Nov 2014
Posts: 91
Thanks: 2
Thanked 1 Time in 1 Post
Default Chapter 15 Demystifying C++ I/O

Marc,

I did not use quoted because when I read the documentation it was for Visual Studio 2015 and new to C++14. There is a red squiggly line under quoted even though the header file <iomanip> was added. I use Visual Studio 2013 Professional which does not implement C++14.

So, how does one do it without quoted?
 
Old June 1st, 2016, 01:40 PM
Wrox Author
 
Join Date: Mar 2011
Posts: 49
Thanks: 0
Thanked 4 Times in 4 Posts
Default

Just try to remove the quoted() then.
In that case of course, the name cannot contain spaces.
If you do want to support spaces, then you'll have to do some more parsing yourself, for example by quoting it yourself.
 
Old June 3rd, 2016, 09:58 AM
Authorized User
 
Join Date: Nov 2014
Posts: 91
Thanks: 2
Thanked 1 Time in 1 Post
Default Chapter 15 Demystifying C++ I/O

Say my data members were an int and a double. When writing to a text file, are ithe int and double converted to text?
 
Old June 4th, 2016, 09:35 AM
Wrox Author
 
Join Date: Mar 2011
Posts: 49
Thanks: 0
Thanked 4 Times in 4 Posts
Default

If you write them with operator <<, then yes, they are converted to text.





Similar Threads
Thread Thread Starter Forum Replies Last Post
More Help with chapter 15 happyandstable BOOK: Beginning ASP.NET 4 : in C# and VB 3 March 12th, 2012 03:19 AM
chapter 15 help kyledonmoyer BOOK: Beginning PHP5, Apache, and MySQL Web Development ISBN: 978-0-7645-7966-0 2 June 30th, 2007 08:06 AM
Chapter 15 rrlevron BOOK: Beginning ASP 3.0 0 November 17th, 2005 03:38 PM
chapter 15 manal_sag BOOK: Beginning ASP 3.0 0 April 22nd, 2005 02:23 PM
Chapter 15 moggie BOOK: Beginning ASP 3.0 2 October 19th, 2004 01:30 PM





Powered by vBulletin®
Copyright ©2000 - 2020, Jelsoft Enterprises Ltd.
Copyright (c) 2020 John Wiley & Sons, Inc.