Search code examples
c++arraysfileinputstream

C++ Iterating File Input Into Class-Type Array


the following text reads in text from a vendors list file.

vendor.h

#include <iostream>
#include <fstream>
#include <cstdlib>

using namespace std;

class Vendor
{

public:
//data types
int VendorID;

string VendorName;
string VendorCity;
string VendorState;

int VendorZip;

//constructors
Vendor(int ID, string Name, string City, string State, int Zip){ VendorID = ID, VendorName = Name, VendorCity = City, VendorState = State, VendorZip = Zip;}
Vendor(){};

//desturcutor
~Vendor();

void SetID(int ID);
void SetName(string name);
void SetCity(string city);
void SetState(string state);
void SetZip(int zip);

};

#include "Vendor.h"

void main () 
{

Vendor VenList[150];

ifstream GetText;

GetText.open("VendorListFile.txt");


if (!GetText.is_open())
{

    cout << "File could not be opened" << endl;

    exit(EXIT_FAILURE);

}


while (GetText.good())
{

    cout << element << " ";
    GetText >> element;

}

}

obviously, the code can read in the text, but what I am looking to do now is iterate through each element and pass them to a constructor for the vendor class to build the elements into vendors that would be held in an array. I was thinking of doing this with a while loop like the following.

int counter = 150;
while (counter > 0)
{

 Vendor (name = [counter + 1], state = [counter + 2] ... );
 counter -= 5;

}

The next question would be assuming these construct, how would I reach these vendors in memory to index or move them around, and how do I make the program read in the elements 1 by 1 breaking at the spaces between the elements. The while loop is pseudo code so I imagine I made some syntax errors


Solution

  • Let's consider the following VendorListFile.txt:

    1 Intel Chicago IL 12345
    2 Dell Seattle WA 23456
    3 HP Paris FR 34567
    

    Note that given your current implementation (eg. fixed-size vendor array), this file should not exceed 150 lines or your program would crash while parsing it.

    Then you can use the following adjusted code to parse it, store the vendors as objects in the VenList array, and iterate through this array at your convenience:

    // Vendor.h
    #include <iostream>
    #include <fstream>
    #include <cstdlib>
    
    using namespace std;
    
    class Vendor
    {
    
    public:
    //data types
    int VendorID;
    
    string VendorName;
    string VendorCity;
    string VendorState;
    
    int VendorZip;
    
    //constructors
    Vendor(int ID, string Name, string City, string State, int Zip){ VendorID = ID, VendorName = Name, VendorCity = City, VendorState = State, VendorZip = Zip;}
    Vendor(){};
    
    //desturcutor
    ~Vendor();
    
    void SetID(int ID);
    void SetName(string name);
    void SetCity(string city);
    void SetState(string state);
    void SetZip(int zip);
    
    };
    
    ::std::istream & operator >> (::std::istream & stream, Vendor & vendor);
    ::std::ostream & operator << (::std::ostream & stream, const Vendor & vendor);
    
    // Vendor.cpp
    Vendor::~Vendor() {}
    
    ::std::istream & operator >> (::std::istream & stream, Vendor & vendor) {
        stream >> vendor.VendorID;
        stream >> vendor.VendorName;
        stream >> vendor.VendorCity;
        stream >> vendor.VendorState;
        stream >> vendor.VendorZip;
        return stream;
    }
    
    ::std::ostream & operator << (::std::ostream & stream, const Vendor & vendor) {
        stream << "ID: " << vendor.VendorID << ::std::endl;
        stream << "Name: " << vendor.VendorName << ::std::endl;
        stream << "City: " << vendor.VendorCity << ::std::endl;
        stream << "State: " << vendor.VendorState << ::std::endl;
        stream << "ZIP: " << vendor.VendorZip << ::std::endl;
        return stream;
    }
    
    // main.cpp
    int main ()
    {
    
    Vendor VenList[150];
    
    ifstream GetText;
    
    GetText.open("VendorListFile.txt");
    
    
    if (!GetText.is_open())
    {
    
        cout << "File could not be opened" << endl;
    
        exit(EXIT_FAILURE);
    
    }
    
    // Store the vendors as objects in the VenList array
    int nVendors = 0;
    GetText >> VenList[nVendors];
    
    while (GetText.good())
    {
    
            cout << VenList[nVendors];
            ++nVendors;
            GetText >> VenList[nVendors];
    
    }
    
    // Iterate the vendor objects from the VenList array
    for (int i = 0; i < nVendors; ++i) {
        cout << VenList[i];
    }
    
    return EXIT_SUCCESS;
    }
    

    I merged everything in one file for the sake of simplicity, feel free to organize the code in 3 files/add the necessary #includes if you wish.

    Note that we do not actually need to use a specialized constructor since 150 vendor objects were already constructed using the default constructor when we instantiated the VenList array. So instead, we modify these objects while reading the file using our overloaded >> operator.

    The code compiles and run fine with GCC 4.8.2 on Gentoo Linux. Running it gives the following output:

    ID: 1
    Name: Intel
    City: Chicago
    State: IL
    ZIP: 12345
    ID: 2
    Name: Dell
    City: Seattle
    State: WA
    ZIP: 23456
    ID: 3
    Name: HP
    City: Paris
    State: FR
    ZIP: 34567
    ID: 1
    Name: Intel
    City: Chicago
    State: IL
    ZIP: 12345
    ID: 2
    Name: Dell
    City: Seattle
    State: WA
    ZIP: 23456
    ID: 3
    Name: HP
    City: Paris
    State: FR
    ZIP: 34567
    

    In this example, vendors are printed twice: once from within your original parsing loop, and another time when iterating through the VenList array.

    The keys here are the functions:

    • ::std::istream & operator >> (::std::istream & stream, Vendor & vendor)
    • ::std::ostream & operator << (::std::ostream & stream, const Vendor & vendor)

    If you change the vendor class/file structure, you would need to adjust these functions appropriately.

    Hope that it helps.