Tuesday 9 April 2013

Complete Double Linked List with class Template


Convert to template DLL from int DLL.

Source Files:

dll_template.h.
#ifndef __DLL_H__
#define __DLL_H__
template <class T>
class DLL;
template <class T>
class Node {
 T _data;
 Node<T>* _prev;
 Node<T>* _next;
 Node(T data, Node<T>* prev = (Node<T>*)0, Node<T>* next = (Node<T>*)0);
 friend class DLL<T>;
};
template <class T>
class DLL {
 Node<T>* _head;
 Node<T>* _curr;
 Node<T>* _tail;
 DLL(DLL<T>& D); // prevent copying
 DLL<T>& operator=(DLL<T>& D);
public:
 DLL();
 virtual ~DLL();
 void append(T data); // add after tail
 T remove();   // remove the current goes next if possible
 void insert(T data); // insert data before current
 T visit();   // returns data of current
 bool goHead();
 bool goTail();
 bool goNext();
 bool goPrev();
 bool isEmpty();
};
#endif

dll_template.cpp
#include "dll.h"

template <class T>
Node<T>::Node(T data, Node<T>* prev, Node<T>* next) {
 _data = data;
 _prev = prev;
 _next = next;
}
template <class T>
DLL<T>::DLL() {
 _head = (Node<T>*)0;
 _curr = (Node<T>*)0;
 _tail = (Node<T>*)0;
}
template <class T>
DLL<T>::~DLL() {
 while(!isEmpty()) {
  remove();
 }
}
template <class T>
void DLL<T>::append(T data) {
 if(isEmpty()) {
  Node<T>* newNode = new Node<T>(data);
  _head = newNode;
  _curr = newNode;
  _tail = newNode;
 }
 else {
  Node<T>* newNode = new Node<T>(data);
  newNode->_prev = _curr;
  _curr->_next = newNode;
  _tail = newNode;
  _curr = newNode;
 }
}
template <class T>
T DLL<T>::remove() {
 T data = 0;
 if(!isEmpty()) {
  Node<T>* ToDel = _curr;
  data = _curr->_data;
  if(_curr == _head && _curr == _tail) {
   _head = (Node<T>*)0;
   _curr = (Node<T>*)0;
   _tail = (Node<T>*)0;
   delete ToDel;
  }
  else if(_curr == _head) {
   _curr->_next->_prev = _curr->_prev;
   _head = _curr->_next;
   _curr = _head;
   delete ToDel;
  }
  else if(_curr == _tail) {
   _curr->_prev->_next = _curr->_next;
   _tail = _curr->_prev;
   _curr = _tail;
   delete ToDel;
  }
  else {
   _curr->_next->_prev = _curr->_prev;
   _curr->_prev->_next = _curr->_next;
   _curr = _curr->_next;
   delete ToDel;
  }
 }
 return data;
}
template <class T>
void DLL<T>::insert(T data) {
 Node<T>* newNode = new Node<T>(data);
 if(isEmpty()) {
  _head = newNode;
  _curr = newNode;
  _tail = newNode;
 }
 else if(_curr == _head) {
  newNode->_next = _head;
  _head->_prev = newNode;
  _head = newNode;
  _curr = newNode;
 }
 else {
  newNode->_prev = _curr->_prev;
  newNode->_next = _curr;
  _curr->_prev->_next = newNode;
  _curr->_prev = newNode;
  _curr = newNode;
 }
}
template <class T>
T DLL<T>::visit() {
 return _curr->_data;
}
template <class T>
bool DLL<T>::goHead() {
 _curr = _head;
 return true;
}
template <class T>
bool DLL<T>::goTail() {
 _curr = _tail;
 return true;
}
template <class T>
bool DLL<T>::goNext() {
 if(_curr != _tail) {
  _curr = _curr->_next;
  return true;
 }
 else {
  return false;
 }
}
template <class T>
bool DLL<T>::goPrev() {
 if(_curr != _head) {
  _curr = _curr->_prev;
  return true;
 }
 else {
  return false;
 }
}
template <class T>
bool DLL<T>::isEmpty() {
 return !_head && !_curr && !_tail;
}

dlltester_template.cpp
#include "dll.h"
#include "dll.cpp"
#include <iostream>
using namespace std;

