CS:APP3e 深入理解计算机系统_3e C Programming Lab实验


queue.h:

/* 
 * Code for basic C skills diagnostic.
 * Developed for courses 15-213/18-213/15-513 by R. E. Bryant, 2017
 */

/*
 * This program implements a queue supporting both FIFO and LIFO
 * operations.
 *
 * It uses a singly-linked list to represent the set of queue elements
 */

#include <stdbool.h>

/************** Data structure declarations ****************/

/* Linked list element (You shouldn't need to change this) */
typedef struct ELE {
    int value;
    struct ELE *next;
} list_ele_t;

/* Queue structure */
typedef struct {
    list_ele_t *head;  /* Linked list of elements */
    list_ele_t *tail;
    unsigned size;
} queue_t;

/************** Operations on queue ************************/

/*
  Create empty queue.
  Return NULL if could not allocate space.
*/
queue_t *q_new();

/*
  Free all storage used by queue.
  No effect if q is NULL
*/
void q_free(queue_t *q);

/*
  Attempt to insert element at head of queue.
  Return true if successful.
  Return false if q is NULL or could not allocate space.
 */
bool q_insert_head(queue_t *q, int v);

/*
  Attempt to insert element at tail of queue.
  Return true if successful.
  Return false if q is NULL or could not allocate space.
 */
bool q_insert_tail(queue_t *q, int v);

/*
  Attempt to remove element from head of queue.
  Return true if successful.
  Return false if queue is NULL or empty.
  If vp non-NULL and element removed, store removed value at *vp.
  Any unused storage should be freed
*/
bool q_remove_head(queue_t *q, int *vp);

/*
  Return number of elements in queue.
  Return 0 if q is NULL or empty
 */
int q_size(queue_t *q);

/*
  Reverse elements in queue
  No effect if q is NULL or empty
 */
void q_reverse(queue_t *q);

queue.c:

/* 
 * Code for basic C skills diagnostic.
 * Developed for courses 15-213/18-213/15-513 by R. E. Bryant, 2017
 */

/*
 * This program implements a queue supporting both FIFO and LIFO
 * operations.
 *
 * It uses a singly-linked list to represent the set of queue elements
 */

#include <stdlib.h>
#include <stdio.h>

#include "harness.h"
#include "queue.h"

/*
  Create empty queue.
  Return NULL if could not allocate space.
*/
queue_t *q_new()
{
    queue_t *q = NULL;
    if((q = malloc(sizeof(queue_t))))
    {
      q->head = NULL;
      q->tail = NULL;
      q->size = 0;
      return q;
    }
    else
    {
      return NULL;
    }
}

/* Free all storage used by queue */
void q_free(queue_t *q)
{
    /* How about freeing the list elements? */
    /* Free queue structure */
    if (q)
    {
      list_ele_t *i = q->head;
      while(i)
      {
        list_ele_t *tmp = i;
        i = i->next;
        free(tmp);
      }
      free(q);
    }
}

/*
  Attempt to insert element at head of queue.
  Return true if successful.
  Return false if q is NULL or could not allocate space.
 */
bool q_insert_head(queue_t *q, int v)
{
    list_ele_t *newh;
    /* What should you do if the q is NULL? */
    if (q)
    {
      if ((newh = malloc(sizeof(list_ele_t))))
      {
        newh->value = v;
        newh->next = q->head;
        q->head = newh;
        if (!q->size)
        {
          q->tail = newh;
        }
        ++q->size;
        return true;
      }
      else
      {
        return false;
      }
    }
    else
    {
      return false;
    }
}


/*
  Attempt to insert element at tail of queue.
  Return true if successful.
  Return false if q is NULL or could not allocate space.
 */
bool q_insert_tail(queue_t *q, int v)
{
    /* You need to write the complete code for this function */
    /* Remember: It should operate in O(1) time */
    list_ele_t *newh;
    if (q)
    {
      if ((newh = malloc(sizeof(list_ele_t))))
      {
        newh->value = v;
        newh->next = NULL;
        if (q->tail)
        {
          q->tail->next = newh;
          q->tail = newh;
          ++q->size;
        }
        else
        {
          q->head = q->tail = newh;
          ++q->size;
        }
        return true;
      }
      else
      {
        return false;
      }
    }
    else
    {
      return false;
    }
}

/*
  Attempt to remove element from head of queue.
  Return true if successful.
  Return false if queue is NULL or empty.
  If vp non-NULL and element removed, store removed value at *vp.
  Any unused storage should be freed
*/
bool q_remove_head(queue_t *q, int *vp)
{
    /* You need to fix up this code. */
    if (!q || !q->size)
    {
      return false;
    }
    else
    {
      if (vp)
      {
        *vp = q->head->value;
      }
      list_ele_t *tmp = q->head;
      q->head = q->head->next;
      free(tmp);
      --q->size;
      return true;
    }
}

