tommywang0tw
>queue.h
and queue.c
to fully implement the following functions:
linux> make
linux> ./qtest
linux> make test
In order to efficiently implement q_size
and q_insert_tail
, we add a pointer called tail to point the end of the queue and a integer called size to record the size of this queue.
q_new
We allocate space for this queue structure and make the head pointer point to NULL. If the malloc fails, the pointer q would be assigned NULL. We use this attribute to detect malloc failure.
q_free
In this code, we use two pointer(temp, prev) to go through this queue. Prev points to the element temp just went through. Everytime when temp goes through a element, we free the string that element points to. After that, prev will go through this element and free it.
q_insert_head
First, we handle the special conditions like: queue doesn't exist(q == NULL), malloc failure when allocating space for string or element. Note that, at line 29, we need to free the space we just allocated or it would be memory leak.
Then we need to do the right move corresponding two situations: queue is empty or not. If it is, we need to point both the head and tail pointer to this new element. Also, the new element should point to NULL. If it's not, we make the new element point to the old head element, then point the head point to the new element. (after line 35)
q_insert_tail
q_insert_tail
is highly similar to q_insert_head
, the functionality is the same and also the special conditions and situations need to be handled. In order to keep this note short, I won't elaborate this function here because the content would be almost the same.
Note: we are required to implement this function in O(1). The key point to do so is in the queue structure declaration. We declared the tail pointer in this structure so that we can easily use the same method as q_insert_head
and implement this function in constant time.
q_remove_head
First, we use a simple if statement to handle the situations that q is empty or doesn't even exist(q==NULL or q->head==NULL
). Then we check if sp is non-NULL. If it is, we need to copy the string we are about to remove to sp.
(Note: we need to put the terminator at the end of string in sp manually because if the size of the removed string is equal or larger than bufsize-1, strncpy
won't copy the terminator to sp.)
Then, we can free the space and adjust the pointers to make the linked list still works properly.
q_size
Instead of calculating the size in this function, we record the size of the queue everytime we insert or remove an element. To do so, we need to declare an integer called size in the queue structure.
You can go and check the code above, there is a line q->size--;
or q->size++;
everytime we remove or insert an element.
In this case, the code is so simple as below:
q_reverse
First, we handle the special cases, empty queue and non-existing queue. In this two cases, we don't need to do anything.
Then, we use three pointers here, which are prev
, temp
, and next
. prev
holds the element previous to temp
, and next
holds the one next to temp
. We go through the whole list from the head and make the element holded by temp
point to previous one, then move to the next element by using next
. This move will keep being implemented until temp
reaches NULL.
I'm new to linux, so all these stuff are totally unfailliar for me. I'm not sure I can really well elaborate how this system work, but I'll write down what I learned and try my best to explain it.
We use the command make
to compile and genenrate the executable code. This command is a utility for building and maintaining groups of programs from source code. The make program uses the makefile data base and the last-modification times of the files to decide which of the files need to be updated. For those files, it issues the commands recorded in the database. make executes commands in the makefile, if no -f is present, make will look for the makefiles GNUmakefile, makefile, Makefile, in that order.
Note: The Makefile is recommended becasue it appears prominently near the beginning of a directory listing, right near other improtant files such as README.
When we do make
without any arguments like this in terminal:
make builds the first target that appears in its makefile, which is traditionally a target named all. In the Makefile of the homework, it is:
From this target, make will compile the source code and build the executable file qtest by running the command from this line in the Makefile:
We can know it will also generate the Git Hooks if we expand the macro (GIT_HOOKS) and look at the rule:
According from the pdf file of the homework requirement, the driver program driver.py
runs the qtest and computes the score. When we do make with argument test following like this:
make build this target in the Makefile:
That is how make invoke the driver.