0

One of the exercises in C++ Primer Plus is having me use fstream to open a txt file and input data into a structure then output it. First line of the txt file is the number of "donors". The problem I seem to be having is that (I think) when I use "inFile >> value;" to retrieve the number and then allocate the structure via new, its expecting an int and its getting a string? Is this correct? What should I be doing differently?

//ch6 p278 exercise #9
#include <iostream>
#include <cstring>
#include <fstream>
#include <cstdlib>
using namespace std;
const int SIZE = 60;
struct contributions
{
    char name[20];
    double dollars;
};

char filename[20];
string donors;
bool donated;

int main()
{
    char filename[SIZE];
    cout << "Enter name of file to scan: ";
    cin >> filename;
    fstream inFile;
    inFile.open(filename);
    if(!inFile.is_open())
    {
        cout << "Could not open the file " << filename << endl;
        cout << "Program terminating.\n";
        exit(EXIT_FAILURE);
    }
    inFile >> donors;
    contributions * ptr = new contributions[donors];
    for(int h = 0; h < donors; h++)
    {
        inFile >> ptr[h].name);
        inFile >> ptr[h].dollars);
    }
//BEGIN OUTPUT OF STRUCTURES
    cout << "GRAND PATRONS:\n";
    for(int i = 0; i < donors; i++)
   {
       if(ptr[i].dollars >= 10000)
       {
           cout << ptr[i].name << " donated " << ptr[i].dollars << endl;
           donated = true;
       }
   }
   if (!donated) {cout << "none.\n";}
   donated = false;
   cout << "PATRONS:\n";
   for(int i=0; i < donors; i++)
   {
       if(ptr[i].dollars < 10000)
       {
           cout << ptr[i].name << " donated " << ptr[i].dollars << endl;
           donated = true;
       }
   }
   if (!donated) {cout << "none.\n";}
   delete ptr;
    return 0;
}
1
  • Separate from the issue at hand, since you've used the array version of new to allocate ptr, you're going to need to use the array version of delete, like this: delete[] ptr; Commented Jul 24, 2009 at 16:49

3 Answers 3

2

What should I be doing differently?

Well, if the code is based on what C++ Primer Plus has taught you - use a different text book. I don't want to insult you, but the code is really poor. For example, has the book covered the std::string class?

I would recommend junking it, and getting Accelerated C++ by Koenig & Moo (two of the original C++ team) which will teach you modern, good, idiomatic C++.

Sign up to request clarification or add additional context in comments.

3 Comments

Not insulted at all. The code is a mash of my own code and pulling ideas from sample code in the book. It's covered string but I feel as if I'm missing something. Vector has also been mentioned, 280 pages in and it has yet to mention this. Looking at Accelerated C++ now...
In principle I second this, except for the fact that many find that "Accelerated C++" has too steep a learning curve. For those I recommend "C++ Primer" bay Lippman/Lajoie/Moo. (Note: no "Plus", but insist on at least the 3rd edition, where Barbara Moo joined the team!)
I read Lippmann's "C++ Primer" when it first came out (a long time ago now) and thought it went on and on about the most obvious things - I haven't read any but the first ed though. And perhaps I'm not the ideal test bed for C++ tutorials...
1

You are most certainly correct, I assume the code does not compile? You can just change the donors variable to an integer. The input streams are overloaded to work with all built in types, ie. bool, double, int etc.

The following will work, assuming the next value is an integer:

int numDonors;
inFile >> numDonors;

Note that the change to an integer is also necessary for the 'for' loops to work correctly, you are currently comparing a string to an integer, there is no built-in/default behavior for this.

Edit: I also noticed that when you delete your array of contributors you do:

delete ptr;

However, this will only clear out the first dynamically allocated block. The correct way to delete an array of dynamically allocated objects is:

delete [] ptr;

Edit 2: Thanks for the sample, so the reason it is not working correctly is the fact that the names are first and last, and the stream operator '>>' breaks on whitespace. So what is essentially happening is you first attempt to read the name, the stream reads the first name only and stops. Then you try to read the donated value, this attempts to read the last name as the value and cannot convert to an double so it returns 0.

3 Comments

It compiles now but when it reads the data from the file what its giving back is not correct.
As in your printed output is incorrect? I would need to see a sample of the input file to help more.
INPUT: 4 Sam Stone 2000 Freida Flass 100500 Tammy Tubbs 5000 Rich Raptor 55000 OUTPUT: Enter name of file to scan: 9.txt GRAND PATRONS: none. PATRONS: Sam donated 0 donated 0 donated 0 donated 0
0

donors is a string, and you are trying to use it as an array size:

string donors;
//...

inFile >> donors;
contributions * ptr = new contributions[donors];

You should make donors an int. Also it's usually better to use std::vector<> instead of manually messing with pointers to raw arrays. That would look something like this:

std::vector<contributions> contribs;
for (...) {
  contributions contrib;
  // .. Some way read contrib from inFile
  contribs.push_back(contrib);
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.