Go Premium for a chance to win a PS4. Enter to Win

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 350
  • Last Modified:

Read in Files. Need some help..

This is a homework assignment so not looking for code to be given... I need to read in a file into an array of the voter class. Here is my code below it works tested it.  Just does not look right for some reason. Another question i use getline to read in whitespace if i want to write this to data file whats the best way to do.  What makes this class harder is that the teacher usually teachers us for 40 mins when its a 2 hr class...  Here is code:

#include "fileutil.cpp"

#include<iostream.h>
#include<conio.h>
#include<iomanip.h>
#include<string.h>
#include<ctype.h>
#include<fstream.h>

#if !defined(microsoft)
#include<stdlib.h>
#define cls() system("cls");
#endif

class Voter
{
      private:
            int idnumber;
            char lastname[25];
            char firstname[25];
            char party[2];
            int birthyear;
            int currentage;

      public:
            Voter();
            Voter(int,char[], char[], char[], int, int);
            Voter(const Voter&);
            void Read(Voter voterlist[],ifstream&, int);
            void print();
            ~Voter();
};

//*****************************************************************************
// Default Constructor                                                        *
//*****************************************************************************

Voter::Voter()
{
      idnumber = 0;
      lastname[0] = '\0';
      firstname[0] = '\0';
      party[2] = '\0';
      birthyear = 0;
      currentage = 0;
}

//*****************************************************************************
// Constructor Arguments                                                      *
//*****************************************************************************

Voter::Voter(int id,char ln[], char fn[], char pid[], int year, int by)
{
      idnumber = id;
      strcpy(lastname, ln);
      strcpy(firstname, fn);
      strcpy(party, pid);
      birthyear = year;
      currentage = 2003 - birthyear;
}

//*****************************************************************************
// Copy Constructor                                                           *
//*****************************************************************************

Voter::Voter(const Voter& v1)
{
      idnumber = v1.idnumber;
      strcpy(lastname, v1.lastname);
      strcpy(firstname, v1.firstname);
      strcpy(party, v1.party);
      birthyear = v1.birthyear;
      currentage = 2003 - v1.birthyear;
}


//*****************************************************************************
// ReadInData                                                                 *
//*****************************************************************************

void Voter::Read(Voter voterlist[], ifstream& infile, int arraysize)
{
      int  age,
             idnumber,
             birthyear,
             currentage = 0,
             numVoters  = 0;

      char lastname[25],
             firstname[25],
             party[2],
             trash[2];

      OpenInput( infile, "Give name of Data File:  " );

      while (infile.good() )
      {
            for ( int x = 0; x < arraysize; x++)
            {
            infile >> idnumber;
            infile.getline(trash,2);
            infile.getline(lastname,25,'\t');
            infile.getline(firstname, 25, '\t');
            infile.getline(party, 2, '\t');
            infile >> birthyear;
            age = 2003 - birthyear;

            voterlist[numVoters] = Voter(idnumber,lastname, firstname, party, birthyear, currentage);
            ++ numVoters;

            }

            if (infile.fail() )
                  break;
      }
      infile.close();

}


//*****************************************************************************
// Destructor                                                               *
//*****************************************************************************

Voter::~Voter()
{

}



void PrintList(Voter voterlist[], int);

void main()
{


const int arraysize = 8;
Voter voterlist[arraysize];

      ifstream infile;
      ofstream outfile;


}





