Hi!

I am supposed to only use the "procedural fragment of C++", i.e. no object-oriented programming (like cin, cout etc). Vectors are not allowed either.

So, one of my goals is to count the number of lines in a text file (let's call it train1.in) which contains data like:

engine 15
engine 40
coach 30
boxcar 52

Now, I am supposed to count the number of cars (i.e. the number of lines in the file), which in this particular case is clearly 4 (two engines, a coach, a boxcar).

Please tell me a simple way to do this. I have one idea in mind- count the number of newlines but I am not sure how exactly to implement this. I am not sure but I think getline() is perhaps not a part of procedural C++. The bottomline is that the code should look like C code.

I have another question. I am just interested in knowing how to read the "spur file_name n" and "shunt file_name n" from user and interpret them as commands.

Write pseudocode and procedural C++ routine for a main routine that accepts a sequence of

train construction commands from standard input (i.e. just use read).
• spur fname n – accept a filename and a number of cars (locomotives) to remove
• shunt fname n – accept a filename and a number of cars (locomotives) to remove (before the reversal)
and then print out the train that results from concatenating each of the trains that the commands generate,
including its length.
For example, if train1.in contains
engine 15
engine 40
coach 30
boxcar 52
and train2.in contains
engine 25
engine 35
lowboy 45
hopper 50

then the commands

spur train1.in 1
shunt train2.in 2

yield

The train contains 5 cars
engine, 40 m.
coach, 30 m.
boxcar, 52 m.
hopper, 50 m.
lowboy, 45 m.
totalling 217 m.

So, if I get to know how to read the commands from user and also interpret them then I will put the necessary code in braces to perform the requisite task. I need help on this as soon as possible. I would greatly appreciate your help.
Thanks a lot!!:)

I have written a few pseudocode algorithms (may have a lot of errors)
http://pastebin.com/HFkrHuGR

Edited 5 Years Ago by codeyy: n/a

Attachments
// main.cc -- for trains
//
// CMPT 115 WT2 2010-2011

#include <cstdlib>
#include <cstdio>
#include "train.cc"
//#include "train.h" this header file is not needed

int main() {

  int ncars = -1;
  while (true) {
    fprintf(stdout, "How many cars: ");
    fscanf(stdin, " %d", &ncars);
    if (ncars >= 0) { break; }
  }

  Train* trainPtr = makeTrain(ncars);

  fprintf(stdout, "Where to find them: ");
  char fname[BUFSIZ];
  fscanf(stdin, " %s", fname);

  if (! readTrain(*trainPtr, fname)) {
    fprintf(stderr, "Could not read the train\n");
    return EXIT_FAILURE;
  }

  printTrain(*trainPtr);
  destroyTrain(trainPtr);
  return EXIT_SUCCESS;
}
// train.h -- data structures for trains
//
// CMPT 115 WT2 2010-2011

struct Car {
  char *kind;
  int length;
};

struct Train {
  int nCars;
  Car *cars;
};

// fill in a shared car structure
void setCar(Car&, const char*, const int);

// allocate a new train
Train* makeTrain(const int);

// read a train
bool readTrain(Train&, const char*);

// print a car
int printCar(const Car, const int);

// print a train
int printTrain(const Train);

// destroy a train
void destroyTrain(Train*);

In C, you read a text file line by line, using

fgets(charArrayName, sizeof(charArrayName), filePointerName);

Which will automatically insert the whole line of text, into your char array, including the newline (and the end of string char: '\0', after that. (If room allows).

while((fgets(charArrayName, sizeof(charArrayName), filePointerName)) != NULL) {
  //your code here

}

Is a standard idiom in C to read every row of text in the file.

Railroad theme, I see. ;)

Edited 5 Years Ago by Adak: n/a

Comments
very helpful

If you can't use c++ objects then use FILE* and call fgets() in a loop until end-of-file is reached, counting the number of iterations of the loop. When done, you will have the number of lines in the file.

Comments
thanks.

Thank you so much, Adak! All I had to do to count lines was putting count=count+1 inside while loop.

Any way, I still need to figure out the second question I asked, i.e. how to take commands from user and also interpret them as two different commands.
For example, if the user inputs: spur train1.in 1 then the program runs a certain set of functions that spur the given train
and if the user inputs shunt train2.in 2 then the program runs a certain set of functions that shunt the given train

Thanks again.:)
Hopefully, this will solve all my major difficulties because I think I have got the pseudocode algorithms more or less in good shape. All I had trouble with was with reading strings etc.

PS: train1.in and train2.in are filenames for text files containing stuff like:
engine 45
coach 36
boxcar 26

Edited 5 Years Ago by codeyy: n/a

First you have to write a function for each command you want to support

Next, read a line, split the line into its individual words, then call the appropriate function for the verb in the first part of the string. Something like this:

string verb;
string line;
size_t pos = line.find(' '); // find first word
verb = line.substr(0,pos);
if( verb == "spur")
   spur(line);
else if(verb == "shunt")
   shunt(line);

I wish to add that:

From the user input command, I also want to retrieve the filename (e.g. train1.in) and the following number (e.g. 1) and store them as separate variables.

Thanks

The easiest way to do that would be to use stringstream class

#include <sstirng>
#include <string>
#include <fstream>
// other includes too

int main()
{
   std::string line = "shunt train2.in 2";
   std::string verb, filename;
   int num;
   strgingstream s(line);
   // now splie the line into its individual parts
   s >> verb >> filename >> num;
}

Hi, Ancient Dragon!

Thanks for your input but I am afraid I am not allowed to use any object-oriented programming and can only use the "procedural fragment of C++". In other words, anything that works in C is allowed.

From your code, it appears to me that I may be violating the rules. Please correct me if I am mistaken here because I do not know as much about C and C++ as you do. The << reminds me of OOP because cin and cout are not allowed in procedural C++.

Edited 5 Years Ago by codeyy: n/a

Sounds like you have to write a C program, not a C++ program. In that case I would use strtok() to split the line.

#include <stdio.h>
#include <string.h>

int main()
{
   char line[] = "shunt train2.in 2";
   char *verb, *filename, *ptr;
   int num;
   verb = strtok(line," ");
   filename = strtok(NULL," ");
   ptr = strtok(NULL," ");
   printf("%s %s %s\n", verb,filename,ptr);
}

Edited 5 Years Ago by Ancient Dragon: n/a

Thanks a lot, Ancient Dragon! Your program worked like a charm and is very helpful.:icon_biggrin:

It looks to me like everyone miss this line in your instructions:

train construction commands from standard input (i.e. just use read).

Your instructor told you what command to use for input, didn't he?
I agree fgets() is better. Then again, maybe he meant it only as an example.

Edited 5 Years Ago by WaltP: n/a

I have a problem with adding of two trains. Consider the scenario when I do not know how many trains the user is going to perform operations on. The user will input a set of commands on a certain number of trains. At the end of all operations, I need to join one train after the other (like linked lists) in the order in which the commands concerning those trains were input.

So, how can I add two trains one after the other?
Furthermore, since I do not know the number of trains the user will be operating on, I intend to prompt the user to enter the number of trains. Then using a loop, I will prompt the user to enter commands for each train individually and respectively. While taking each command, I will be executing the commands immediately and when all the commands for a single train (starting with the first train) have been executed, I add them to an empty queue (or stack). For the next train, all the commands will be executed and the resulting train will be added just behind the previous one in the queue (or stack).

So, I do not know the exact C way to add the trains, one behind each other. All I can think of is linking the tail of the first to the head of the latter but I don't know how exactly it will be implemented.
Some files are available for me to use with a note saying (You will need to (only) change the typedef lines inside Stack.h and Queue.h in order to use our code. You still do not need to hand in the Stack.h and Queue.h files however.) :
Queues (i.e. Queue.h, QueueInterface.h, and Queue.cc) and Stacks (i.e.
Stack.h, StackInterface.h, and Stack.cc)

