Assistance with linked lists

B

B. Williams

I have written some code to accept input and place this input at the
beginning or end of a list, but I need assistance including a class so that
it will allow input of a phone number that is properly formatted. I'll post
my code below. Thanks in advance.

This is the code for the linked list. It tests using int's and string's.

#ifndef LIST_H
#define LIST_H

#include <iostream>
using std::cout;

#include "Listnode.h"

template< typename NODETYPE >
class List
{
public:
List();
~List();
void insertAtFront( const NODETYPE & );
void insertAtBack( const NODETYPE & );
bool removeFromFront( NODETYPE & );
bool removeFromBack( NODETYPE & );
bool isEmpty() const;
void print() const;
private:
ListNode< NODETYPE > *firstPtr;
ListNode< NODETYPE > *lastPtr;

// utility function to allocate new node
ListNode< NODETYPE > *getNewNode( const NODETYPE & );
}; // end class List

// default constructor
template< typename NODETYPE >
List< NODETYPE >::List()
: firstPtr( 0 ), lastPtr( 0 )
{
}

// destructor
template< typename NODETYPE >
List< NODETYPE >::~List()
{
if ( !isEmpty() ) // List is not empty
{
cout << "Destroying nodes ...\n";

ListNode< NODETYPE > *currentPtr = firstPtr;
ListNode< NODETYPE > *tempPtr;

while ( currentPtr != 0 ) // delete remaining nodes
{
tempPtr = currentPtr;
cout << tempPtr->data << '\n';
currentPtr = currentPtr->nextPtr;
delete tempPtr;
} // end while
} // end if

cout << "All nodes destroyed\n\n";
} // end List destructor

// insert node at front of list
template< typename NODETYPE >
void List< NODETYPE >::insertAtFront( const NODETYPE &value )
{
ListNode< NODETYPE > *newPtr = getNewNode( value ); // new node

if ( isEmpty() ) // List is empty
firstPtr = lastPtr = newPtr; // new list has only one node
else // List is not empty
{
newPtr->nextPtr = firstPtr; // point new node to previous 1st node
firstPtr = newPtr; // aim firstPtr at new node
} // end else
} // end function insertAtFront

// insert node at back of list
template< typename NODETYPE >
void List< NODETYPE >::insertAtBack( const NODETYPE &value )
{
ListNode< NODETYPE > *newPtr = getNewNode( value ); // new node

if ( isEmpty() ) // List is empty
firstPtr = lastPtr = newPtr; // new list has only one node
else // List is not empty
{
lastPtr->nextPtr = newPtr; // update previous last node
lastPtr = newPtr; // new last node
} // end else
} // end function insertAtBack

// delete node from front of list
template< typename NODETYPE >
bool List< NODETYPE >::removeFromFront( NODETYPE &value )
{
if ( isEmpty() ) // List is empty
return false; // delete unsuccessful
else
{
ListNode< NODETYPE > *tempPtr = firstPtr; // hold tempPtr to delete

if ( firstPtr == lastPtr )
firstPtr = lastPtr = 0; // no nodes remain after removal
else
firstPtr = firstPtr->nextPtr; // point to previous 2nd node

value = tempPtr->data; // return data being removed
delete tempPtr; // reclaim previous front node
return true; // delete successful
} // end else
} // end function removeFromFront

// delete node from back of list
template< typename NODETYPE >
bool List< NODETYPE >::removeFromBack( NODETYPE &value )
{
if ( isEmpty() ) // List is empty
return false; // delete unsuccessful
else
{
ListNode< NODETYPE > *tempPtr = lastPtr; // hold tempPtr to delete

if ( firstPtr == lastPtr ) // List has one element
firstPtr = lastPtr = 0; // no nodes remain after removal
else
{
ListNode< NODETYPE > *currentPtr = firstPtr;

// locate second-to-last element
while ( currentPtr->nextPtr != lastPtr )
currentPtr = currentPtr->nextPtr; // move to next node

lastPtr = currentPtr; // remove last node
currentPtr->nextPtr = 0; // this is now the last node
} // end else

value = tempPtr->data; // return value from old last node
delete tempPtr; // reclaim former last node
return true; // delete successful
} // end else
} // end function removeFromBack