void save(Voter voterlist

0
rbran1974
Asked:
rbran1974
2 Solutions
 
Drew_BentonCommented:
""This is a homework assignment so not looking for code to be given... I need to read in a file into an array of the voter class. Here is my code below it works tested it.  Just does not look right for some reason. Another question i use getline to read in whitespace if i want to write this to data file whats the best way to do.  What makes this class harder is that the teacher usually teachers us for 40 mins when its a 2 hr class...  Here is code""

1. What specifically does not look right?
2. I dont fully understand your 2nd question either...plz explain fully
3. Theres always mention of a homework help policy lol
0
 
rbran1974Author Commented:
ok where i read in the array is there a better way of doing this.
0
 
n_fortynineCommented:
>>   while (infile.good() )
>>     {
 >>         for ( int x = 0; x < arraysize; x++)
 >>         {
 >>         infile >> idnumber;
>>          infile.getline(trash,2);
>>          infile.getline(lastname,25,'\t');
>>          infile.getline(firstname, 25, '\t');
>>          infile.getline(party, 2, '\t');
>>          infile >> birthyear;
>>          age = 2003 - birthyear;
>>
>>          voterlist[numVoters] = Voter(idnumber,lastname, firstname, party, birthyear, currentage);
>>          ++ numVoters;
>>
>>          }
>>
>>          if (infile.fail() )
>>               break;
>>     }

How about:
   while (numVoters < arraysize && infile >> idnumber)
   {
          infile.getline(trash,2);
          infile.getline(lastname,25,'\t');
          infile.getline(firstname, 25, '\t');
          infile.getline(party, 2, '\t');
          infile >> birthyear;
          age = 2003 - birthyear;

          voterlist[numVoters] = Voter(idnumber,lastname, firstname, party, birthyear, currentage);
          ++ numVoters;
    }
0
Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

 
rstaveleyCommented:
An alternative to using getline with '\t' is to use a std::setw manipulator to set the maximum field width.

e.g.
        char firstname[24+1];
        infile >> std::setw(sizeof(firstname)) >> firstname;

However, the disadvantage with adopting this approach is that you can't have names with spaces in.

If you do go the manipulator route, with Josuttis's ignoreLine manipulator, you can do...

        infile >>  ignoreLine

...to eat up any remaining junk to the end of a line. The manipulator is defined as a template at http://www.josuttis.com/libbook/io/ignore.hpp.html . I like it.

This approach and your approach both need some additional handling in the event that you have an input field which is too large (e.g. a > 24 character name). In both cases, it will run into the next field.

Since all of your fields are delimited by '\t', I'd be inclined to tokenise the input line into std::strings:
--------8<--------
#include <iostream>
#include <vector>
#include <string>

int main()
{
      std::string str;
      while (getline(std::cin,str)) {
            std::vector<std::string> token;
            std::string::size_type pos1 = 0,pos2;
            while ((pos2 = str.find('\t',pos1)) != std::string::npos) {
                  token.push_back(str.substr(pos1,pos2-pos1));
                  pos1 = pos2+1;
            }
            /*if (!str.substr(pos1).empty())*/                                
                  token.push_back(str.substr(pos1));
            for (int i = 0;i < token.size();i++)
                  std::cout << "Token " << i+1 << ": " << token[i] << '\n';
      }
}
--------8<--------
You can then use the strings separately.

e.g.
      const int LastName = 0;        
      const int FirstName = 1;
      std::string lastName = token[LastName].substr(0,24);
      //...

I notice you are using deprecated headers (ones with .h), which may mean that you've got an old compiler, which predates support for namespaces. If so, you'll need to lose the std:: prefixes in this to get it to work on your compiler.
0
 
RJSoftCommented:
One thing about getline it does not stop until it gets the newline char. So putting a largish value like 100 or even 200 helps, otherwise you can get a messed up string if someone enters a large string.

RJ
0
 
federal102Commented:
I hope that you are just starting out in this class and that your teacher will demonstrate some knowledge of C++ rather than teaching C with classes. C++ has alot of functionality that would help with this code. Please do not take this a a put down on your code, but rather a commentary on the way that C++ is often taught. I experienced the same problemsa as you with an frequently absentee lecturer - luckily the TA's were excellent.

That being said I have updated your code a little to demonstrate some C++ tricks..

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

using namespace std; // used for brevity (actually bad form)



class Voter
{
     private:

          int idnumber;
          string lastname;  //use std::string vs C string - no need to worry about string length now
          string firstname;
          string party;
          int birthyear;
          int currentage;

     public:
          Voter();
          Voter(int,string &, string &, string &, int, int);
          Voter(const Voter&);
              //The Read function does not belong in the Voter class (IMHO)
          //void Read(Voter voterlist[],ifstream&, int);
          void print();
          ~Voter();
          friend ostream & operator << (ostream &o, Voter &v); // use to write to file
};

//*****************************************************************************
// Default Constructor                                                        *
//*****************************************************************************

Voter::Voter() //initialize instance via M.I.L. (member initialization list)
:idnumber(0),
 lastname(" "),
 firstname(" "),
 party(" "),
 birthyear(0),
 currentage(0){}


//*****************************************************************************
// Constructor Arguments                                                      *
//*****************************************************************************

Voter::Voter(int id, string &ln, string &fn, string &pid, int year, int by) // use M.I.L.
:idnumber(id),
 lastname(ln),
 firstname(fn),
 party(pid),
 birthyear(year)
{
     currentage = 2003 - birthyear;
}

//*****************************************************************************
// Copy Constructor                                                           *
//*****************************************************************************

Voter::Voter(const Voter& v1)
{
     idnumber = v1.idnumber; // can now use op =  vs C strcpy function
     lastname = v1.lastname;
     firstname = v1.firstname;
     party = v1.party;
     birthyear = v1.birthyear;
     currentage = 2003 - v1.birthyear;
}


//*****************************************************************************
// ReadInData                                                                 *
//*****************************************************************************

/*void Voter::Read(Voter voterlist[], ifstream& infile, int arraysize)
{
     int  age,
           idnumber,
           birthyear,
           currentage = 0,
           numVoters  = 0;

     char lastname[25],
           firstname[25],
           party[2],
           trash[2];

     OpenInput( infile, "Give name of Data File:  " );

     while (infile.good() )
     {
          for ( int x = 0; x < arraysize; x++)
          {
          infile >> idnumber;
          infile.getline(trash,2);
          infile.getline(lastname,25,'\t');
          infile.getline(firstname, 25, '\t');
          infile.getline(party, 2, '\t');
          infile >> birthyear;
          age = 2003 - birthyear;

          voterlist[numVoters] = Voter(idnumber,lastname, firstname, party, birthyear, currentage);
          ++ numVoters;

          }

          if (infile.fail() )
               break;
     }
     infile.close();

}*/


//*****************************************************************************
// Destructor                                                               *
//*****************************************************************************

Voter::~Voter()
{

}

void PrintList(Voter voterlist[], int);

ostream & operator << (ostream &o, Voter &v)
{
      return o << v.idnumber << "\t"
                   << v.lastname << "\t"
                   << v.firstname << "\t"
                   << v.party << "\t"
                   << v.birthyear;
}


int main() // main should always rturn int not void
{
  vector<Voter> voterlist; //use vector vs array (no need to know how many records are on file)
  string filename, trash, lastname, firstname, party, idnumber, birthyear, temp;
  int age = 0;

  cout << "Enter file name: ";
  cin >> filename;
  ifstream infile(filename.c_str());
  istream fin(infile);
  if(!infile)
  {
        cout << "File not found" << endl;
      return 0;
  }
  while(!fin.eof())
  {
      getline(fin, temp);
      istringstream ss(temp); // use istringstream to parse the file
      ss >> idnumber >> lastname >> firstname >> party >> birthyear;
      age = 2003 - atoi(birthyear.c_str()); // convert string to int (it's a C function - sometimes they're useful
      voterlist.push_back(Voter(atoi(idnumber.c_str()), lastname, firstname, party, atoi(birthyear.c_str()), age));
  }
      string outputfile;
      cout << "Enter name for output file: ";
      cin >> outputfile;

    ofstream outfile(outputfile.c_str());
      vector<Voter>::iterator i = voterlist.begin();
      while (i != voterlist.end())
      {
            outfile << *i << endl; //outputs records to file.
            ++i;
      }
      return 0;
}
0
 
rstaveleyCommented:
>  ss >> idnumber >> lastname >> firstname >> party >> birthyear;
>  age = 2003 - atoi(birthyear.c_str()); // convert string to int (it's a C function - sometimes they're useful

Or indeed go all the way and have birthyear as an int. Nice to lose the C :-)
0
 