struct Car {
  char *kind;
  int length;
};

struct Train {
  int nCars;
  Car *cars;
};


Write C routine for a main routine() that accepts a sequence of

train construction commands from standard input (i.e. just use read).
• spur fname n – accept a filename and a number of cars (locomotives) to remove
• shunt fname n – accept a filename and a number of cars (locomotives) to remove (before the reversal)
and then print out the train that results from concatenating each of the trains that the commands generate, including its length.
For example, if train1.in contains

engine 15
engine 40
coach 30
boxcar 52

and train2.in contains
engine 25
engine 35
lowboy 45
hopper 50

then the commands

spur train1.in 1
shunt train2.in 2

yield

The train contains 5 cars
engine, 40 m.
coach, 30 m.
boxcar, 52 m.
hopper, 50 m.
lowboy, 45 m.
totalling 217 m.

Attachments
#include <cstdlib>
#include <cassert>

#include "Queue.h"
#include "QueueInterface.h"

using namespace std;

// create a queue with the given capacity
Queue CreateQueue(int capacity) {
  assert (0 < capacity);

  Queue q;
  q.elts = new Element[capacity];
  if (NULL == q.elts) {
    q.capacity = 0;
    return q;
  }
  q.head = 0;
  q.count = 0;
  q.capacity = capacity;
  return q;
}

// destroy a queue
void DestroyQueue(Queue& q) {
  delete q.elts;
  q.elts = NULL;
  q.head = 0;
  q.count = 0;
  q.capacity = 0;
}

// enqueue an element, indicating success
bool EnQueue(Queue& q, Element& e) {
  if (q.count >= q.capacity) {
    return false;
  }
  q.elts[(q.head + q.count) % q.capacity] = e;
  q.count += 1;
  return true;
}

// dequeue an element, indicating success
bool DeQueue(Queue& q, Element& e) {
  if (0 < q.count) {
    e = q.elts[q.head];
    q.head = (q.head + 1) % q.capacity;
    q.count -= 1;
    return true;
  }
  return false;
}

 // return the number of elements in the queue
int QueueSize(const Queue q) {
  return q.count;
}
// Queue.h

#ifndef _QUEUE_H_
#define _QUEUE_H_

typedef int Element;		// or use Element.h and Element.cc

// we will use a circular-based array for the queue
struct Queue {
  Element *elts;		// the elements
  int head;			// the first one entered
  int count;			// how many are waiting: tail is head+count
  int capacity;			// how many we can hold
};

#endif // _QUEUE_H_
// queue.h

Queue CreateQueue(int);	        // create a queue with the given capacity

void DestroyQueue(Queue&);	// destroy a queue

bool EnQueue(Queue&, Element&); // enqueue an element, indicating success

bool DeQueue(Queue&, Element&); // dequeue an element, indicating success

int QueueSize(const Queue);     // return the number of elements in the queue
#include <cstdlib>
#include "StackInterface.h"

//  Create a new Stack.
//  Pre: size is the max number of values to be stored in the Stack
//  Return: a new Stack
//
Stack CreateStack(const int capacity) {
  Stack stack;
  stack.numElements = 0;
  stack.arr = new Element[capacity]; // allocate space for elements
  if ( NULL == stack.arr ) {
    stack.capacity = -1;	// Houston, we have a problem.
  } else {
    stack.capacity = capacity; // set maximum number elements to be stored
  }
  return stack; // return Stack
}

//  Pushes element to the top of the Stack.
//  Pre: stack is the Stack into which to push
//       dataIn is the element to be inserted
//  Post: dataIn is pushed onto the top of the Stack
//  Return: true if successful, false if not enough capacity
//
bool PushOntoStack(Stack& stack, const Element dataIn) {
  if ( stack.numElements < stack.capacity ) {
    stack.arr[stack.numElements] = dataIn;
    stack.numElements += 1;
    return true;
  }
  return false;
}