// is List empty?
template< typename NODETYPE >
bool List< NODETYPE >::isEmpty() const
{
return firstPtr == 0;
} // end function isEmpty

// return pointer to newly allocated node
template< typename NODETYPE >
ListNode< NODETYPE > *List< NODETYPE >::getNewNode(
const NODETYPE &value )
{
return new ListNode< NODETYPE >( value );
} // end function getNewNode

// display contents of List
template< typename NODETYPE >
void List< NODETYPE >::print() const
{
if ( isEmpty() ) // List is empty
{
cout << "The list is empty\n\n";
return;
} // end if

ListNode< NODETYPE > *currentPtr = firstPtr;

cout << "The list is: ";

while ( currentPtr != 0 ) // get element data
{
cout << currentPtr->data << ' ';
currentPtr = currentPtr->nextPtr;
} // end while

cout << "\n\n";
} // end function print

#endif

#ifndef LISTNODE_H
#define LISTNODE_H


template< typename NODETYPE > class List;

template< typename NODETYPE >
class ListNode
{
friend class List< NODETYPE >;

public:
ListNode( const NODETYPE & );
NODETYPE getData() const;
private:
NODETYPE data;
ListNode< NODETYPE > *nextPtr; // next node in list
}; // end class ListNode

// constructor
template< typename NODETYPE >
ListNode< NODETYPE >::ListNode( const NODETYPE &info )
: data( info ), nextPtr( 0 )
{
} // end ListNode constructor

// return copy of data in node
template< typename NODETYPE >
NODETYPE ListNode< NODETYPE >::getData() const
{
return data;
} // end function getData

#endif

#include <iostream>
using std::cin;
using std::cout;
using std::endl;

#include <string>
using std::string;

#include "List.h"

// function to test a List
template< typename T >
void testList( List< T > &listObject, const string &typeName )
{
cout << "Testing a List of " << typeName << " values\n";
instructions(); // display instructions

int choice; // store user choice
T value; // store input value

do // perform user-selected actions
{
cout << "? ";
cin >> choice;

switch ( choice )
{
case 1: // insert at beginning
cout << "Enter " << typeName << ": ";
cin >> value;
listObject.insertAtFront( value );
listObject.print();
break;
case 2: // insert at end
cout << "Enter " << typeName << ": ";
cin >> value;
listObject.insertAtBack( value );
listObject.print();
break;
case 3: // remove from beginning
if ( listObject.removeFromFront( value ) )
cout << value << " removed from list\n";

listObject.print();
break;
case 4: // remove from end
if ( listObject.removeFromBack( value ) )
cout << value << " removed from list\n";

listObject.print();
break;
} // end switch
} while ( choice != 5 ); // end do...while

cout << "End list test\n\n";
} // end function testList


void instructions()
{
cout << "Enter one of the following:\n"
<< " 1 to insert at beginning of list\n"
<< " 2 to insert at end of list\n"
<< " 3 to delete from beginning of list\n"
<< " 4 to delete from end of list\n"
<< " 5 to end list processing\n";
} // end function instructions

int main()
{
// test List of int values
List< int > intList;
testList( intList, "integer" );

// test List of string values
List< string > stringList;
testList( stringList, "string" );

return 0;
} // end main

I want to be able to include my phone number class so that this will accept
phone numbers as input. Here is the phone class

#ifndef PHONENUMBER_H
#define PHONENUMBER_H

#include <iostream>
using std::eek:stream;
using std::istream;

#include <string>
using std::string;

#include <iomanip>
using std::setw;