template <class T>
void printList(DLL<T>& d){
    d.goHead();
}
template <class T>
ostream& operator<<(ostream& os, DLL<T>& d){
  int cur;
  bool done = false;
  for(cur=0;d.goPrev();cur++); // findout where is current
  do{
    os<<d.visit();
    done = !d.goNext();
    if(!done){
      os<<", ";
    }
  }while(!done);
  for(d.goHead();cur;d.goNext(), cur--); // set current to what it was before
  return os;
}
template <class T>
ostream& operator>>(ostream& os, DLL<T>& d){ // printing in reverse!!!!!
  int cur;
  bool done = false;
  for(cur=0;d.goNext();cur++); // findout where is current
  do{
    os<<d.visit();
    done = !d.goPrev();
    if(!done){
      os<<", ";
    }
  }while(!done);
  for(d.goTail();cur;d.goPrev(), cur--); // set current to what it was before
  return os;
}

int main(){
  DLL<int> d;
  for(int i=0;i<10;i++){
    d.append(i+1);
  }
  cout<<d<<endl;
  d.goHead();
  d.insert(1000);
  d.goNext();
  d.insert(2000);
  cout<<d<<endl;
  cout>>d<<endl;
  cout<<d.remove()<<endl;
  cout<<d<<endl;
  return 0;
}

Complete Double Linked List with a test file.

To do:
 - Code DLL.

Source Files:
dll.h file.
#ifndef __DLL_H__
#define __DLL_H__
class DLL;
class Node {
 int _data;
 Node* _prev;
 Node* _next;
 Node(int data, Node* prev = (Node*)0, Node* next = (Node*)0);
 friend class DLL;
};
class DLL {
 Node* _head;
 Node* _curr;
 Node* _tail;
 DLL(DLL& D); // prevent copying
 DLL& operator=(DLL& D);
public:
 DLL();
 virtual ~DLL();
 void append(int data); // add after tail
 int remove();   // remove the current goes next if possible
 void insert(int data); // insert data before current
 int visit();   // returns data of current
 bool goHead();
 bool goTail();
 bool goNext();
 bool goPrev();
 bool isEmpty();
};
#endif

dll.cpp file.
#include "dll.h"

Node::Node(int data, Node* prev, Node* next) {
 _data = data;
 _prev = prev;
 _next = next;
}

DLL::DLL() {
 _head = (Node*)0;
 _curr = (Node*)0;
 _tail = (Node*)0;
}
DLL::~DLL() {
 while(!isEmpty()) {
  remove();
 }
}
void DLL::append(int data) {
 if(isEmpty()) {
  Node* newNode = new Node(data);
  _head = newNode;
  _curr = newNode;
  _tail = newNode;
 }
 else {
  Node* newNode = new Node(data);
  newNode->_prev = _curr;
  _curr->_next = newNode;
  _tail = newNode;
  _curr = newNode;
 }
}
int DLL::remove() {
 int data = 0;
 if(!isEmpty()) {
  Node* ToDel = _curr;
  data = _curr->_data;
  if(_curr == _head && _curr == _tail) {
   _head = (Node*)0;
   _curr = (Node*)0;
   _tail = (Node*)0;
   delete ToDel;
  }
  else if(_curr == _head) {
   _curr->_next->_prev = _curr->_prev;
   _head = _curr->_next;
   _curr = _head;
   delete ToDel;
  }
  else if(_curr == _tail) {
   _curr->_prev->_next = _curr->_next;
   _tail = _curr->_prev;
   _curr = _tail;
   delete ToDel;
  }
  else {
   _curr->_next->_prev = _curr->_prev;
   _curr->_prev->_next = _curr->_next;
   _curr = _curr->_next;
   delete ToDel;
  }
 }
 return data;
}
void DLL::insert(int data) {
 Node* newNode = new Node(data);
 if(isEmpty()) {
  _head = newNode;
  _curr = newNode;
  _tail = newNode;
 }
 else if(_curr == _head) {
  newNode->_next = _head;
  _head->_prev = newNode;
  _head = newNode;
  _curr = newNode;
 }
 else {
  newNode->_prev = _curr->_prev;
  newNode->_next = _curr;
  _curr->_prev->_next = newNode;
  _curr->_prev = newNode;
  _curr = newNode;
 }
}
int DLL::visit() {
 return _curr->_data;
}
bool DLL::goHead() {
 _curr = _head;
 return true;
}
bool DLL::goTail() {
 _curr = _tail;
 return true;
}
bool DLL::goNext() {
 if(_curr != _tail) {
  _curr = _curr->_next;
  return true;
 }
 else {
  return false;
 }
}
bool DLL::goPrev() {
 if(_curr != _head) {
  _curr = _curr->_prev;
  return true;
 }
 else {
  return false;
 }
}
bool DLL::isEmpty() {
 return !_head && !_curr && !_tail;
}