//  Pops the top of the Stack
//  Pre: stack is the Stack to delete from
//       dataOut is a shared variable to receive the
//       removed element
//  Post: Contents of element stored in *dataOut,
//        Stack pops the top element
//  Return: true if successful, false otherwise
//
bool PopFromStack(Stack& stack, Element& dataOut) {
  if ( 0 < stack.numElements ) {
    stack.numElements -= 1;
    dataOut = stack.arr[stack.numElements];
    return true;
  }
  return false;
}

//  Retrieves the element from the top of the Stack without
//  changing the Stack.
//  Pre: stack is Stack to return element from
//       dataOut is reference to a variable to receive the
//       retrieved element
//  Post: Contents of element stored in *dataOut is the top
//        element of the Stack
//  Return: true if successful, false otherwise
//
bool PeekAtStack(const Stack stack, Element& dataOut) {
  if ( 0 != stack.numElements ) {
    dataOut = stack.arr[(stack.numElements)-1];
    return true;
  }
  return false;
}

//  Determines if a Stack is empty
//  Pre: stack is a Stack
//  Return: true is stack is empty; false if there is at least
//          one element in stack.
//
bool StackIsEmpty(const Stack stack) {
  return (1 > stack.numElements);
}

//  Determine number of elements stored in Stack
//  Pre: stack is a Stack to be checked
//  Return: number of elements in stack
//
int StackCount(const Stack stack) {
  return stack.numElements;
}

//  Free all memory to the heap.
//  Pre: stack is a Stack to be destroyed
//  Post: De-allocates arr in stack
//
void DestroyStack(Stack& stack) {
  delete [] stack.arr;
  stack.arr = NULL;
  stack.capacity = -1;
  stack.numElements = 0;
}
//
// Array-based Stack Implementation
//

#ifndef _STACK_H_

// type definition for Element
// in a more general situation, this would be #include "Element.h"
typedef int Element;

// type defintion for Stack -- beginning with the structure ...
struct Stack {
  Element* arr;
  int numElements;		// arr[numElements] will be the first unused space
  int capacity;
};

#endif _STACK_H_
//
// The Stack Interface (function prototypes for operations)
//

#include "Stack.h"

// create a new empty stack of given capacity
Stack CreateStack(const int);

// push an Element onto the stack, returning success or failure
bool PushOntoStack(Stack&, const Element);

// pop an Element from the stack, returning success or failure
bool PopFromStack(Stack&, Element&);

// peek at the top Element on the stack, returning success or failure
bool PeekAtStack(const Stack, Element&);

// indicate whether the stack is empty
bool StackIsEmpty(const Stack);

// indicate the number of elements pushed onto the stack
int StackCount(const Stack);

// destroy the stack, including all elements
void DestroyStack(Stack&);

It looks to me like everyone miss this line in your instructions:

Your instructor told you what command to use for input, didn't he?
I agree fgets() is better. Then again, maybe he meant it only as an example.

Sorry for the confusion WaltP. First we have to write main() in pseudocode (and that is why "read" was used) and then the pseudocode should be translated to procedural C++ code (which is just like writing C code in C++).

Please help me with my current problem. I do not fully understand how the Train structure could be manipulated with these given routines.