int q_size(queue_t *q)
{
    /* You need to write the code for this function */
    /* Remember: It should operate in O(1) time */
    if (!q || !q->size)
    {
      return 0;
    }
    else
    {
      return q->size;
    }
}

/*
  Reverse elements in queue
 */
void q_reverse(queue_t *q)
{
    if (q && q->size)
    {
      int cache[q->size];
      list_ele_t *tmp = q->head;
      for (int i = q->size - 1; (i >= 0) && (tmp != NULL); --i)
      {
        cache[i] = tmp -> value;
        tmp = tmp->next;
      }
      tmp = q->head;
      for (int i = 0; (i < q->size) && (tmp != NULL); ++i)
      {
        tmp->value = cache[i];
        tmp = tmp->next;
      }
    }
}

测试:

frank@under:~/Desktop/cs:app/lab/cprogramminglab/cprogramminglab-handout$ ./qtest 
cmd>help
cmd>help
Commands:
    #    ...            | Display comment
    free                    | Delete queue
    help                    | Show documentation
    ih   v [n]          | Insert v at head of queue n times (default: n == 1)
    it   v [n]          | Insert v at tail of queue n times (default: n == 1)
    log  file           | Copy output to file
    new                 | Create new queue
    option   [name val]     | Display or set options
    quit                    | Exit program
    reverse                 | Reverse queue
    rh   [v]            | Remove from head of queue.  Optionally compare to expected value v
    rhq  [v]            | Remove from head of queue without reporting value
    show                    | Show queue contents
    size     [n]            | Compute queue size n times (default: n == 1)
    source   file           | Read commands from source file
    time     cmd arg ...    | Time command execution
Options:
    echo    1   Do/don't echo commands
    error   5   Number of errors until exit
    fail    30  Number of times allow queue operations to return false
    malloc  0   Malloc failure probability percent
    verbose 4   Verbosity level
cmd>new
cmd>new
q = []
cmd>show
cmd>show
q = []
cmd>ih 1
cmd>ih 1
q = [1]
cmd>ih 2
cmd>ih 2
q = [2 1]
cmd>ih 3
cmd>ih 3
q = [3 2 1]
cmd>size
cmd>size
Queue size = 3
q = [3 2 1]
cmd>it 0
cmd>it 0
q = [3 2 1 0]
cmd>it -1
cmd>it -1
q = [3 2 1 0 -1]
cmd>size
cmd>size
Queue size = 5
q = [3 2 1 0 -1]
cmd>reverse
cmd>reverse
q = [-1 0 1 2 3]
cmd>size 
cmd>size
Queue size = 5
q = [-1 0 1 2 3]
cmd>rh -1
cmd>rh -1
Removed -1 from queue
q = [0 1 2 3]
cmd>size

评分:

frank@under:~/Desktop/cs:app/lab/cprogramminglab/cprogramminglab-handout$ ./driver.py 
--- Trace       Points
+++ TESTING trace trace-01-ops:
# Test of insert_head and remove_head
--- trace-01-ops    7/7
+++ TESTING trace trace-02-ops:
# Test of insert_head, insert_tail, and remove_head
--- trace-02-ops    7/7
+++ TESTING trace trace-03-ops:
# Test of insert_head, insert_tail, reverse, and remove_head
--- trace-03-ops    7/7
+++ TESTING trace trace-04-ops:
# Test of insert_head, insert_tail, and size
--- trace-04-ops    7/7
+++ TESTING trace trace-05-ops:
# Test of insert_head, insert_tail, remove_head reverse, and size
--- trace-05-ops    7/7
+++ TESTING trace trace-06-robust:
# Test operations on NULL queue
--- trace-06-robust 7/7
+++ TESTING trace trace-07-robust:
# Test operations on empty queue
--- trace-07-robust 7/7
+++ TESTING trace trace-08-robust:
# Test remove_head with NULL argument
--- trace-08-robust 7/7
+++ TESTING trace trace-09-malloc:
# Test of malloc failure on new
--- trace-09-malloc 7/7
+++ TESTING trace trace-10-malloc:
# Test of malloc failure on insert_head
--- trace-10-malloc 7/7
+++ TESTING trace trace-11-malloc:
# Test of malloc failure on insert_tail
--- trace-11-malloc 7/7
+++ TESTING trace trace-12-perf:
# Test performance of insert_tail
--- trace-12-perf   7/7
+++ TESTING trace trace-13-perf:
# Test performance of size
--- trace-13-perf   8/8
+++ TESTING trace trace-14-perf:
# Test performance of insert_tail, size, and reverse
--- trace-14-perf   8/8
--- TOTAL       100/100

点赞