Linked list issue with insert - c++

The problem appears with the insert function that I wrote.
3 conditions must work, I tested b/w 1 and 2, b/w 2 and 3 and as last element, they worked.
EDIT;
It was my own problem. I did not realize I put MAXINPUT = 3 (instead of 4). I do appreciate all the efforts to help me becoming a better programmer, using more advance and more concise features of C++.
Basically, the problem has been solved.
Efficiency is not my concern here (not yet). Please guide me through this debug process.
Thank you very much.
#include<iostream>
#include<string>
using namespace std;
struct List // we create a structure called List
{
string name;
string tele;
List *nextAddr;
};
void populate(List *);
void display(List *);
void insert(List *);
int main()
{
const int MAXINPUT = 3;
char ans;
List * data, * current, * point; // create two pointers
data = new List;
current = data;
for (int i = 0; i < (MAXINPUT - 1); i++)
{
populate(current);
current->nextAddr = new List;
current = current->nextAddr;
}
// last record we want to do it sepeartely
populate(current);
current->nextAddr = NULL;
cout << "The current list consists of the following data records: " << endl;
display(data);
// now ask whether user wants to insert new record or not
cout << "Do you want to add a new record (Y/N)?";
cin >> ans;
if (ans == 'Y' || ans == 'y')
{
/*
To insert b/w first and second, use point as parameter
between second and third uses point->nextAddr
between third and fourth uses point->nextAddr->nextAddr
and insert as last element, uses current instead
*/
point = data;
insert(());
display(data);
}
return 0;
}
void populate(List *data)
{
cout << "Enter a name: ";
cin >> data->name;
cout << "Enter a phone number: ";
cin >> data->tele;
return;
}
void display(List *content)
{
while (content != NULL)
{
cout << content->name << " " << content->tele;
content = content->nextAddr;
cout << endl; // we skip to next line
}
return;
}
void insert(List *last)
{
List * temp = last->nextAddr; //save the next address to temp
last->nextAddr = new List; // now modify the address pointed to new allocation
last = last->nextAddr;
populate(last);
last->nextAddr = temp; // now link all three together, eg 1-NEW-2
return;
}

Your code works fine on my machine (once the insert(()) statement is "filled in" properly as explained in the code comment). The insertion works in all positions.
Something else, though: I initially had a look at your insert function. I thought I'd give you a hint on how to make it a little shorter and easier to understand what's going on:
void insert(List *last)
{
// create a new item and populate it:
List* new_item = new List;
populate(new_item);
// insert it between 'last' and the item succeeding 'last':
new_item->nextAddr = last->nextAddr;
last->nextAddr = new_item;
}
This would be preferable because it first creates a new, separate item, prepare it for insertion, and only then, when this has worked successfully, will the function "mess" with the linked list. That is, the linked list is not affected except in the very last statement, making your function "safer". Contrast this with your version of insert, where you mix code for constructing the new item with the actual insertion. If something goes wrong inside this function, chances are far higher that the linked list is messed up, too.
(What's still missing btw. is a initial check whether the passed argument last is actually valid, ie. not a null pointer.)
P.S.: Of course you could just use a standard C++ std::list container instead of building your own linked list, but seeing that you tagged your question beginner, I assume you want to learn how it actually works.

step one should be to make the list into an object instead of just keeping a bunch of pointers around in main(). you want an object called List that knows about it's own first (and maybe last) elements. it should also have methods like List.append() and List.insert().
your current code is nigh unreadable.

Use a std::list, unless this is homework, in which case it needs tagging as such.

In my experience, I have learned to start small and test, then build up. I'll guide you through these steps.
BTW, a linked list is a container of nodes. So we'll start with the node class first.
Minimally, a node must have a pointer to another node:
#include <iostream>
#include <cstdlib> // for EXIT_SUCCESS
#include <string>
using std::cout;
using std::endl;
using std::cerr;
using std::cin;
using std::string;
struct Node
{
// Add a default constructor to set pointer to null.
Node()
: p_next(NULL)
{ ; }
Node * p_next;
};
// And the testing framework
int main(void)
{
Node * p_list_start(NULL);
// Allocate first node.
p_list_start = new Node;
// Test the allocation.
// ALWAYS test dynamic allocation for success.
if (!p_list_start)
{
cerr << "Error allocating memory for first node." << endl;
return EXIT_FAILURE;
}
// Validate the constructor
ASSERT(p_list_start->p_next == 0);
// Announce to user that test is successful.
cout << "Test successful." << endl;
// Delete the allocated object.
delete p_list_start;
// Pause if necessary.
cin.ignore(100000, '\n'); // Ignore input chars until limit of 100,000 or '\n'
return EXIT_SUCCESS;
}
Compile, and run this simple test. Fix errors until it runs correctly.
Next, modify the tester to link two nodes:
int main(void)
{
Node * p_list_start(NULL);
Node * p_node(NULL); // <-- This is a new statement for the 2nd node.
//...
// Validate the constructor
ASSERT(p_list_start->p_next == 0);
// Allocate a second node.
p_node = new Node;
if (!p_node)
{
cerr << "Error allocating memory for 2nd node." << endl;
// Remember to delete the previously allocated objects here.
delete p_list start;
return EXIT_FAILURE;
}
// Link the first node to the second.
p_list_start->Link_To(p_node);
// Test the link
ASSERT(p_list_start.p_next == &p_node);
//...
// Delete the allocated object(s)
delete p_list_start;
delete p_node;
//...
}
Compile with the modifications.
It failed to compile, undefined method: Node::Link_To
Not to worry, this is expected. Show us the compiler is working. :-)
Add the Link_To method to the Node structure:
struct Node
{
// ...
void Link_To(const Node& n)
{
p_next = &n;
return;
}
//...
};
Compile and run. Test should pass.
At this point the linking process has been validated. Onto adding content to the node.
Since the Node object has been tested, we don't want to touch it. So let's inherit from it to create a node with content:
struct Name_Node
: public Node // Inherit from the tested object.
{
std::string name;
std::string phone;
};
If you haven't learned inheritance yet, you can append to the existing node:
struct Node
{
//...
std::string name;
std::string phone;
}
At this point you can add functions for setting and displaying content. Add the testing statements. Run and validate.
The next step would be to create two content nodes and link them together. As you build up, keep the testing code. Also, if stuff works you may want to put the functionality into separate functions.
For more information on this process, check out Test Driven Development.