class PhoneNumber
{
friend ostream &operator<<( ostream &, const PhoneNumber & );
friend istream &operator>>( istream &, PhoneNumber & );
private:
string areaCode; // 3-digit area code
string exchange; // 3-digit exchange
string line; // 4-digit line
}; // end class PhoneNumber

ostream &operator<<( ostream &output, const PhoneNumber &number )
{
output << "(" << number.areaCode << ") "
<< number.exchange << "-" << number.line;
return output; // enables cout << a << b << c;
} // end function operator<<

istream &operator>>( istream &input, PhoneNumber &number )
{
input.ignore(); // skip (
input >> setw( 3 ) >> number.areaCode; // input area code
input.ignore( 2 ); // skip ) and space
input >> setw( 3 ) >> number.exchange; // input exchange
input.ignore(); // skip dash (-)
input >> setw( 4 ) >> number.line; // input line
return input; // enables cin >> a >> b >> c;
} // end function operator>>

#endif
 
A

Alf P. Steinbach

* B. Williams:
I need assistance including a class so that
it will allow input of a phone number that is properly formatted.

Try to be a little more specific. Do you want someone to write the code
for you?
 
B

B. Williams

Alf P. Steinbach said:
* B. Williams:

Try to be a little more specific. Do you want someone to write the code
for you?

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?

I apologize for not being more specific. I know both of these work
independently, but I need help with incoporating the phone number class into
the program. I couldn't figure out any better way to get the program to
accept phone numbers. I tried inputting the phone number as a string, but
the blank space ends the string. I guess I am asking for some assistance on
writing the code, but I just need a kick start. This is the code to test the
phone number class.

#include <iostream>
using std::cout;
using std::cin;
using std::endl;

#include "PhoneNumber.h"

int main()
{
PhoneNumber phone;

cout << "Enter phone number in the form (123) 456-7890:" << endl;

cin >> phone;

cout << "The phone number entered was: ";

cout << phone << endl;
return 0;
} // end main.
 
J

Jim Langston

B. Williams said:
I apologize for not being more specific. I know both of these work
independently, but I need help with incoporating the phone number class
into the program. I couldn't figure out any better way to get the program
to accept phone numbers. I tried inputting the phone number as a string,
but the blank space ends the string. I guess I am asking for some
assistance on writing the code, but I just need a kick start. This is the
code to test the phone number class.

#include <iostream>
using std::cout;
using std::cin;
using std::endl;

#include "PhoneNumber.h"

int main()
{
PhoneNumber phone;

cout << "Enter phone number in the form (123) 456-7890:" << endl;

cin >> phone;

cout << "The phone number entered was: ";

cout << phone << endl;
return 0;
} // end main.

And what happens when you run this code? I see you have
operator<< and operator>> overridden for the class PhoneNumber and without
looking at the code real closely or testing it, it looks about right. So
what's the problem when you try this?
 
B

BobR

B. Williams wrote in message ...
I apologize for not being more specific. I know both of these work
independently, but I need help with incoporating the phone number class into
the program. I couldn't figure out any better way to get the program to
accept phone numbers. I tried inputting the phone number as a string, but
the blank space ends the string. I guess I am asking for some assistance on
writing the code, but I just need a kick start. This is the code to test the
phone number class.

#include <iostream>
using std::cout;
using std::cin;
using std::endl;
#include "PhoneNumber.h"

// suggestion:
istream& operator>>( istream &input, PhoneNumber &number ){
std::string line;
std::getline( input, line );
if( /* check something */ ){ /* do something */ } // like 'line.empty()'

if( '(' == line.at(0) && ')' == line.at(4) ){
number.areaCode = line.substr( 1, 3 ); // input area code
}
else{
number.areaCode = "GIGO";
}
number.exchange = line.substr( 6, 3 ); // input exchange
// etc.

// OR:

if( '(' == input.peek() ){
input.ignore();
}
if( input ){
input >> number.areaCode;
if( ')' == number.areaCode.at(3) ){
number.areaCode.erase(3);
}
}
// etc.

return input; // enables cin >> a >> b >> c;
} // end function operator>>
 
