/* internet2.cpp reads TCP/IP addresses from a file and produces a list 
 * of distinct addresses and a count of how many times each appeared 
 * in the file.  The addresses and counts are stored in a linked list.

 * Input (keyboard): name of file containing addresses
 * Input (file):     addresses
 * Output:           a list of distinct addresses and their counts
 ***********************************************************************/

#include <cassert>                // assert
#include <string>                 // string
#include <iostream.h>             // cin, cout, >>, <<
#include <fstream.h>              // ifstream, isopen()
#include <list>                   // list<T>
#include <algorithm>              // find

//--------------- Begin class AddressItem --------------------------------
class AddressItem
{
 public:
   void Read(istream & in)
   { in >> address; count = 0; }

   void Print(ostream & out) const
   { out << address << "\t occurs " << count << " times\n"; }

   void Tally()
   { count++; }

   friend bool operator==(const AddressItem & addr1,
                          const AddressItem & addr2);
 private:
   string address;
   int count;
};

inline bool operator==(const AddressItem & addr1,
                       const AddressItem & addr2)
{ return addr1.address == addr2.address; }

//----------------- End class AddressItem --------------------------------

typedef list<AddressItem> TCP_IP_List;

int main()
{
   string fileName;                       // name of file of TCP/IP addresses
   TCP_IP_List addressList;               // list of addresses

   ifstream inStream;                     // open stream to file of addresses
   cout << "Enter name of file containing TCP/IP addresses: ";
   cin >> fileName;
   inStream.open(fileName.data());
   assert(inStream.is_open());

   AddressItem item;                      // one of the addresses & its count
   for (;;)                               // loop:
   {
      item.Read(inStream);                //   read an address
      if (inStream.eof()) break;          //   if eof, quit

      TCP_IP_List::iterator it =          //   check if item already in list
         find(addressList.begin(), addressList.end(), item);
      if (it != addressList.end())        //   found
        (*it).Tally();                    //   increment its count
      else
        addressList.push_back(item);      //   else add it to the list
   }                                      // end loop

   cout << "\nList of addresses:\n\n";    // output the list
   for (TCP_IP_List::iterator it = addressList.begin();
                              it != addressList.end(); it++)
      (*it).Print(cout);
}

