www.delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp/1999/05/22/05:25:44

From: jack DOT stinchcombe AT usa DOT net
Newsgroups: comp.os.msdos.djgpp
Subject: problem with referenced structure
Date: Sat, 22 May 1999 00:48:27 GMT
Organization: Deja.com - Share what you know. Learn what you don't.
Lines: 467
Message-ID: <7i4usr$mg7$1@nnrp1.deja.com>
NNTP-Posting-Host: 206.17.119.174
X-Article-Creation-Date: Sat May 22 00:48:27 1999 GMT
X-Http-User-Agent: Mozilla/4.08 [en] (Win95; I ;Nav)
X-Http-Proxy: 1.0 x43.deja.com:80 (Squid/1.1.22) for client 206.17.119.174
To: djgpp AT delorie DOT com
DJ-Gateway: from newsgroup comp.os.msdos.djgpp
Reply-To: djgpp AT delorie DOT com

I am using a structure to store most of the data the program needs.
main then passes the structure on as a reference varible to the
functions
it calls. Im using a structure like this to avoid having functions with
lots of paramaters.

My problem is that in some cases when I assign a structure member in
these functions, it assigns the value to a different member than the
one specified in the code.

First I found that although the clerk_events[] member of the QueueData
was dimensioned correctly, with the code

int clerk_events[NUMBER_OF_CLERKS];

but when the program assigned the subscript NUMBER_OF_CLERKS for
this array, the value for the structure member customer_count was
changed instead . I worked around this problem by increasing the
dimension of the array, as you can see at line 36:

int clerk_events[NUMBER_OF_CLERKS+1];


However I have now come across a problem I cant seem to work around.
On line 295, which reads

data.prev_customer_count=data.customer_count;
I find that the value for data.clock_time is changed!

I can't figure how this kind of thing could logically happen.

So what I need to know is: how could this happen, and what I
can do about it? The only thing I can think of is re-organising
the program so  it doesnt store and access its data in this way,
but if you've an easier solution, i'd really appreciate it.

I have got version 2.8.1 of DJGPP and Windows 95.
I compile the program using gxx, and the program needs to be compiled
with the -fguiding-decls flag because Dqueue.h needs it, and of course
with the -g flag for the debugger.

I have pasted the code for my program below.  Basically what the
program is trying to do is simlulate a queue in a shop, and report
back on various things.

I know I have used some non-c++ code (e.g pointers and 'printf'),
but thats just because im more familiar with them than the c++
equivalents.

I cant post Dqueue.h here because it is copyright. Dqueue.h is an
implementation of a queue ADT. (Line 1 of the program is the first
commented line of asterisks. )

//****************************************************************
//**                                                            **
//**   IMPORTANT: GNU C++, compile with -fguiding-decls flag.   **
//**                                                            **
//****************************************************************

#include <assert.h>
#include <stdlib.h>
#include <iostream.h>
#include <fstream.h>
#include "Dqueue.h"

#include <stdio.h>

#define SIMULATION_LENGTH 1
#define MAX_CUSTOMER_ARRIVAL_INTERVAL 60
#define CUSTOMER_SERVICE_TIME_MIN 10
#define CUSTOMER_SERVICE_TIME_MAX 180
#define SERVICE_RECORD_UPDATE_INTERVAL 10
#define ASSUMED_MAX_CUSTOMERS 200
#define NUMBER_OF_QUEUES 1
#define NUMBER_OF_CLERKS 2

#define CUSTOMER_EVT 1
#define CLERK_EVT 2
#define RECORD_EVT 3
#define true 1
#define false 0

struct QueueData{
	Queue<int> Q[NUMBER_OF_QUEUES];
	int clerk_idletime[NUMBER_OF_CLERKS];//the total amount of time
each clerk has been idle
	int customer_record[ASSUMED_MAX_CUSTOMERS];//the total amount of
time each customer was in the shop
						   //this is needed to
calculate the average amount of time
						   //each customer was
in the shop
	int clerk_events[NUMBER_OF_CLERKS+1];//the time at which each
clerk will become free
					     //its a mystery why the
array subscript needs to be
					     //NUMBER_OF_CLERKS +1, but
if it isnt, customer_count
					     //gets corrupted.
	int customer_count;//the total number of customers during the
simulation
	int customer_event;// time that the next customer will arrive in
the shop
	int clock_time;//the current simluation time
	int clerk_index;//index of the  clerk in a CLERK_EVT
	int event_time;//the time of the next event
	int prev_customer_count;
	int
service_record[10*SIMULATION_LENGTH*3600/SERVICE_RECORD_UPDATE_INTERVAL,
1];
	int update_event;//the ime of the next record update event
	};

int clerk_event (QueueData &data);
int customer_event (QueueData &data);
int customerservicetime (void);
int find_next_event (QueueData &data);
char *formathms (int seconds, char *charbuf);
char *formatms (int seconds, char *charbuf);
int getRand (int a, int b);
int initialise (QueueData &data);
int is_simulation_running (QueueData &postshop);
void output_results (QueueData &data);
int queues_empty(Queue<int> *q);
int record_event (QueueData &data);
int which_queue (Queue<int> *q);