rbran1974Author Commented:
Thanks for all the help so far.. I saw my teacher for the first time in almost 2 weeks.  Asked her if I could use vector for this project and she told me no.  So here is the question.  I need to be able to add another voter to the database.  How would i go about changing the array size if its defined as a constant. I cannot use a vector ( would make this easier).  

Also I cleaned up my code alittle.


#include "fileutil.cpp"

#include<iostream.h>
#include<conio.h>
#include<iomanip.h>
#include<string.h>
#include<ctype.h>
#include<fstream.h>

#if !defined(microsoft)
#include<stdlib.h>
#define cls() system("cls");
#endif

class voter
{

private:      
      int  idnumber;
      char lastname [25];
      char firstname[25];
      char party         [2];
      int  birthyear;
      int  currentage;

public:
      voter();
      voter(int,char[], char[], char[], int, int);
      voter(const voter&);
      void operator = (const voter&);
      void print();
      void disksave(ofstream& outfile);
      ~voter();

};


// =========================== Default Constructor =================================

voter::voter()
{
      idnumber       =   0;
      lastname [0]   = '\0';
      firstname[0]   = '\0';
      party    [0]   = '\0';
      birthyear      =   0;
      currentage     =   0;
}


// =========================== Constructor with Arguments ==========================

voter::voter(int id,char ln[], char fn[], char pid[], int year, int by)
{
      idnumber   = id;
      strcpy(lastname, ln);
      strcpy(firstname, fn);
      strcpy(party, pid);
      birthyear  = year;
      currentage = 2003 - birthyear;
}


// =========================== Copy Constructor ====================================


voter::voter(const voter& v1)
{
      idnumber   = v1.idnumber;
      strcpy(lastname, v1.lastname);
      strcpy(firstname, v1.firstname);
      strcpy(party, v1.party);
      birthyear  = v1.birthyear;
      currentage = 2003 - v1.birthyear;
}


// =========================== Assignment Operator  ================================

void voter::operator = (const voter& v1)
{
      idnumber   = v1.idnumber;
      strcpy(lastname, v1.lastname);
      strcpy(firstname, v1.firstname);
      strcpy(party, v1.party);
      birthyear  = v1.birthyear;
      currentage = 2003 - v1.birthyear;
}


// =========================== Display List of Voters  =============================