Related

pointer array in member variable (C++)

I'm currently struggling with a problem with pointer array member variable, Addresses.
The codes below are example codes for my situation. Assume that Addresses always contains at least one element.
// MyClass.h
MyClass{
private:
int size;
Node* root;
Node** Addresses; // Node is custom struct
void saveAddresses(Node* v);
void UpdateAddresses();
public:
MyFunction1() {UpdateAddresses(); cout << Addresses[0] << endl;} // cout for debug
MyFunction2() {UpdateAddresses(); cout << Addresses[0] << endl;} // cout for debug
};
// MyClass.cpp
void MyClass::saveAddresses(Node* v){
static int i = 0;
if (v == nullptr)
return;
saveAddresses(v -> left);
saveAddresses(v -> right);
Addresses[i++] = v;
cout << "SAVED: " << v->key << " in " << v << endl;
}
void MyClass::UpdateAddresses(){
Addresses = new Node*[size];
saveAddresses(root);
}
// in main.cpp
MyClass m = MyClass();
m.MyFunction1(); // It works!
m.MyFunction2(); // SEG FAULT!!
I confirmed (by using cout) that the saveAddresses() function normally saves node pointers into Addresses. Also, MyFunction1() in the main function works well. However, if MyFunction2() is called after function call MyFunction1(), a segmentation fault occurs(Addresses[] becomes nullptr here). I really don't know what the problem is. Please help me!
Note: std::vector is prohibited.
Your UpdateAddresses function will create a new array everytime it is called. If you call it twice, it will always call saveAddresses with a single Node, but the counter will always increased. I see two problems with that:
I don't know what set size to, but it could be that on the second call of saveAddresses you try to set the value for index 1, but it the array is too small (just guessing here).
The first time you call saveAddresses, it will save the node to index 0, which is also the one you read from. The second time you will save the node to index 1, but you will try to read from index 0, which is not initialized.

Binary Search Tree using the most frequent node to print out certain statements

