I'm trying to create a linked list that has 2 data types and a function that inserts nodes. But in order to insert nodes, I have to create at least 1 empty node first.
linked list struct
struct receipt{
string name;
double price;
receipt* link;
};
function that inserts a node at the end of the list
void insert(receipt** head_name_ref, string new_name, double new_price)
{
receipt* new_name_node = new receipt();
receipt *last = *head_name_ref;
new_name_node->name = new_name;
new_name_node->price = new_price;
new_name_node->link = NULL;
if (*head_name_ref == NULL)
{
*head_name_ref = new_name_node;
return;
}
while (last->link != NULL)
{
last = last->link;
}
last->link = new_name_node;
return;
}
function that print the list
void printList(receipt* n){
while(n!=NULL){
cout<<"Name: "<<n->name<<'\t'<<" ";
cout<<"Price: "<<n->price<<'\t'<<" ";
cout<<endl;
n=n->link;
}
}
main function
int main(){
receipt* head = NULL;
head = new receipt;
insert(&head, "item", 23);
printList(head);
return 0;
}
here is a picture of the output https://i.stack.imgur.com/6Ss02.png
CodePudding user response:
Consider that in a more complex program you would have much more than simply a main function. When creating a data structure you have to store a pointer or reference to an object in some way that other functions can receive or access the pointer. For something this simple a global variable or instance of a struct containing the attributes of the list would suffice. Simply initialize the head to 0 and create the functions needed to manage that global object. Upon the first instantiation of the node, simply assign the head to that pointer.
You've already created a struct that represents a node. Now create another one that represents the list which contains nodes. Within that struct you'd want attributes such as a head that pointers to the first node object or null if it is empty. You can give it a default constructor.
Since this looks like an assignment I'm only giving you some hints and not a complete example, purposefully.
struct SinglyLinkList {
receipt* head;
SinglyLinkList() : head(0) {}
~SinglyLinkList() { // code to iterate and destroy all node objects }
// now define copy constructor and assignment operators if you want or delete those
// possibly some methods to add, remove, print nodes
void print();
add(receipt* r); // could overload to insert at a position
remove(size_t n); // remove nth receipt or overload to remove by some other factor
void removeAll();
receipt
};
// somewhere above the main function you could just instantiate a global list
// Within the main function you may call methods that operate on the
// list and call its methods, or define other global functions if you
// prefer that the list be defined only with the attributes
SinglyLinkList list; // default constructed with head = 0 or head = nullptr if you prefer
CodePudding user response:
First note that when struct receipt
is constructed, price
and link
will be uninitialized (std::string name
will be default constructed to an empty string, but double
and pointers do not have such a default initialization). This problem will manifest with this line in main
:
head = new receipt;
(the problem does not manifest when you create new_name_node
because you manually initialized it after the allocation).
Therefore you should better handle struct receipt
initialization. The minimum would be something like this:
struct receipt {
std::string name;
double price{ 0 };
receipt* link{ nullptr };
};
You can consider to add a custom constructor.
Now to answer you question:
The question title is how to avoid printing the first node.
To do this you just have to skip one node before starting the loop.
Add the following at the beginning of printList
:
if (n != nullptr)
{
n = n->link;
}
However, "solving" the problem like this is not a good idea.
Having a "dummy" first node in a linked list is not the ideal design.
I suggest you redesign your code to avoid it. You can search the web for typical linked list implementations to get some ideas. Then the issue of printing (while skipping a node) will not arise at all.
On a side note: better to avoid using namespace std
- see here Why is "using namespace std;" considered bad practice?.