 Hello and welcome back. In this lecture, we are going to try to put together all that we have studied about structures in the last few lectures by actually solving a programming problem that uses structures. Here is a quick recap of some of the relevant topics that we have already studied. We have studied about structures as collections of variables, arrays and other structures. We have studied about pointers to structures. We have seen how members of structures can be accessed. We have studied about linked structures and also how to dynamically allocate and deallocate structures in the heap. In this lecture, we are going to look at an example C++ program that makes heavy use of structures. Particularly, it is going to make use of linked structures in which we are going to access members through both the dot operator and the arrow operator and we are also going to encounter dynamic allocation and deallocation of structures. Some examples in this lecture are from the book An Introduction to Programming through C++ by Abhiram Giranade published by Michael Hill Education in 2014. All such examples will be indicated in the slides with the citation AGR book. So, here is a simple problem. It is about a taxi queuing system and it is inspired by a discussion in AGR book. So, let us suppose that we have a train station and at this train station, taxis arrive and depart at different times and we want to maintain a queue of taxis at the train station. We require this queue to implement a first and first out policy for taxis, which means that the taxi that came to the station the earliest among all the waiting taxis should be at the front of the queue and this should be the taxi that should be the next one to be dispatched when a passenger comes calling for a taxi. The latest taxi to arrive at the station must join the queue at its end and no taxi is allowed to leave the queue once it joins the queue at its end until it reaches the front of the queue and is dispatched. So, in trying to program this in C++ let us try to understand what kind of structures would be useful for us. How do we want to organize the information? What are the different entities or objects that are going to be interacting? So, it is clear that in this case we have taxis and in particular we want to have link taxis in which I can go from the information for one taxi to the information from the next taxi to the information for the taxi after that because we actually want to implement a queue of taxis and of course each link taxi should also have information about driver. So, we are going to have three kinds of objects or entities driver link taxi and of course the overall queue. Now, we have seen the structure definition in an earlier lecture. So, this structure driver has two members name and ID. Name is going to be of string data type, ID is of integer data type. A link taxi is a structure which has three members. It has the ID of the taxi which is of integer type. It has a member DRV which stores a pointer to an object of type driver which basically stores the details of the driver for the taxi and we also have a member next which points to the next link taxi in the queue. So, the type of next is really a pointer to the same structure link taxi and of course overall queue will have a front and end both of which are pointers to the link taxi structure and it is also going to have a member num taxis which is of integer type and this is going to contain account of the total number of taxis currently in the queue. Note that all these structure definitions have been done before and outside the definitions of functions that are going to use them. Note also that while in earlier lectures when we talked about the structure driver, we had used a character array for name. We have suddenly switched over to the string data type instead of character array for the same member named name and we have done this because it really helps simplify reading of strings with spaces using CN. The name of a driver may have spaces in it and in order to simplify the reading of strings with spaces using CN, we have used the string data type here. That is the only reason why we have changed the data type from a character array to a string. Well, after we have defined the structures here is what the main function might look like. We have a variable queue of type structure queue and both the front and end members of queue are initialized to null and the number of taxes in the queue is initialized to zero. After that, we have an infinite while loop or so it appears because this is while true. So, it might appear to be an infinite while loop, but really we will see that there is a way to get out of this while loop. So, within this while loop, we basically ask for a command from the user. This command could be one of three characters J, D or X. J stands for joining the queue, D for dispatching a taxi from the queue and X to exit the program and then we read in the command and store it in a character variable called command and then we use a switch case statement to take the appropriate action based on whatever command is. So, if the command is J, then we execute the code to add a newly arrived taxi at the end of the queue and then break. If the command is D, we execute the code to dispatch a taxi from the front of the queue and then break and of course, if the command is X, we say thank you and here is where we actually return from the main function with the exit code zero. So, note that this is as an expected or a normal return from the main function and therefore, we return the exit code zero so that whoever called the main function which is the operating system would know that the main function terminated as expected and of course, if the command is none of J, D or X, we say invalid command and then we go back and ask for the command all over again. Now, how would the code for adding a taxi at the end of the queue look like? So, remember a taxi will have information about the driver of the taxi as well. So, we are first going to allocate a new object of type driver in the heap using new driver. This will return a pointer to that newly allocated object of type driver which we will then store in this variable new DRV whose type is a pointer to the structured driver. Now, if this new succeeded then it is not going to return a null pointer otherwise it is going to return a null pointer. So, we are going to check if new indeed returned a null pointer if so we will say memory allocation failure and we will return with minus one. So, this is an abnormal return from the main function and so we are returning minus one to tell the operating system that the main function has returned but it returned in an abnormal way in an unexpected way. Otherwise, if this new succeeded then we have a freshly allocated object of type structured driver in the heap and we are going to populate various members of that object now. So, we are going to ask for the name of the driver and read in the name of the driver in the member named name of that newly allocated object. We are going to ask for the ID of the driver and read in the ID of the driver and store it in the member named ID of that newly allocated object. Once we have stored the information about the driver we are now going to create a new object of structure type link taxi in the heap. We are going to use this new link taxi to do that and whatever pointer it returns is now going to be stored in this variable new taxi whose type is a pointer to the structure type link taxi. Once again if this new fails then it is going to return a null pointer and we are going to check that and in that case we are going to say memory allocation failure and again return from the main function with the exit code minus 1. Otherwise, if this new succeeded then we will have a newly allocated object of type link taxi in the heap to which this variable new taxi is pointing and we are going to update the member DRV of that newly allocated object of type link taxi with the pointer to the object of type driver that we had already allocated and in whose members we had already stored the details of the driver. Recall that new DRV was pointing to that object of type driver and so we just copy new DRV to the member named DRV of the object pointed to by new taxi and we are going to set the member next of the object of type link taxi pointed to by new taxi to null. After that we are going to ask for the ID of the taxi and we are going to store that in the member named ID of that newly allocated object of type link taxi. So, here is where we have now got all the information about the taxi, we have got its ID, we have got the information about its driver and everything is set up. Now, we are going to check if q dot end is null which means that the taxi q is really empty then this must be the first taxi that is going into the queue. So, we are going to update both q dot front and q dot end to new taxi, we are going to update the number of taxes in the queue to one and that would complete adding the taxi at the end of the queue. Otherwise if q dot end is not null then really there are already some taxes in the queue like this. So, this is the front of the queue, this is the end of the queue. The next member of the front of the queue is pointing to the next taxi in the queue and the next member of the taxi at the end of the queue is pointing to null and here is new taxi whose next member is already pointing to null that is what we did here. And now in this case what should we do in order to add this new taxi at the end of the queue, we should simply make this next pointer of whatever was originally at q dot end to point to this new taxi and we should make q dot end also point to this new taxi. So, that is exactly what we are going to do, we are going to update whatever q dot end was pointing to its next member to point to new taxi that is what we did here. Then we are going to update q dot end itself to point to new taxi and we are going to increment the number of taxes in the queue. So, that completes adding a taxi at the end of the queue. How do we dispatch a taxi from the front of the queue? Well if there are no taxes in the queue then q dot front will be null and in this case we will just say sorry no taxes in the queue at present and we will go back to accept the next command. Otherwise if there is a taxi at the front of the queue, we figure out what is this which taxi is this. So, basically q dot front is a pointer to the taxi at the front of the queue, we copy that pointer in this variable dispatch taxi whose type is also a pointer to link taxi. And if this dispatch taxi was the last taxi in the queue, if it was the only one taxi in the queue then after we have dispatched it then queue would become empty. So, how do we check whether this was the only one taxi in the queue? We basically check if q dot front is equal to q dot end and if so after this taxi has been dispatched the queue becomes empty. So, both q dot front and q dot end become null and the number of taxis in the queue becomes zero. Otherwise if dispatch taxi is not the only taxi in the queue then we have a situation like this. So, the queue is like this, this is the front of the queue, this is the end of the queue and dispatch taxi is pointing to the taxi at the front of the queue. Now, what should happen when I dispatch this taxi from the front of the queue, q dot front should point here. So, that is what we have done, we have updated q dot front to the next member of whatever q dot front was already pointing to and we have decremented the number of taxis by one. And now we have got to dispatch this taxi. So, we have really got to get rid of this dispatch of this object pointed to by dispatch taxi. So, here is where we are going to call the delete function to deallocate memory. But recall that before we call delete function we must always check whether the pointer on which we are calling delete is null or not. So, that is what we do here, we check if dispatch taxi is not equal to null then really we have a taxi to dispatch and we say that dispatching taxi with id and whatever the id of that taxi at the front of the queue was. And before we deallocate this object of type link taxi please note that one of the members of this object was a pointer to an object of type driver and that object was also dynamically allocated. So, if we are going to deallocate this object we better deallocate that object as well otherwise that object allocated in the heap would just be hanging around and nobody would be pointing to it. So, that is what we do here we check if dispatch taxi arrow DRV is not equal to null then we delete dispatch taxi arrow DRV this would free up the object of type driver allocated on the heap to store information about the driver of this dispatch taxi. And finally, after we have done that we are going to delete the object of type link taxi from the heap itself by calling delete dispatch taxi. So, that is what is going to happen dispatch taxi would be freed from the heap memory. So, in summary in this lecture we saw how to implement a taxi dispatch system which works in a first in first out order using linked structures we made use of dynamic allocation deallocation of structures. And we also saw that members could be accessed through both the dot and the arrow operators note that in this example the size of the queue was not predetermined every time a new taxi came to join the queue we allocated space for it in the heap dynamically and every time a taxi was dispatched we freed up that space. So, really the size of the queue is not predetermined in fact it is the amount of memory in the system that dictates how many taxes you can have in the queue. Thank you.