I have a binary search tree that I want to use to be able to give a certain output for the most common node but i'm having a hard time doing that. I already have code that prints out how many times the node is entered into the tree and which one is the most frequent but I don't know how to write the if statement that would compare the values and be able to output certain things if one was greater than the other. I have been working on this for hours and just can't get the right output please help.
So if i have more a's i want that to have a certain output or if i have more b's that should have a different output etc.
For starters, change the node definition to look more like the one below. This definition initializes all the struct's fields to their zero values. For me, this change prevented an access violation at the line if (p->data == q->data), probably because the next pointer was not initialized to nullptr.
struct node {
char data{};
int count{};
node *left{};
node *right{};
int height{};
node *next{};
};
Similarly, my compiler warns about an uninitialized variable res. So that too should be initialized like char res{};.
This seems to work for the maxChar function. The second overload calls the first overload, which calls itself recursively. They don't have to have the same names.
char maxChar(node *node, int max, char res) {
if (node != nullptr) {
res = maxChar(node->left, max, res);
if (node->count > max) {
max = node->count;
res = node->data;
}
res = maxChar(node->right, max, res);
}
return res;
}
char maxChar(node *node) {
int max{};
char res{};
return maxChar(node, max, res);
}
Then if needed, you could do something like this:
char maxCh = maxChar(root);
switch (maxCh) {
case 'A': cout << "Your recommendation is A." << endl;
break;
case 'B': cout << "Your recommendation is B." << endl;
break;
}

c++ String copying error to struct pointer data fields

I'm currently writing a program that uses a binary search tree to store names and phone numbers (phonebook basically). I've done this before with an AVL tree, and it works fine. I have decided to switch my methods up for this implementation and not just copy/paste the logic and format of the last one. In doing so I've run into a weird error and I have no idea why it's happening. At first I thought my problem was in the way I returned a struct pointer, but it is actually in my string copying.
I've written a very basic program that only shows the copy function that returns the structure, which are then used to recursively fill the BST with the data (which is read in from a file).
Here is the shortened example:
#include <iostream>
#include <string>
using namespace std;
struct Node
{
std::string first;
std::string last;
std::string phone;
};
Node* copyfunc(std::string first, std::string last, std::string phone)
{
Node* temp = NULL;
temp->first = first;
temp->last = last;
temp->phone = phone;
return temp;
}
int main()
{
std::string first, last, phone;
first = "Jenny";
last = "Something";
phone = "8675309";
Node* newStruct = NULL;
newStruct = copyfunc(first, last, phone);
cout << newStruct->first << endl;
cout << newStruct->last << endl;
cout << newStruct->phone << endl;
cout << "Never to be seen again..." << endl;
return 0;
}
Now, I've tried using VS2013 debugger to find out where the issue is, and it happens on the first copy: "temp->first = first;". It breaks with an access violation warning and then opens the xstrings (header?) and points to the section: (line 2245)
if (this->_Myres < _Newsize)
_Copy(_Newsize, this->_Mysize); // reallocate to grow"
I'm just guessing, but from what I can gather it seems to me that it's failing in creating the new string to fit the old strings length.
The program (both the example and real one) will compile, they just hang at the point of reaching the copy function.
All input is appreciated, thanks!
EDIT: The reason I use pointers for my structures is due to the way the algorithms I'm using are written. The functions that actually link the nodes together in the BST accept a Node* type rather than a Node object.
Ex: recursiveInsert(Node* root, Node* newNodeToAdd);
You are not initializing temp to anything useful before you attempt to use it.
Node* temp = NULL;
temp->first = first; // oops! temp is NULL!
It would be easier to drop the pointers entirely:
Node copyfunc(std::string first, std::string last, std::string phone)
{
Node temp = {first, last, phone};
return temp;
}
You should also consider passing the parameters by const reference instead of value. Or just drop the function completely and initialize the Node where needed:
Node newStruct = {first, last, phone};
cout << newStruct.first << endl;

Can't add items to linked list in a loop in C++