Instructor:
you can include train.h, and use the train functions with the typedef Car Element; statement (and there will be a typedef added to the file by the TA's, making Elements equivalent to the Car struct)

or, you can use the element structure defined in one of these threads, and include element.h.

the two are incompatible. there is one other complication: the typedefs existing on the stack and queue.h files need to be removed for either of these methods to work. this will be done come grading of the assignments, but you need to do it yourself to test your program.

Instructor gives some more details:

We will be using our own

    * List.cc,
    * List.h,
    * ListInterface.h,

rrom tutorial 5: where Element.h actually be train.h since we (obviously) use a Car structure as the element (as in Assignment 3).

We will be using

    * Stack.cc,
    * Stack.h,
    * StackInterface.h,

from tutorial 6 (again our element will be generalized to a Car structure).

We will be using

    * Queue.cc,
    * Queue.h,
    * QueueInterface.h,

from tutorial 7 (again our element will be generalized to a Car structure), and

    * train.cc
    * train.h (which will contain the Car structure)

from assignment 3.

As long as your code only calls ADT routines as documented in ListInterface.h, StackInterface.h, QueueInterface.h for the various tutorials, and train.cc as in Assignment 3, it will work with our code.

Note that this means you cannot rely on a particular List implementation, (i.e. no accessing an array element of a List, or using a next pointer).  You can only insertHead, insertTail, deleteHead, deleteTail, head, tail, destroyList, createList, etc.  You also cannot rely on a particular Stack or Queue implementation, but you must use push, pop, enQueue, deQueue, empty, ...
 
More details again:
 
Recalling assignment 3,

struct Car {
    char *kind;
    int length;
}

struct Train {
    int nCars;
    Car *cars;
}

After getting Element.h and Element.cc from Tutorial 5 to understand that elements will be cars, we can try something:

#include <cstdlib>
#include <cassert>
#include <cstdio>

#include "train.h"           // from Assignment 3
typedef Car Element;

#include "List.h"            // from Tutorial 5
#include "ListInterface.h";  // from Tutorial 5

// accept a train and return it as a List of Cars
// using only the operations in the List ADT
List train2List(Train t) {
    List trainAsList = createList();
    for (int i=0; i<t.nCars; i+=1) {
        assert(insertTail(trainAsList, t.cars[i]));
    }
    return trainAsList;
}

// accept a List of Cars and convert it to a train
// using only the operations in the List ADT
Train list2Train(List l) {
    Train t = *(makeTrain(lengthList(l)));
    for (int i=0; !emptyList(l); i+=1) {
        assert(head(l, t.cars[i]));
        assert(deleteHead(l));
    }
    return t;
}

// simple activity
int main() {
    while (!feof(stdin)) {
        int nCars;
        char tFile[BUFSIZ];

scanf(" %d %s", &nCars, tFile);
if (0 == nCars) { // stop when the count is 0
     break;
        }
        Train t = *(makeTrain(nCars));
if (!readTrain(t, tFile)) {
            fprintf(stderr, "Read failed\n");
            continue;
        }
char ignored[BUFSIZ];
fgets(ignored, BUFSIZ, stdin);

printTrain(t);
        List l = train2List(t);
        Train t2 = list2Train(l);
        printf("\n This should be the same:\n");
        printTrain(t2);
    }

    return EXIT_SUCCESS;
}

This will do a simple activity, of reading a train and operating it on as a List.

I am attaching the lab5 files on Element and List.

Edited 5 Years Ago by codeyy: n/a

Comments
Endless repitition of the same text and attaching the same files to every post is a waste or your time and our bandwidth. Think before you post!
Attachments
//
// Elements to store in lists
//
// Christopher Dutchyn, for CMPT115 2010 WT2, February 2011
//

#include <cstdio>
#include "Element.h"

// create an element with given key and data
Element createElement(const Key& k, const Data& d) {
  Element e;
  e.key = k;
  e.data = d;
  return e;
}

// destroy an element
void destroyElement(Element& e) {
  //delete e.data;		// only for dynamically allocated data that isn't pointed to from elsewhere
}

// get the key from an element
Key getKey(const Element& e) {
  return e.key;
}

// !!!!! MUST BE CUSTOMIZED TO YOUR KEY TYPE !!!!!
// compare two elements' keys
Comparison compareKeys(const Key& k1, const Key& k2) {
  return (k1 - k2);
}

// !!!!! MUST BE CUSTOMIZED TO YOUR KEY TYPE !!!!!
// print out an element
void fPrintElement(FILE* f, const Element& e) {
  fprintf(f, "\t%d %s\n", e.key, e.data);
}
//
// Elements
//

#ifndef _ELEMENT_H_
  #define _ELEMENT_H_

  #include <cstdio>

// a simple Element: a number as the key
//               and a string as the data
typedef int   Key;		// change 'int' to your key type
typedef char* Data;		// change 'char*' to your data type

struct Element {
  Key key;
  Data data;
};

// comparing keys will return values just like strcmp() does
typedef int Comparison;
const int EQUAL_ELEMENT = 0;

// create an element with given key and data
Element createElement(const Key&, const Data&);
// destroy an element
void destroyElement(Element&);

// get the key from an element
Key getKey(const Element&);
// compare two elements' keys
Comparison compareKeys(const Key&, const Key&);

// print an element to the given place
void fPrintElement(FILE*, const Element&);

#endif /*_ELEMENT_H_*/
//
// Simple Lists: the list contains a pointer to the head node
//
// Christopher Dutchyn, for CMPT115 2010 WT2, February 2011
//

#include <cassert>
#include "Element.h"
#include "List.h"
#include "ListInterface.h"

// CONSTRUCTOR and DESTRUCTOR
// create a new empty list
List createList() {
  List l;

  l.head = NULL;
  l.count = 0;

  return l;
}

// destroy an existing list
void destroyList(List& l) {
  Node* p = l.head;
  while (NULL != p) {
    Node* t = p->next;
    destroyElement(p->data);
    delete p;
    p = t;
  }
  l.head = NULL;
}


// STATUS
// check whether a list is empty
bool emptyList(const List l) {
  return (NULL == l.head);
}

// return the element count of a list
int lengthList(const List l) {
  return l.count;
}


// INSERTION -- return indicates success or failure
// insert the element into the list as the head
bool insertHead(List& l, Element e) {
  Node* n = new Node;
  if (NULL == n) {
    return false;
  }

  n->data = e;
  n->next = l.head;
  l.head = n;
  l.count += 1;

  return true;
}

// insert the element into the list as the tail
bool insertTail(List& l, Element e) {
  if (NULL == l.head) {
    return insertHead(l, e);
  }

  Node* n = new Node;
  if (NULL == n) {
    return false;
  }

  n->data = e;
  n->next = NULL;
  l.count += 1;

  Node* p = l.head;
  assert (NULL != p);
  while (NULL != p->next) {
    p = p->next;
  }
  assert ((NULL != p) && (NULL == p->next));
  p->next = n;

  return true;
}

// EXTRACTION -- return indicates success or failure
// return the element at the head of the list
bool head(const List l, Element& e) {
  if (NULL == l.head) {
    return false;
  }
  e = (l.head)->data;
  return true;
}

// return the element at the tail of the list
bool tail(const List l, Element& e) {
  if (NULL == l.head) {
    return false;
  }
  
  Node* p = l.head;
  assert (NULL != p);
  while (NULL != p->next) {
    p = p->next;
  }

  assert ((NULL != p) && (NULL == p->next));
  e = p->data;
  return true;
}

// return the element matching the key
bool findMatching(const List l, const Key k, Element& e) {
  Node *p = l.head;

  while (NULL != p) {
    if (EQUAL_ELEMENT == compareKeys(k, getKey(p->data))) {
      e = p->data;
      return true;
    }
    p = p->next;
  }
  return false;
}


// DELETION -- return indicates success or failure
// delete the element at the head of the list
bool deleteHead(List& l) {
  if (NULL == l.head) {
    return false;
  }

  l.count -= 1;
  Node *p = l.head;
  l.head = p->next;
  p->next = NULL;
  destroyElement(p->data);
  delete p;
  return true;
}

// delete the element at the tail of the list
bool deleteTail(List& l) {
  if (NULL == l.head) {
    return false;
  }

  if (NULL == (l.head)->next) {
    return deleteHead(l);
  }

  l.count -= 1;
  Node *p = l.head;
  assert (NULL != p);
  assert (NULL != p->next);
  while (NULL != (p->next)->next) {
    p = p->next;
  }

  destroyElement((p->next)->data);
  delete p->next;
  p->next = NULL;
  return true;
}

// delete the element matching the key
bool deleteMatching(List& l, const Key k) {
  if (NULL == l.head) {
    return false;
  }

  assert (NULL != l.head);
  if (EQUAL_ELEMENT == compareKeys(k, getKey((l.head)->data))) {
    return deleteHead(l);
  }

  Node *p = l.head;
  assert (NULL != p);
  while (NULL != p->next) {
    if (EQUAL_ELEMENT == compareKeys(k, getKey((p->next)->data))) {
      l.count -= 1;
      Node* t = p->next;
      p->next = (p->next)->next;
      destroyElement(t->data);
      delete t;
      return true;
    }
    p = p->next;
  }
  return false;
}

// DEBUGGING
// print a list to the given file
void fPrintList(FILE* f, const List& l) {
  Node* p = l.head;
  while (NULL != p) {
    fPrintElement(f, p->data);
    p = p->next;
  }
}
//
// Simple Lists: the list contains a pointer to the head node and a count
//
// Christopher Dutchyn, for CMPT115 2010 WT2, February 2011
//

#ifndef _SIMPLE_LIST_
  #define _SIMPLE_LIST_

#include "Element.h"

// a node stores data and points to the next node
struct Node {
  Element data;
  Node* next;
};

// a list contains a pointer to the head node and a count
struct List {
  Node* head;
  int count;
};

#endif /*_SIMPLE_LIST_*/
//
// the List Operations
//
// Christopher Dutchyn, for CMPT115 2010 WT2, February 2011
//

#include <cstdio>		// FILE*

// must have Key, Element, Comparison typedef'ed -- usually by having #include "Element.h" before including this file
// must have List typedef'ed                     -- usually by having #include "List.h"    before including this file

// CONSTRUCTOR and DESTRUCTOR
// create a new empty list
List createList();
// destroy an existing list
void destroyList(List&);

// STATUS
// check whether a list is empty
bool emptyList(const List);
// return the element count of a list
int lengthList(const List);

// INSERTION -- return indicates success or failure
// insert the element into the list as the head
bool insertHead(List&, const Element);
// insert the element into the list as the tail
bool insertTail(List&, const Element);

// EXTRACTION -- return indicates success or failure
// return the element at the head of the list
bool head(const List, Element&);
// return the element at the tail of the list
bool tail(const List, Element&);
// return the element matching the key
bool findMatching(const List, const Key, Element&);

// DELETION -- return indicates success or failure
// delete the element at the head of the list
bool deleteHead(List&);
// delete the element at the tail of the list
bool deleteTail(List&);
// delete the element matching the key
bool deleteMatching(List&, const Key);

// DEBUGGING
// print a list to the given file
void fPrintList(FILE*, const List&);

The first comment "you can include traing.h ... " was given by a student and not an instructor.

Unfortunately, your post above, is all about your assignment - and not about using C style C++. This is the part of the assignment that you need to work through. It has so many parts to it, with so many constraints, that it's very unlikely anyone will be willing to donate the time necessary to fully understand it. I've read your description of the problem through twice, and have an insufficient grasp of the total problem yet.

And you can't even start to put up pseudo code, until you really understand the problem fully. :(

Use your class notes, your memory from the lectures, and if you're stuck, ask your teacher a class mate, or assistant, to explain some details for you.

My advice is to work it through until and unless, you have a specific problem that is C related, and not assignment related - then we can help you. If you can't describe the C problem in a paragraph or two, you need to get to the point that you can do that.

This article has been dead for over six months. Start a new discussion instead.