dlltester.cpp file.
// provided by professor.
#include "dll.h"
#include <iostream>
using namespace std;

void printList(DLL& d){
    d.goHead();
}
ostream& operator<<(ostream& os, DLL& d){
  int cur;
  bool done = false;
  for(cur=0;d.goPrev();cur++); // findout where is current
  do{
    os<<d.visit();
    done = !d.goNext();
    if(!done){
      os<<", ";
    }
  }while(!done);
  for(d.goHead();cur;d.goNext(), cur--); // set current to what it was before
  return os;
}
ostream& operator>>(ostream& os, DLL& d){ // printing in reverse!!!!!
  int cur;
  bool done = false;
  for(cur=0;d.goNext();cur++); // findout where is current
  do{
    os<<d.visit();
    done = !d.goPrev();
    if(!done){
      os<<", ";
    }
  }while(!done);
  for(d.goTail();cur;d.goPrev(), cur--); // set current to what it was before
  return os;
}

int main(){
  DLL d;
  for(int i=0;i<10;i++){
    d.append(i+1);
  }
  cout<<d<<endl;
  d.goHead();
  d.insert(1000);
  d.goNext();
  d.insert(2000);
  cout<<d<<endl;
  cout>>d<<endl;
  cout<<d.remove()<<endl;
  cout<<d<<endl;
  return 0;
}

Queue add method

To do:
 - Do the add method of the Queue as exercise

Source Code:
Queue.h file
#pragma once
#ifndef __QUEUE_H__
#define __QUEUE_H__

class Queue;
class Node{
 int _data;
 Node* _next;
 Node(int data, Node* next= (Node*)0);
 friend class Queue;
};
class Queue{
private:
 Node* _head;
public:
 Queue();
 void add(int data);
 int remove();
 bool isEmpty();
 virtual ~Queue();
};
#endif


Queue.cpp file
#include "queue.h"  

Node::Node(int data, Node* next) {
 _data = data;
 _next = next;
}
Queue::Queue() {
 _head = (Node*)0;
}
void Queue::add(int data) {
 // 1 create node, and 2 point to next node
 Node* toAdd= new Node(data, _head);
 _head = toAdd; // 3 point to new node
}
int Queue::remove() {
 int ret = _head->_data;  // 1
 // int ret = (*_head)._data;  // 1 crazy but ok
 Node* toDel = _head;  // 2
 _head = _head->_next;  // 3 
 //  _head = toDel->_next; //  same as 3
 delete toDel; // 5
 return ret;
}
bool Queue::isEmpty() {
 /*if(_head == (Node*)0) {
  return true;
 }
 else {
  return false;
 }*/
 return _head == (Node*)0 ? true : false;
}
Queue::~Queue() {
 while(!isEmpty()) {
  remove();
 }
}

Monday 21 January 2013

Two Simple Programs from OOP344

OOP344 class.
Two problems to solve.:

1. write 4 command line programs to do
$ add num num<ENTER>
$ sub num num<ENTER>
$ mul num num<ENTER>
$ div num num<ENTER>

2. write a program to show the content of an Operating system environment variable
$ prnenv path<ENTER>
The output will be either the "content" of path variable or "not found" if the environment variable does not exist.

Features added by myself.
to 1. for first program, Error checking in case of wrong inputs such as with characters(add 123 38a)
to 2. for second program, lists all environments' name.

Code (First program):
// Homework Question 1
// Write a program to do math values got from command line

// File:        q1.cpp
// Subject:	OOP344
// Author:	Hanho Ko
// Section:	A

#include <iostream>
#include <cstring>
using namespace std;