int main (void){

	assert(SIMULATION_LENGTH>0);

assert((NUMBER_OF_QUEUES==NUMBER_OF_CLERKS)||(NUMBER_OF_QUEUES==1));

	QueueData postshop;
	initialise(postshop);
	//
	//loop the simluation until all queues are empty and the
simulation
	//duration has passed
	while (is_simulation_running(postshop)) {
	//
		switch (find_next_event(postshop)) {

			case CLERK_EVT:
			clerk_event (postshop);
			break;

			case CUSTOMER_EVT:
			customer_event (postshop);
			break;

			case RECORD_EVT:
			record_event (postshop);
			break;
		}

	}//end of while loop


	output_results(postshop);
	getc(stdin);
	return 0;
}

int queues_empty(Queue<int> *q) {
	int q_empty=0;
	//determine if all the queues are empty
	for (int
queue_index=0;queue_index<NUMBER_OF_QUEUES;queue_index++){
		//increments q_empty for every empty queue
		q_empty+=((q+queue_index)->empty());
		}

	return (q_empty==NUMBER_OF_QUEUES);
}

int which_queue (Queue<int> *q) {

	//find shortest queue if any
	//shortest_q_index the index of the shortest queue
	//shortest_q_length is the length of the shortest queue
	int shortest_q_index=-1;
	int shortest_q_length;

	//start by assuming the 1st queue is the shortest
	shortest_q_length=(q+0)->length();


	//use a loop to find the shortest queue.
	for (int
queue_index=0;queue_index<NUMBER_OF_QUEUES;queue_index++){
		if (shortest_q_length>(q+queue_index)->length()) {
			shortest_q_length=(q+queue_index)->length();
			shortest_q_index=queue_index;
		}
	}
	//return index of the shortest queue or index of random queue
	//if queue lengths are equal or return 1 if theres only one
queue
	if (NUMBER_OF_QUEUES==1) return 0;
	return
(shortest_q_index==-1)?getRand(0,NUMBER_OF_QUEUES-1):shortest_q_index;
}


int customerservicetime (void) {
	return getRand (CUSTOMER_SERVICE_TIME_MIN,
CUSTOMER_SERVICE_TIME_MAX);
}

int getRand (int a, int b) {
	assert (a<b);
	int r=rand();
	return a+r%(b-a+1);
}

int find_next_event (QueueData &data){
	//printf ("fne: clock_time %d\n",data.clock_time);
	//printf ("fne: customer_count1 %d\n",data.customer_count);
	data.event_time=
CUSTOMER_SERVICE_TIME_MAX+(SIMULATION_LENGTH*3600)+(data.customer_event)
;

	int record_update=0;

	if (data.customer_event<data.event_time) {
		data.event_time=data.customer_event;
		data.clerk_index=0;
		}

	for (int loop_index=1;loop_index<=NUMBER_OF_CLERKS;loop_index++)
{

		if (data.clerk_events[loop_index]<data.event_time)
			{data.event_time=data.clerk_events[loop_index];
			 data.clerk_index=loop_index;
			}
		}

	//printf ("fne: customer_count2 %d\n\n",data.customer_count);
	//check to see if a record updae event comes next
	if (data.update_event<data.event_time) {
		data.event_time=data.update_event;
		record_update=true;
		}
	if (record_update) return RECORD_EVT;
	if (data.clerk_index==0) return CUSTOMER_EVT;

	return CLERK_EVT;
}


int initialise (QueueData &data) {
	int loop_index=1;

	//set the time for the 1st record update update event
	data.update_event=SERVICE_RECORD_UPDATE_INTERVAL-1;

	//fix the random seed at zero
	srand (0);

	data.clock_time=0;

	// set the time the 1st customer arrives
	data.customer_event=getRand(0,
MAX_CUSTOMER_ARRIVAL_INTERVAL)+data.clock_time;
	data.customer_count=0;

	do {
		data.clerk_events[loop_index]=1;
		data.clerk_idletime[loop_index]=0;
		loop_index++;}
	while (loop_index<=NUMBER_OF_CLERKS);

	return 1;
}

int clerk_event (QueueData &data) {
	//update the clock
	data.clock_time=data.clerk_events[data.clerk_index];


	if (!queues_empty(data.Q)) {
		//remove customer from queue and calulate how
		//long he spent in the queue
		int misc=0;

misc=data.Q[(NUMBER_OF_QUEUES>1)?data.clerk_index-1:0].deQueue();

		data.customer_record[misc]=
data.clock_time-data.customer_record[misc,0];

		//update when the clerk will be free next

data.clerk_events[data.clerk_index]=customerservicetime()+data.clock_tim
e;

		}
	else //if there's no-one in any of the queues then ...
		{

		//the clerk is going to be idle untill a customer
arrives,
		//so the record of how much idle time that clerk has had
		//must increase
		data.clerk_idletime[data.clerk_index]+=
data.customer_event-data.clock_time;

		//re-schedule the event to occur when a customer arrives
		//trouble line
		data.clerk_events[data.clerk_index]=data.customer_event;
		data.clerk_index=0;
		}

	return 0;
}

