I need to use a class for a program that reads an input file, prints the file, sorts the list then prints the sorted list. This is for a Programming II class. I can see how to print and sort. My issue is the input file and the array. I am trying to make the array a part of the class. What I am trying to do is dynamically allocate the array as a part of the class. I am imagining a member function List.read where the input file will be processed into the array. Is this too complicated for this level? Should I just make the array part of the int main() and pass the array to the member function? Do you actually "pass" the ifstream object to the member function or just have the member function contain the code to access the input file? If the array is a part of the class, then a destructor needs to delete the dynamic memory object, right? If you need code I will post it but I have not really reached a "finish point" yet. I am trying to determine if it is a waste of my time to try it this way.

Ok, I have made a lot of "progress" but I am running into problems everywhere. I got the program to work from a single source file (without the class). Then I began moving stuff to the class and trying to get it to work. The first problem is that I have removed the array from the class but this does not leave any real data in the class. The class is now just a collection of member functions to manipulate the array. This doesn't seem right so I must assume that there is a good way to read the input file from the header file or "pass" the input file to the class header. Also, I cannot get the header file to recognize the output file to write the output even though I have moved that definition to above the int main() (this is how I thought a global variable is declared). I have much to learn if anyone can teach me. Sorry for the length of this post but there are three files involved (not counting the input and output files which can be simulated with any collection of integers). Here goes:

Source.cpp

#include <iostream>
#include <fstream>
#include <string>
#include <iomanip>
#include <cstdlib>
#include "datalist.h"
using namespace std;

void swap(int, int);

struct CommandLineException
{
CommandLineException(int max, int actual)
  {
    cout << endl << "Too many command line arguments." << endl;
    cout << "A maximum of " << max << " arguments are permitted." << endl;
    cout << actual << " arguments were entered." << endl;
  }
};

struct FileException
{
  FileException(char* fn)
  {
    cout << endl << "File " << fn << " could not be opened." << endl;
  }
};

char ifn[255], ofn[255];
ifstream j(ifn);
ifstream i(ifn);
ofstream o(ofn);

int main(int argc, char* argv[])
{

  if(!j) throw FileException(ifn);
  if(!i) throw FileException(ifn);
  if(!o) throw FileException(ofn);

  try
  {
    switch(argc)
    {
      case 1:
        cout << "Enter the input file name. ";
        cin >> ifn;
        cout << "Enter the output file name. ";
        cin >> ofn;
        break;
      case 2:
        strcpy(ifn, argv[1]);
        cout << "Enter the output file name. ";
        cin >> ofn;
        break;
      case 3:
        strcpy(ifn, argv[1]);
        strcpy(ofn, argv[2]);
        break;
      default:
        throw CommandLineException(2, argc - 1);
        break;
    }

    int* counta = new int;
    *counta = 0;
    int testmsg;

    while (j >> testmsg)
    {
      *counta++;
    }
    const int SIZE = *counta;
    delete counta;
    int* data = new int[SIZE];
    int* countb = new int;
    *countb = 0;
    while (i >> data[*countb])
    {
      *countb++;
    }
    delete countb;

    o << "The input file originally contained values in this order: \n";
/*    for (int a = 0; a < SIZE; a++)
    {
      o << data[a] << " ";
    }*/
    datalist info(data, SIZE);
    info.print(data, SIZE);

    o.close();
    i.close();
    delete[] data;
  }

  catch(...)
  {
    cout << "Program terminated." << endl;
    exit(EXIT_FAILURE);
  }

  return 0;
}

void swap(int& x, int& y)
{
  int temp = x;
  x = y;
  y = temp;
}

header.cpp

#include <iostream>
#include <fstream>
#include <string>
#include <iomanip>
#include <cstdlib>
using namespace std;
#include "datalist.h"

    datalist::datalist(int data[], int size)
    {
      data = new int[size];
    }
void datalist::bubbleSort(int data[], int size)
{
  for (int i = 0; i < size-1; i++)
  {
    bool swapped = false;
    for (int k = 0; k < size-1-i; k++)
    {
      if (data[k] > data[k+1])
      {
        swap(data[k], data[k+1]);
        swapped = true;
      }
    }
    if (!swapped) break; // all sorted
  }
}

void datalist::print(int data[], int size)
{
  for (int i = 0; i < size; i++)
    o << data[i] << " ";

  o << endl;
}

header.h

#include <iostream>
#include <fstream>
#include <string>
#include <iomanip>
#include <cstdlib>
using namespace std;

#ifndef datalist_h
#define datalist_h

class datalist
{
  private:

  public:
    datalist(int[], int);
    void print(int[], int);
    void bubbleSort(int[], int);
};

#endif