// Dispaly help message
void displayHelp(char* prg) {
	cout<<"To use this program..."<<endl;
	cout<<"   "<<prg<<" <Argument 1> <Argument 2> <Argument 3>"<<endl;
	cout<<"    *** <Argument 1> must be one of 'add', 'sub', 'mul' and 'div'."<<endl;
	cout<<"    *** <Argument 2> and <Argument 3> must be an integer(NOT double)."<<endl;
	cout<<"   ex."<<endl;
	cout<<"      $> "<<prg<<" add 325 942"<<endl;
	cout<<endl;
}

// check the arguments are integer or not
int checkInt(char* str) {
	int i;
	for(i=0; str[i]!='\0'; i++) {
		if(str[i] < 48 || str[i] > 57)
			return 0;
	}
	return 1;
}

int main(int argc, char* argv[]) {
	// val1 and val2 are valuables to store integer from command line
	// flag stores a value to do math or check wrong input
	int val1, val2, i, flag=-1;
	// math contains arithmetic operations
	char math[4][4]={"add", "sub", "mul", "div"};

	// check number of arguments taken from command line
	if(argc<3) {
		displayHelp(argv[0]); // display help message
		return 0; // terminate the program
	}

	// check the arguments that are integer or not
	if(checkInt(argv[2])==1 && checkInt(argv[3])==1) {
		val1=atoi(argv[2]); // convert characters to integer
		val2=atoi(argv[3]); // convert characters to integer

		// check the argument is one of arithmetic operations
		for(i=0; i<4; i++) {
			if(strcmp(math[i], argv[1])==0)
				flag=i; // if it is, then store index number
		}

		cout<<endl;

		// by index number, process arithmetic operation
		switch(flag) {
		case 0: // add
			cout<<val1+val2<<endl;
			break;
		case 1: // sub
			cout<<val1-val2<<endl;
			break;
		case 2: // mul
			cout<<val1*val2<<endl;
			break;
		case 3: // div
			// type-casting to get an accurate value
			cout<<(double)val1/(double)val2<<endl;
			break;
		default: // wrong input
			displayHelp(argv[0]);
			break;
		}
	}
	// if the arguments are not integer
	else {
		displayHelp(argv[0]); // display help message
		return 0;
	}

	return 0;
}

Code (Second program):
// Homework Question 2
// Write a program to print the value of an environment variable

// File:        q2.cpp
// Subject:	OOP344
// Author:	Hanho Ko
// Section:	A

#include <iostream>
#include <cstring>
using namespace std;

// get the name of environment
void getName(char* str, char* tmp) {
	int i;
	for(i=0; str[i]!='='; i++) // store characters before '='
		tmp[i]=str[i];
	tmp[i]=0; // add null byte
}

// get the value of environment
void getValue(char* str, char* tmp) {
	int i, j;
	for(i=0; str[i]!='='; i++); // skip until reach '='
	for(j=0, i++; str[i]!=0; i++, j++) // store characters after '='
		tmp[j]=str[i];
	tmp[j]=0; // add null byte
}

int main(int argc, char* argv[], char* env[]) {
	int i, flag=-1; // flag is for index of environment
	char envName[50], tmp[1024];
	
	for(i=0; env[i]!=0; i++) { // list the names of an environment
		getName(env[i], tmp);
		printf(" %-25s", tmp); // left align and assign 25 columns for each name
		if((i+1)%3==0) // new line after list 3 names in one line
			cout<<endl;
	}

	cout<<endl<<endl<<"Enter the name of an environment[Less than 50 characters, Case sensetive]"<<endl<<" Environment name: ";
	cin>>envName;

	for(i=0; env[i]!=0; i++) {
		getName(env[i], tmp); // get the name from the environment split by '='
		if(strcmp(envName, tmp)==0) { // compare two names
			flag=i; // if found the name, put index number into flag
		}
	}
	if(flag>=0) { // check flag that found the same name or not
		cout<<endl<<"Found! The value of '"<<envName<<"' is: "<<endl;
		getValue(env[flag], tmp); // get the value from the environment split by '='
		cout<<tmp<<endl;
	}
	else // print message if not found
		cout<<endl<<"Not found..."<<endl;

	return 0;
}

Source Files:
Download q1.cpp
Download q2.cpp

Sunday 10 July 2011

OOP344A - First post

Hello, World!!

I'm currently in Seneca College and taking CPA (Computer Programming and Analysis).

Nice to meet you!