/* This program 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>
#include <string>
#include <iostream>
#include <fstream>
#include <list>
#include <algorithm>
using namespace std;

//--------------- 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);
}