PS. I have a feeling that some of the stuff that seems to be working is not correct either, i.e., I had to create a constructor which is declaring a new dynamic array but I have only one delete[]. Also, I am sure that the header.cpp and header.h don't need all of the include files (or the main for that matter). Anyways, any problems you can find please help me understand the way it is supposed to work so that next time someone asks, it won't be me.

Edited 3 Years Ago by diafol: fixed formatting

Moving the ifstream and ofstream outside of int main() seems to have caused more problems than I thought. The program compiles but now the files will not open and the program fails. (I tested by changing the header.cpp from o << data to cout << data just to get it to compile). More work! YEAH!!

Believe it or not, I am STILL up trying to solve this one. I have now been working for over 14 hours, looking in my books and online, and have not found an answer. Maybe this is harder than I thought? I decided that I will probably switch to a vector just for the easier memory management. I thought that there was something in the assignment about using an array but there wasn't. I still have the same problem though. The ifstream and ofstream are declared in int main() like in the instructor's examples and I cannot find a way to "pass" these to the class. I assume that I will have to populate the vector in int main and then pass the vector by reference (not sure of the syntax for this one but I can look this up easy enough, I think) to the class. That still leaves a problem with making a member function such as classobj.print to send the output to the output file designated in int main. Can anyone please teach me the C++ tools to do this?

My thought is that you're overworking this.
Unless you're committed to linked lists, use a vector. It's comfortable and easy to wear.

The operator overloads required to implement a vector provide a convenient 'on read' sorting system. If possible, before you add to the vector, use the overloaded operators < and == to see where to place the new entry. Then, 'Set it and forget it'.

Dynamic allocation of arrays is tricky, particularly if you don't know the size that the array needs before you start reading in entries from the file. Best to avoid this scenario if at all possible. Also, Narue sez bubblesort is teh ebil. If you can avoid it, you probably should.

My suggestion: Start over.
1. Make a class for a single data entry.
2. Declare a vector of that classes in main. An iterator for the vector will also be helpful.
3. Open the file (check for success)
4. Read the file into the vector.
5. Sort the vector.

Drowzee

Thank you for taking the time to look at this for me and give me some feedback. I agree that this is harder than it needs to be. With such a simple problem I can easily do this with a single source code (that's how I started, in fact). The impression that I received (although not explicitly stated) is that the class is suposed to function as the main storage and manipulation tool. That raises these concerns for me:

>> 1. Make a class for a single data entry.
Would this be like cheating the requirement for a class? In this instance the class would be nothing more than a single int value that should not be changed in any way. It would be essentially the same as not using a class, wouldn't it?

>>use the overloaded operators < and == to see where to place the new entry.
This should work. I have to print the file in the same format as it is read before I sort it but I could just add one line in the loop to accomplish that I would think, so this is workable if the vector is placed in int main and directly manipulated. That refers back to my original reservation with this solution.

>>Dynamic allocation of arrays is tricky, particularly if you don't know the size that the array needs before you start reading in entries from the file
By using the second ifstream obj on the same input file I read the file through once and counted it before I created the array/vector so I have the size determined (May be inefficient. Will ifstreamobj.clear() clear the actual input.dat or just the buffer for the file I just read in? This may be more efficient than an second ifstream object)

>>Narue sez bubblesort is teh ebil
You are both correct. However, the professor's example uses a selection sort which really isn't any better and I confirmed that we can use any sort we prefer. I just went with bubblesort because it has been more common in my previous classes.

Please don't feel that your input is unappreciated. I thank you very much for your time. I have already changed to a vector instead of an array so your advise was usful (although my all-nighter caused me to try this in desperation before the normal hours most people keep). I just have reservations about using the class to store single values because I feel that I will be accused of dodging the reason for using a class (a class was specified as a requirement of the assignment). If you have any other suggestions, I would love to hear them. I know from reading many threads searching for the answer that you are much more educated in the language (and concepts) than I am so I value your input.

No offense taken. I'm finally out of college, and I've been taken to task a few times at work for doing things in a needlessly complex way.

I'd think reading the file twice is not efficient, but I've been primarily working with C, so I can't say if that's true or not. I'd read once until there was no more to read, then take stock of the data.

My suggested method comes from me doing pretty much the same thing (no sorting yet), but with a much more complex data structure. I'd argue that if the int were a struct or another class, then creating a class vector would make the entire dataset easier to access.

Thank you. I actually have the code working the way I originally wanted. I went back and got it all working in a single source file again and then just cut and pasted into the seperated files that we were required to use for data hiding. It required slight modifications from there but I finally got it. Now I just have to get my output formatting working the way we are supposed to and it will be ready. Thanks again.

This article has been dead for over six months. Start a new discussion instead.