I am having trouble understanding how to use pointers when they are in "private".
mostly I don't know how to get and set values for pointers
I want to create a head and tail node that have no character value. then create new nodes that lie in between head and tail and add new nodes on to the end of the list (before tail).
the code runs, but it doesn't do anything when I use the print function.
sorry if my formatting is wrong and if the code is too long.
here is the code for my class:
#include <iostream>
using namespace std;
class node
{
public:
node(void)// constructor for empty nodes
{
left_link = NULL;
right_link = NULL;
}
node(char x) // constructor for nodes with given value
: anything(x)
{ }
char get_char() // return character
{
return anything;
}
void setLeftLink(node *left)
{
left_link = left;
}
void setRightLink(node *right)
{
right_link = right;
}
node *getlefttLink()
{
return left_link;
}
node *getRightLink()
{
return right_link;
}
private:
node *left_link;
char anything;
node *right_link;
};
here are my functions:
void append(node *&head, node *&tail);
void print(node *head);
void append(node *&head, node *&tail)
{
char c;
cout << "Please enter a single character: ";
cin >> c;
node *current = new node(c);
cout << current->get_char() << endl;
if(head == NULL && tail == NULL)
{
head->setRightLink(current);
tail->setLeftLink(current);
current->setLeftLink(head);
current->setRightLink(tail);
}
else
{
tail->setRightLink(current);
current->setLeftLink(tail);
tail = current;
tail->setRightLink(NULL);
}
}
// print function
void print(node *head)
{
node* temp;
temp = head;
while(temp->getRightLink()!=NULL){
cout<<temp->get_char()<<endl;
temp = temp->getRightLink();
}
}
here is my main:
int main()
{
char choice;
node *head = new node;
node *tail = new node;
cout << "Please choose one menu option at a time:\n"
<< "1 = Append\n"
<< "2 = Print list\n"
<< "3 = Exit\n\n";
do
{
cout << "Menu option(1-3): ";
cin >> choice;
switch (choice)
{
case '1': append(head, tail); // add to the end of list.
break;
case '2': print(head); // print list
break;
case '3': cout << "end program\n\n";
break;
default: cout << "try again\n";
break;
}
}while(choice != '3');
return 0;
}
First off, head and tail should be initialized to NULL since there is nothing in the beginning.
Then change your code to append, particularly the first if statement. change your code to
Since you are starting a new list, both head and tail are the same node that you just inserted.
Finally change the condition of your while loop in your print function. Something as simple as this should work.
You want to print the current node, even it doesn't have a right neighbor.
private
members, pointers or otherwise, are data that the object either does not want messed by anyone else with or wants to know if someone messed with them.Setter and getter methods allow access to the
private
member, but in a controlled manner. For example if you have a private integer that under no circumstances can ever be greater than ten, you can have code in the setter that checks for a caller trying to force the value out of range and reject the request.Now the program can't have any nasty surprises with X == 11 causing an out-of-range access or whatever.
This is self defense for objects. They maintain control over who sets their data to what and can maintain consistency. Say you have a more complex case where you cannot sample an A/D at over 10000 samples per second with the FIR filter enabled without starving the CPU and locking up the system. Whoops. If the only way to set the Filter state or the sampling rate is through setters in the A/D manager object, the object can test and reject and prevent disaster (and possibly leave a nice fat log message pointing at the bad actor).
Think very hard before implementing a getter that returns a non-constant reference or a pointer. Once the caller has either, they can do whatever they want with the returned data.
The rule of thumb is to default to paranoia: Grant no access to any data without a good reason, and then prefer controlled access through setters and getters.
Onto the specifics of your problem.
Getters and setters for a link node is often a sucker bet. The node most likely cannot determine for itself if a linkage is valid. Only the list manager can. This is a case where the object itself is too ignorant to know what is safe, so you have to open up the internals to another object that knows more.
friend
is useful here, though it is often better to make the node's linkspublic
and never allow the list manager to give a node to a client.Odds are good the client should know absolutely nothing about how the list works anyway. Read up on coupling.
So the node should be utterly stupid. This means you need to have a
ListManager
class to (duh) manage the list and protect thenode
s from badly behaved actors.ListManager
contains yourhead
,tail
,root
or whatever along withappend
andremove
,print
and other list management methods. Under no circumstances do any of these functions reveal anode
to the caller, though they can return a handle or an iterator that can be used to reference a node without giving the caller a tool to damage the list. Iterators are a topic worthy of their own question and probably have quite a few already.A bit of code to explain the above is in order. Please note I have marked, but not corrected, the logic problems I found. There may be more as this compiles (with C++11 enabled) but I haven't run it.
Note how
node
is built right intoListManager
and isprivate
. Now onlyListManager
has access tonode
and it has complete access.ListManager
also needs a destructor to handledelete
ing all of thenew
ed nodes that were appended. It also needs a copy constructor and an assignment operator to make it Rule of Three compliant. "What is The Rule of Three?" you ask? It is very very important. Read the link to save yourself much future debugging. Failure to obey the Rule of Three results in a disproportionate number of C++ questions on Stack Overflow, and there is no point in inflating this statistic further.Usage: