Annotated code for Schelling's segregation model in C: Version schelling3.c

This is a web page with annotations for the code in the file schelling3.c, which is a C program implementing Thomas Schelling's model of segregation from Micromotives and Macrobehavior, according to a Pascal version of that model written by Robert Axelrod. This version of the program is based on the program in schelling.c and please read that page if you haven't already. This annotation only mentions the differences between the two files To download the code for schelling3.c without these remarks please follow this link:

There are three versions of this program, annotations for the other two are the files:


Global declarations

The main difference between this file and schelling2.c (click link for annotations) is that here we add the capacity to save the output to an outfile. In order to do this we have to open an outfile and redirect the printed output to the file. Note the FILE pointer declared as a global variable:

/* Global vars */
int number_of_reports=8;
int events_per_report=100;
int num_white=25;
int num_agents=50;
FILE * outfile;

We also have to be able to pass the name of the outfile to the program. This can be done through the arguments to main, which are the command line arguments when the program is invoked. Note that the first argument is always the name of the program. The variable argc gives the number of arguments, and if it is larger than one we know that a file name was given. In opening the file we also check for errors, such as whether the file was allocated, and if the name is valid. On an error we crash the program, with exit code 1 - which indicates that something went wrong. If no argument is given to the program, we assume that output should go to stdout (the console). Since stdout is a file pointer we can simply set outfile to stdout an everything will work correctly.

void main(int argc,char * argv[]) {
  int i;
  int report;
  int events_in_report;
  int event=0;
  int moves_this_period=0;
  
  /* Open output file if asked for */
  if(argc>1) {
    printf("Output will go to file %s\n",argv[1]);
    if((outfile=fopen(argv[1],"w"))==NULL) {
      printf("Aborting. Unable to open outfile %s\n",argv[1]);
      exit(1);
    }
  } else {
    outfile=stdout;
  }
  
  /* Get parameters */
  get_parameters();
  
  /* Allocate memory for agent lists */
  initialize_arrays();
  
  /* Initialize lattice and neighborhood list */
  initial_output();
  initialize_agent_color();
  initialize_agent_location();
  initialize_neighbor_list();
  periodic_output(0,0);

  /* Count timesteps or events */
  event = 0;
  i = 0;

  /* Outer event loop */
  for (report=0;report<number_of_reports;report++) {
    /* Count of actual moves */
    moves_this_period = 0;

    /* Inner event loop */
    for (events_in_report = 0;events_in_report < events_per_report;events_in_report++) {
      event++;
      /* Work our way through the agent list */
      if (i >= num_agents)
	i = 0;
      if (!content(i)) {
	/* If agent is not content then move it*/
	moves_this_period++;
	random_move(i);
      }
      i++;
    }
    /* Print out report */
    periodic_output(event,moves_this_period);   
  } 

  exit(0);
}

Output functions

We have also made changes to the output functions, basically using the function fprintf() from the stdio library, which is equivalent to printf except that it prints to a file. Hence fprintf takes an additional argument, namely the file pointer. In other respects the functions are the same as before:

void initial_output() {
  /* Prints some information at beginning of run */

  fprintf(outfile,"Parameters:\n");
  fprintf(outfile,"   Number of agents=%3d\n",num_agents);
  fprintf(outfile,"   Number of agents with color 0=%3d\n",num_white);

}

void periodic_output(int event,int moves) {
  /* Prints out periodic state of map */
  int line;
  int address;
  int column;
  char str[3]={'.','@','#'};
    
  if(event==0) 
    fprintf(outfile,"Initial state of map\n");
  else
    fprintf(outfile,"Event %3d. Moves this period %3d\n",event,moves);  
  
  address=0;
  for(line=0;line<8;line++) {
    for(column=0;column<8;column++) {
      /* Output agent map */
      if(occupant[address]==-1) 
	fprintf(outfile," . ");
      else 
	fprintf(outfile,"%3d",occupant[address]);
      address++;
    }
    /* Rewind and put space between */
    address-=8;
    fprintf(outfile,"     ");
    for(column=0;column<8;column++) {
      /* Output color map */
      if(occupant[address]==-1)
	fprintf(outfile," %c ",str[0]);
      else 
	fprintf(outfile," %c ",str[color[occupant[address]]+1]);
      address++;
    }
    fprintf(outfile,"\n");
  }
  fprintf(outfile,"\n");

}

Written by Benedikt Stefansson: benedikt@ucla.edu
Last modified: Mon Feb 2 17:45:36 PST 1998