Solved

Read in Files.  Need some help..

Posted on 2003-11-23
13
332 Views
Last Modified: 2010-04-01
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
Comment
Question by:rbran1974
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
13 Comments
 

Expert Comment

by:Drew_Benton
ID: 9808403
""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
 

Author Comment

by:rbran1974
ID: 9808460
ok where i read in the array is there a better way of doing this.
0
 
LVL 4

Accepted Solution

by:
n_fortynine earned 53 total points
ID: 9809025
>>   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
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 17

Assisted Solution

by:rstaveley
rstaveley earned 52 total points
ID: 9810846
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
 
LVL 3

Expert Comment

by:RJSoft
ID: 9811589
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
 
LVL 2

Expert Comment

by:federal102
ID: 9812502
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
 
LVL 17

Expert Comment

by:rstaveley
ID: 9812553
>  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
 

Author Comment

by:rbran1974
ID: 9815484
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
 

Author Comment

by:rbran1974
ID: 9815504
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
 
LVL 17

Expert Comment

by:rstaveley
ID: 9816298
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
 
LVL 17

Expert Comment

by:rstaveley
ID: 9816303
> 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
 
LVL 9

Expert Comment

by:tinchos
ID: 10285754
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.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

When writing generic code, using template meta-programming techniques, it is sometimes useful to know if a type is convertible to another type. A good example of when this might be is if you are writing diagnostic instrumentation for code to generat…
IntroductionThis article is the second in a three part article series on the Visual Studio 2008 Debugger.  It provides tips in setting and using breakpoints. If not familiar with this debugger, you can find a basic introduction in the EE article loc…
The viewer will learn additional member functions of the vector class. Specifically, the capacity and swap member functions will be introduced.
The viewer will be introduced to the member functions push_back and pop_back of the vector class. The video will teach the difference between the two as well as how to use each one along with its functionality.

740 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question