G

Greg Buchholz

B. Williams said:
I have written some code to accept input and place this input at the
beginning or end of a list, but I need assistance including a class so that
it will allow input of a phone number that is properly formatted. I'll post
my code below. Thanks in advance.

#include<iostream>
#include<list>
#include<iterator>
#include<boost/regex.hpp>
#include<cassert>

using namespace std;
class PhoneNumber
{ public:
PhoneNumber(const string a, const string e, const string s):
area_code(a), exchange(e), station(s){};
string area_code, exchange, station;
};

ostream &operator<<(ostream &o, const PhoneNumber &n)
{
return o << "(" << n.area_code << ") "
<< n.exchange << "-" << n.station;
}

// This should probably be something fancier
// http://en.wikipedia.org/wiki/North_American_Numbering_Plan
static const boost::regex
valid_ph("\\s*\\(?(\\d{3})\\)?\\s*[-.]?\\s*" // Area Code
"(\\d{3})\\s*[-.]?\\s*" // Exchange
"(\\d{4})\\s*"); // Station

void tests(void)
{
using namespace boost;
assert( regex_match("(800)555-1212" ,valid_ph));
assert( regex_match("800-555-1212 " ,valid_ph));
assert( regex_match("800.555.1212" ,valid_ph));
assert( regex_match("(800) 555 1212",valid_ph));
assert( regex_match("800 555 1212" ,valid_ph));
assert( regex_match("8005551212" ,valid_ph));
assert(not regex_match("800 555 12129" ,valid_ph));
assert(not regex_match(" 800 555 121" ,valid_ph));
assert(not regex_match("(foo) bar-quux",valid_ph));
}

int main(int argc, char* argv[])
{
string p;
list<PhoneNumber> l;
boost::smatch m;

tests();
cout << "Enter Phone numbers (blank line to stop):\n";
while(true)
{
getline(cin,p);
if(not boost::regex_search(p,m,valid_ph)) break;
l.push_back(PhoneNumber (m[1].str(),m[2].str(),m[3].str()));
}

cout << "Phone numbers:\n";
copy(l.begin(),l.end(),ostream_iterator<PhoneNumber>(cout, "\n"));
return 0;
}
 
B

B. Williams

BobR said:
B. Williams wrote in message ...

// suggestion:
istream& operator>>( istream &input, PhoneNumber &number ){
std::string line;
std::getline( input, line );
if( /* check something */ ){ /* do something */ } // like 'line.empty()'

if( '(' == line.at(0) && ')' == line.at(4) ){
number.areaCode = line.substr( 1, 3 ); // input area code
}
else{
number.areaCode = "GIGO";
}
number.exchange = line.substr( 6, 3 ); // input exchange
// etc.

// OR:

if( '(' == input.peek() ){
input.ignore();
}
if( input ){
input >> number.areaCode;
if( ')' == number.areaCode.at(3) ){
number.areaCode.erase(3);
}
}
// etc.

return input; // enables cin >> a >> b >> c;
} // end function operator>>
Bob,
What I am want to do is to incorporate the phone class into the list class
that I posted in my origional post. Will you assist me with that?
 
B

BobR

B. Williams wrote in message ...
Bob,
What I am want to do is to incorporate the phone class into the list class
that I posted in my origional post. Will you assist me with that?

I'll do what I can.

What do you mean by "incorporate the phone class into the list class"?

class Phone{};
class List{
Phone phoneNum;
};

--- or ---

class List{
Phone phoneNum;
class Phone{};
};

--- or ---

class List{
std::string phoneNum;
std::string areacode;
std::string prefix;
std::string numberpart;
public:
bool GetPhoneNumber(std::string &phone);
};

