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 -