void voter::print()
{
      cout << idnumber    << setw(12)
              << lastname    << setw(12)
             << firstname   << setw(12)
           << party       << setw(12)
             << birthyear      << setw(12)
             << currentage  << setw(12)
         << endl;
}


// =========================== Save to File on Disk ================================

void voter::disksave(ofstream& outfile)
{
outfile  << idnumber    << setw(12)
              << lastname    << setw(12)
             << firstname   << setw(12)
           << party       << setw(12)
             << birthyear      << setw(12)
             << currentage  << setw(12)
         << endl;
}


// =========================== Destructor Argument  ================================

voter::~voter()
{

}



void getdata( voter voterlist[], int&, ifstream&);
void savefile(voter voterlist[], int , ofstream&);
void printreport( voter voterlist[], int);


void main()
{

      const int arraysize = 8;
              int error     = 0;
             
      voter voterlist[arraysize];
      
      ifstream infile;
      ofstream outfile;

      getdata (voterlist, error, infile);
      savefile(voterlist, error, outfile);
      
      //printreport(voterlist, error);



}


void getdata( voter voterlist[], int& error, ifstream& infile)
{
      int            age,
                  idnumber,
                  birthyear,
                  currentage  = 0,
                  numvoters   = 0;

      char    lastname[25],
                firstname[25],
                party[2],
                trash[2];

OpenInput( infile, "Give name of Data File:  " );

while (infile.good() )
{
      infile >> idnumber;
      infile.getline(trash,2);
      infile.getline(lastname,25,'\t');
      infile.getline(firstname, 25, '\t');
      infile.getline(party, 2, '\t');
      infile >> birthyear;
      age = 2003 - birthyear;

 if ((strcmp(party, "r") == 0) || (strcmp(party, "R") == 0)  ||
      ( strcmp(party, "d") == 0) || (strcmp(party, "D") == 0)  ||
      ( strcmp(party, "l") == 0) || (strcmp(party, "L") == 0)  ||
      ( strcmp(party, "c") == 0) || (strcmp(party, "C") == 0))
 {
      if ((idnumber > 1000) && ( idnumber < 10000))
      {
            if ((age > 17) && (age < 126))
            {
            voterlist[numvoters] = voter(idnumber,lastname, firstname, party, birthyear, currentage);
            ++ numvoters;
            }
            else
            error = error + 1;
            }
            else
            error = error + 1;
            }
            else
            error = error + 1;

      if (infile.fail())
      break;
}
infile.close();
}


void printreport(voter voterlist[], int error)
{

      for (int n = 0;n<(8 - error) ;n++)
      {
            voterlist[n].print();
      }
}


void savefile(voter voterlist[], int error, ofstream& outfile)
{
      OpenOutput(outfile);

      for (int n = 0;n<(8 - error) ;n++)
      {
            voterlist[n].disksave(outfile);
      }
}



0
 
rbran1974Author Commented:
another thing. when i read in the file if one of the elements in the feild dont meet the requirements i increment error by 1.  Then when i go to print the array i do  

for (int n = 0;n<(8 - error) ;n++)
     {
          voterlist[n].print();
     }

it works, but is there better way.
0
 
rstaveleyCommented:
Presumably, your teacher wants you not to use the standard library's std::string too.

If you need an array size to be determined at run run, you can use the new and delete[] operators.

e.g. For a name member of your class:

class X {
char *name;
public:
    X(const char *name)
    {
        X::name = new char[strlen(name)+1];
        strcpy(X::name,name);
    }
    ~X()
    {
        delete []name;
    }
};

If you've not yet covered new and delete in your course, you should simply make your arrays big enough for the worst case.

The voter array could be dynamically allocated to be an appropriate right size at run time using new and []delete, or - if you've reached that point in your course - you could construct a "linked list" of voters. However, if your teacher has yet to introduce you to the standard library's vector<>, I assume that you won't be able to use the standard library's list<>, which presumable means you'd need to implement your own lined list, which is something that C programmers dirty their hands with.
0
 
rstaveleyCommented:
> when i read in the file if one of the elements in the feild dont meet the requirements i increment error by 1

It would be more normal to have a flag in the class to indicate that whichever field was corrupt. Alternatively, don't load the array with that class.
0
 
tinchosCommented:
No comment has been added lately, so it's time to clean up this TA.
I will leave the following recommendation for this question in the Cleanup topic area:

Split: n_fortynine {http:#9809025} & rstaveley {http:#9816303}

Please leave any comments here within the next seven days.
PLEASE DO NOT ACCEPT THIS COMMENT AS AN ANSWER!

Tinchos
EE Cleanup Volunteer
0

Featured Post

Free Tool: Subnet Calculator

The subnet calculator helps you design networks by taking an IP address and network mask and returning information such as network, broadcast address, and host range.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

Tackle projects and never again get stuck behind a technical roadblock.
Join Now