Your class List is templated. Will all the types it uses have a phone number?
"I can write to my friend 'int', because I have the address, but, I can't
find int's phone number! When I ask 'double' all I get is 1.234567890e+09!"
<G>

Is this what you want to do?:

List<PhoneNumber> phonebook;
 
B

B. Williams

BobR said:
B. Williams wrote in message ...

I'll do what I can.

What do you mean by "incorporate the phone class into the list class"?

class Phone{};
class List{
Phone phoneNum;
};

--- or ---

class List{
Phone phoneNum;
class Phone{};
};

--- or ---

class List{
std::string phoneNum;
std::string areacode;
std::string prefix;
std::string numberpart;
public:
bool GetPhoneNumber(std::string &phone);
};

Your class List is templated. Will all the types it uses have a phone
number?
"I can write to my friend 'int', because I have the address, but, I can't
find int's phone number! When I ask 'double' all I get is
1.234567890e+09!"
<G>

Is this what you want to do?:

List<PhoneNumber> phonebook;
Bob,
I don't really need the template because I just want to create a linked list
of phone numbers. I don't care about int' strings, etc... I probably went
about this the wrong way but I like to break things down because I'm fairly
new. That's why I have seperate code for both the linked list and the
phonenumber. I have gotten them to work seperately, now I just want to
phonenumber class to work so that I can create a linked list.
 
I

IR

B. Williams said:
I probably went about this the wrong way but I like to
break things down because I'm fairly new. That's why I have
seperate code for both the linked list and the phonenumber.

As a side note: even though you're "fairly new", you got the right
approach.

Every class (or template, for instance) must do only one thing, and do
it right. The smaller the pieces, the easier it is to get them right.

Remember:
- Keep it simple
- Small is beautiful

;-)


Cheers,
 
B

BobR

B. Williams wrote in message ...
Bob,
I don't really need the template because I just want to create a linked list
of phone numbers. I don't care about int' strings, etc... I probably went
about this the wrong way but I like to break things down because I'm fairly
new. That's why I have seperate code for both the linked list and the
phonenumber. I have gotten them to work seperately, now I just want to
phonenumber class to work so that I can create a linked list.

Then you will probably want to do as Salt_Peter said in
alt.comp.lang.learn.c-c++:
add the following to PhoneNumber:
a) a def ctor
b) a copy ctor
c) an assignment operator (not used, but required)

.....then test it:

std::vector<PhoneNumber> phonebook;
// std::list<PhoneNumber> phonebook;

.....then try:

List<PhoneNumber> phonebook;


[ I just saw you posted code(or something big) on the other NG. I'll load it
and take a look. ]
 
B

B Williams

BobR said:
B. Williams wrote in message ...
Bob,
I don't really need the template because I just want to create a linked
list
of phone numbers. I don't care about int' strings, etc... I probably went
about this the wrong way but I like to break things down because I'm
fairly
new. That's why I have seperate code for both the linked list and the
phonenumber. I have gotten them to work seperately, now I just want to
phonenumber class to work so that I can create a linked list.

Then you will probably want to do as Salt_Peter said in
alt.comp.lang.learn.c-c++:
add the following to PhoneNumber:
a) a def ctor
b) a copy ctor
c) an assignment operator (not used, but required)

....then test it:

std::vector<PhoneNumber> phonebook;
// std::list<PhoneNumber> phonebook;

....then try:

List<PhoneNumber> phonebook;


[ I just saw you posted code(or something big) on the other NG. I'll load
it
and take a look. ]
Bob,
Did you get a chance to look at the code I posted in the other NG?
 
B

BobR

B Williams wrote in message ...
"BobR" wrote in message ...
[ I just saw you posted code(or something big) on the other NG. I'll load
it and take a look. ]
Bob,
Did you get a chance to look at the code I posted in the other NG?

Yup! Try the change (and test if() ). Report result.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,770
Messages
2,569,583
Members
45,073
Latest member
DarinCeden

Latest Threads

Top