int is_simulation_running (QueueData &data) {
		return (data.clock_time<=(SIMULATION_LENGTH*3600)
		|| !queues_empty(&data.Q[0]));}

int customer_event (QueueData &data) {
	//a customer arrives in the shop and is added to one of the
queues

	//the trick is here to not add a customer if he's
	//going to arrive beyond end of the simllation. However
	//the clock still needa to be updated, and a time for
	//another to arrive chosen, so that the program doesnt
	//get stuck on the same event

	data.clock_time=data.customer_event;

	if (data.clock_time<=(SIMULATION_LENGTH*3600)) {

		data.customer_count++;

		int wq=which_queue(&data.Q[0]);

		data.Q[wq].enQueue(data.customer_count);

		//make a record of when the customer arrived

data.customer_record[data.customer_count]=data.clock_time;

		}
	//Get the arrival time for the next customer
	//This needs to be done even if its beyond the simulation time
because
	//else the program will think that the customer_event is still
the next
	//event and will get stuck on the same event
	data.customer_event=getRand(0,
MAX_CUSTOMER_ARRIVAL_INTERVAL)+data.clock_time;

	return 0;
}

int record_event (QueueData &data) {
	data.clock_time=data.update_event;

	//make a record of how many customers were deal with
	data.service_record
[(data.update_event/SERVICE_RECORD_UPDATE_INTERVAL)-1,0]=
		data.customer_count-data.prev_customer_count;

	//set time time for the next reord update event
	data.update_event+=SERVICE_RECORD_UPDATE_INTERVAL;

	//calculate the average time each customer spent in the office
	int average_time=0;
	for (int
loop_index=data.prev_customer_count;loop_index<=data.customer_count;
		loop_index++)
average_time+=data.customer_record[loop_index];


	if (data.customer_count-data.prev_customer_count>0)

{average_time=(int)(average_time/(data.customer_count-data.prev_customer
_count));}
	else
		{average_time=-1;}
	data.service_record
[(data.update_event/SERVICE_RECORD_UPDATE_INTERVAL)-1,1]  =average_time;

	//update prev_customer_count
	data.prev_customer_count=data.customer_count;
	return 0;
}

char *formatms (int seconds, char *charbuf) {
	//formats seconds into mintues:seconds format
	//Returns the same pointer to charbuf as in the second
	//paramater

	int minutes=(int)(seconds/60);
	sprintf(charbuf,"%2d:%02d", minutes, seconds-(minutes*60));

	return charbuf;
}


char *formathms (int seconds, char *charbuf) {
	//formats seconds into hours:mintues:seconds format
	//Returns the same pointer to charbuf as in the second
	//paramater

	int minutes=(int)(seconds/60);
	seconds-=minutes*60;
	int hours=(int)(minutes/60);
	minutes-=hours*60;
	sprintf(charbuf,"%d hours, %d minutes, %d seconds.", hours,
minutes, seconds);

	return charbuf;
}

void output_results (QueueData &data) {

	FILE *output;

	//output=fopen ("A21B.out","w");
	output=stdout;

	//output general info
	char timebuffer[40];
	printf ("Length of Simulation: %s\n", formathms
(data.clock_time, timebuffer));
	printf ("Number of Customers:  %d\n", data.customer_count);
	printf ("Number of Queues:     %d\n", NUMBER_OF_QUEUES);
	printf ("Number of Clerks:     %d\n\n", NUMBER_OF_CLERKS);

	//output service record
	fprintf (output,"Service Time  Customers    Average Time in
Office\n");

	int loop_index;
	int start_srvc_time=0;
	for (loop_index=0;

loop_index<(int)(data.clock_time/SERVICE_RECORD_UPDATE_INTERVAL);
		loop_index++) {
		fprintf (output,"%3d - %3d          %2d           %s",
			start_srvc_time,
start_srvc_time+SERVICE_RECORD_UPDATE_INTERVAL-1,
			data.service_record[loop_index, 0], formatms
(data.service_record[loop_index, 1], timebuffer));

		start_srvc_time+=SERVICE_RECORD_UPDATE_INTERVAL;
		}

	//output the clerks idle times.
	fprintf (output, "Clerk           Idle Time\n");
	for (loop_index=1;loop_index<=NUMBER_OF_CLERKS;loop_index++){
		fprintf (output, "  %d             %s\n",
			loop_index, formatms
(data.clerk_idletime[loop_index], timebuffer));
		}

	return;
}



--== Sent via Deja.com http://www.deja.com/ ==--
---Share what you know. Learn what you don't.---

- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019