/* This program performs a variety of processing tasks for a file about cities

   File:  /home/walker/c/files/city-file.c
   Author:  Henry M. Walker
   Last Revised:  2 May 2005

*/

#include <stdio.h>

#define Max 80
#define TextFileName "/home/walker/c/files/city.dat"

struct CityData {
  char name[Max];
  char county[Max];
  char state[Max];
  int year;
  int pop;
  int area;
  int phone;
  int radio;
  int tv;
};

void readLine (FILE *cityFile, char * line);
/* This procedure reads a line from the given file, replacing
   any final end-of-line character by a NULL */

void displayCities ();
/* This procedure displays the city data from a text file on the screen */

void readCity (FILE * cityFile, struct CityData *city);
/* This procerdure reads a single city's worth of data from the file */

void printCity (struct CityData city);
/* This procedure prints information on a given city */

void incorporated ();
/* This procedure prints the names of all cities incorporated before 1855*/ 

void media ();
/* This procedure computes the city with the lowest per capita number
   of radio and TV stations*/

int main (void) {
  char option;
  printf ("This program processes data on cities in various ways");

  while (1) {
    printf ("\n");;
    printf ("Menu Options\n");
    printf ("    D - Display data from Text File\n");
    printf ("    I - Find cities incorporated 150 years ago\n");
    printf ("    M - Find city with fewest radio and TV stations\n");
    printf ("    Q - Quit\n");
    printf ("Enter desired option:  ");
    scanf (" %c", &option);
    switch (option) 
      { case 'd':
        case 'D':  
          displayCities ();
          break;
        case 'i':
        case 'I': 
          incorporated ();
          break;
        case 'm':
        case 'M': 
          media ();
          break;
          break;
        case 'q':
        case 'Q': 
          printf ("Program terminated\n");
          return ;
          break;
      default:  printf ("Invalid Option\n");
      }
  }
  return 0;
}

void displayCities () {
  /* This procedure displays the city data from a text file on the screen */
  FILE *cityFile;
  struct CityData city;
    
  printf ("\nThe city data are shown below: \n\n");
  cityFile = fopen (TextFileName, "r");
  readCity (cityFile, &city);

  while (city.state[0] != EOF)  {
    printCity (city);
    readCity (cityFile, &city);
  }
  fclose (cityFile);
}

void readLine (FILE *cityFile, char * line) {
/* This procedures reads a line from the given file, replacing
   any final end-of-line character by a NULL  */
  char * pos;

  if (feof (cityFile))
    line[0] = EOF;
  else
    fgets (line, Max, cityFile);

  if ((pos = strchr (line, '\n')) != NULL) {
    *pos = 0;
  }
    
}

void readCity (FILE * cityFile, struct CityData *city) {
  /* This procedure reads one city record from a file */
  char ch;
  readLine (cityFile, (*city).name);
  readLine (cityFile, (*city).county);
  readLine (cityFile, (*city).state);
  if ((*city).state[0] != EOF) 
   {
     char line[Max];
     readLine (cityFile, line);
     sscanf (line,"%d", &(*city).year);
     readLine (cityFile, line);
     sscanf (line,"%d", &(*city).pop);
     readLine (cityFile, line);
     sscanf (line,"%d", &(*city).area);
     readLine (cityFile, line);
     sscanf (line,"%d", &(*city).phone);
     readLine (cityFile, line);
     sscanf (line,"%d", &(*city).radio);
     readLine (cityFile, line);
     sscanf (line,"%d", &(*city).tv);

    /* read blank line at end of city */
     readLine (cityFile, line);
  }
}

void printCity (struct CityData city) {
  /* This procedure prints information on a given city */
  printf ("%s, %s\n", city.name, city.state);
  printf ("     County:  %s\n\n", city.county);
  printf ("     Year                                      ");
  printf ("    Area     Radio      TV\n");
  printf ("     Incorporated     Population     Telephones");
  printf ("    (km)   Stations  Stations\n");
  printf ("%13d %16d %14d %9d %7d %9d\n\n", 
          city.year, city.pop, city.phone, city.area, city.radio, city.tv);
}

void incorporated () {
  /* This procedure prints the names of all cities incorporated before 1855*/ 
  FILE *cityFile;
  struct CityData city;
    
  printf ("\nThe following cities were incorporated before 1855\n\n");
  cityFile = fopen (TextFileName, "r");
  readCity (cityFile, &city);

  while (city.state[0] != EOF)  {
    if (city.year < 1855)
      printCity (city);
    readCity (cityFile, &city);
  }

  fclose (cityFile);
}

void media () { 
  /* This procedure computes the city with the lowest per capita number
     of radio and TV stations*/
    printf ("\n   Processing Radio and TV Data\n\n");

  FILE *cityFile;
  struct CityData city;

  char lowestCityName [Max];
  double lowestCityRatio, nextCityRatio;
    
  cityFile = fopen (TextFileName, "r");

  /* keep track of city with lowest per capita number of those read so far */
  readCity (cityFile, &city);
  if (city.state[0] == EOF)  {
    printf ("The file is empty; no cities found\n");
  }
  else {
    strcpy (lowestCityName, city.name);
    lowestCityRatio = (double)(city.radio + city.tv) / (double) city.pop;

    readCity (cityFile, &city);
    while (city.state[0] != EOF)  {
      nextCityRatio =(double)(city.radio + city.tv) / (double) city.pop;
      if (nextCityRatio < lowestCityRatio) {
        strcpy (lowestCityName, city.name);
        lowestCityRatio = nextCityRatio; 
      }
      readCity (cityFile, &city);
    }

    printf ("The city with the lowest per capita number of radio and tv ");
    printf ("stations is %s\n", lowestCityName); 
    printf (" with a ratio of %lf stations per capita\n", lowestCityRatio);
  }

  fclose (cityFile);
}