I have started learning C++ and as a first project, I am trying to make a linked list application. I have not had any real problems with the linked list concept so far as I have previously worked with it in a different language.
So far, I already have working functions to add items to the list and to print it. In the main() class, I can add items one by one, but when I try to add multiple items via a for or while loop.
I have separate functions to create an item and to add it to (the beginning of) the list:
ListItem createItem(int value)
{
ListItem x;
std::cout << &x;
x.value = value;
return x;
}
void addBeg(ListItem* &start, ListItem &item)
{
// Adding to an empty list
if (start == nullptr)
{
item.prev = &item;
item.next = &item;
}
else
{
std::cout << std::endl <<"X" &item;
item.prev = (*start).prev;
(*item.prev).next = &item;
item.next = start;
(*start).prev = &item;
}
start = &item;
}
My main() function looks like this:
int main(void)
{
using namespace std;
// List is empty at the beginning.
ListItem* start = nullptr;
printList(start);
// This doesn't work:
int i = 0;
while (i < 10)
{
ListItem a = createItem(i);
addBeg(start, a);
i++;
}
// This works:
addBeg(start, createItem(12));
addBeg(start, createItem(13));
addBeg(start, createItem(-42));
addBeg(start, createItem(1));
addBeg(start, createItem(-85));
printList(start);
return 0;
}
I cannot seem to graps why it doesn't work. One reason I have thought of is that ListItem a does not reset in each iteration, but that does not make any sense whatsoever to me. Any help or idea is appreciated.
The createItem function returns by value, and when passing that along directly to another function (like you do with e.g. addBeg(start, createItem(12)) the returned value is temporary. Taking and saving an address of a temporary value will lead to undefined behavior.
The simple solution is to have createItem create a node dynamically of the heap using new, and return a pointer.

singly linked chain printing c++

I am trying to pick my chain in the format {1,2,3,4,etc}. You can find the header file below which will have the layout of the nodes. I am just confused on how I should go about cycling through my list to print out Item.
Any guidance would be greatly appreciated!
set.h
using namespace std;
#include <iostream>
class Set
{
private:
struct Node
{
int Item; // User data item
Node * Succ; // Link to the node's successor
};
unsigned Num; // Current count of items in the set
Node * Head; // Link to the head of the chain
public:
// Return information about the set
//
bool is_empty() const { return Num == 0; }
unsigned size() const { return Num; }
// Initialize the set to empty
//
Set();
// Insert a specified item into the set, if possible
//
bool insert( int );
// Display the set
//
void display( ostream& ) const;
};
Here are two recommendations: 1) Sort the list first, then print all nodes; 2) Create another list (indices) to the data and sort those links (don't need data in those nodes).
Sorting List First
An often used technique is to order the nodes in the order you want them printed. This should involve changing the link fields.
Next, start at the head node and print each node in the list (or the data of each node in the list).
Using an Index list
Create another linked list without the data fields. The links in this list point to the data fields in the original list. Order the new list in the order you want the nodes printed.
This technique preserves the order of creation of the first list and allows different ordering schemes.
Changing Links
Since you're writing your own Linked List, the changing of the links is left as an exercise as I'm not getting paid to write your code. There are many examples on SO as well as the web for sorting and traversing linked lists.
You just want to do something like this:
void Set::display(ostream &out) const {
for(int i=0; i<Num; i++) {
out << Pool[i] << " ";
}
out << endl;
}
An ostream behaves as cout would.
It's hard to get your question. If you want to print the array to screen you should consider writing a display() like:
#include <iostream>
#include <iterator>
void Set::display() const {
ostream_iterator<int> out_it (cout," ");
copy(Pool,Pool+Num,out_it);
cout << endl;
}
or if you want to write to a ostream& (as it is pointed out in the answer by #alestanis)
#include <iostream>
#include <iterator>
void Set::display(ostream &out) const {
ostream_iterator<int> out_it (out," ");
copy(Pool,Pool+Num,out_it);
out << endl;
}
Without testing, I'd do something like this. (Assumes the last node has Succ set to NULL, as I would recommend it does.)
void LoopList(struct Node *head)
{
for (struct Node *p = head; p != null; p = p->Succ)
{
// Do whatever with this node
Print(p);
}
}
I think I was over thinking it. Anyway here is what I ended up doing. Now I just need to add some formatting for the commas and im all set.
Node * Temp;
Temp = new (nothrow) Node;
Temp = Head;
out << "{";
while(Temp->Succ)
{
out << Temp->Item;
Temp = Temp->Succ;
}
out << '}' << endl;
Suppose your list is cyclical, you can use this:
struct Node *n = begin;
if (n != NULL) {
//do something on it
...
for (n = begin->Succ; n != begin; n = n->Succ) {
}
}
or
struct Node *n = begin;
if (n != NULL) {
do {
//do something
...
n = n->Succ;
} while (n != begin)
}