Array getting passed incorrectly to a function in C++ - c++

I'm working a project for class that requires creating a binary search tree of criminal names with up to 8 attributes per criminal.
I set up a string array att[] that will read in the attributes for each criminal, and then be passed to my BSTInsert class function. Through debugging I can see that the array is correct when it's just in the setupTree function. Once it's passed to BSTInsert, instead of having each string it only has one string, and on top of that nothing is copied from the array to the node in the tree.
Can anyone tell me what I'm doing wrong?
Here's my code for setting up the tree:
void setupTree(BST& criminals)
{
ifstream fin("criminals.txt");
string temp;
fin >> temp;
//FINISHED means it has all the criminals
while (temp != "FINISHED")
{
//SUSPECT lets it know to read in a new name and new attributes
if (temp == "SUSPECT")
{
string name;
string att[8];
int count = 0;
fin >> temp;
//if there is a false "suspect" line, quit
if (temp == "FINISHED") return;
name = temp;
fin >> temp;
while (temp != "SUSPECT" && temp != "FINISHED")
{
att[count] = temp;
count++;
fin >> temp;
}
criminals.BSTInsert(name, att, count);
}
}
}
Here's my class function for inserting a node:
bool BST::BSTInsert(treetype name, treetype att[], int count)
{
//gets the memory for the node. If unable, returns fail.
node* newNode = new node;
if (newNode == NULL)
{
return false;
}
newNode->count = 0;
//initializes the node with the given information to place
for (int i = 0; i < count; i++)
{
newNode->att[newNode->count] = att[count];
newNode->count++;
}
newNode->name = name;
newNode->left = newNode->right = NULL;
//if the tree is empty, creates this node as the root
if (root == NULL)
{
root = newNode;
root->parent = NULL;
}
else
{
//the tree is not empty, so it will use the parent to insert the node
node* current = root;
node* parent = NULL;
//finds the insertion spot
while (current != NULL)
{
parent = current;
if (name <= current->name)
{
current = current->left;
}
else
{
current = current->right;
}
}
//inserts the new node onto the correct side of the parent
if (name <= parent->name)
{
parent->left = newNode;
}
else
{
parent->right = newNode;
}
newNode->parent = parent;
}
return true;

treetype att[] doesn't pass an array, it passes a pointer to an array - it decays to treetype att*.
That said, your problem is here:
for (int i = 0; i < count; i++)
{
newNode->att[newNode->count] = att[count];
newNode->count++;
}
This copies the wrong element of att (beyond the end of the array) into every att in newNode. What you meant was
for (int i = 0; i < count; i++)
{
newNode->att[newNode->count] = att[newNode->count];
newNode->count++;
}

Related

C++ Linked List list_copy_front function confusion

I've been struggling with this last function (list_copy_front). The function is for a linked list, it is supposed to return the value of the head pointer for a new list that contains copies of the first n nodes that the source pointer points to. Also if there is less than n nodes in the source then just copy all. Currently, when I run it as is I get a nasty Segmentation Fault SIGSEGV error. The debugger says the error happens at "Node *cursor = source_ptr-> link; Any help would be greatly appreciated, thank you.
Here is some relevant info,
struct Node
{
typedef int Item;
Item data;
Node *link;
};
void list_tail_attach(Node*& head_ptr, const Node::Item& entry);
Node* list_copy_front(Node* source_ptr, size_t n);
void list_tail_attach(Node*& head_ptr, const Node::Item& entry)
{
Node *last = new Node;
last->data = entry;
last->link = NULL;
if(head_ptr == NULL)
{
head_ptr = last;
}
else
{
Node *temp = new Node;
temp = head_ptr;
while(temp->link != NULL)
{
temp = temp->link;
}
temp->link = last;
}
}
Node* list_copy_front(Node* source_ptr, size_t n)
{
Node *new_head_ptr = new Node;
Node *cursor = source_ptr->link;
size_t i = 0;
for(i = 0; i < n; i++)
{
list_tail_attach(new_head_ptr, cursor->data);
cursor = cursor->link;
}
return new_head_ptr;
}
Here's the Main test for the function
int test4()
{
Node* list = NULL; // an empty list
Node* copy = NULL;
copy = list_copy_front(list, 3);
if(copy != NULL)
{
cout << "list_copy_front function doesn't work for copying empty list\n";
return 0;
}
for(int i = 1; i <= 4; i++)
list_tail_attach(list, i);
// list contains 1, 2, 3, 4
copy = list_copy_front(list, 3);
if(list_length(copy) != 3 || copy->data != 1 || copy->link->data != 2 || copy->link->link->data != 3 )
{
cout << "list_copy_front function doesn't work\n";
return 0;
}
copy->link->data = 100;
if(list->link->data == 100)
{
cout << "list_copy_front function doesn't work.\n";
return 0;
}
list_clear(copy);
copy = list_copy_front(list, 6);
if(list_length(copy) != 4)
{
cout << "list_copy_front function doesn't work\n";
return 0;
}
cout << "list_copy_front passes the test\n";
list_clear(list);
for(int i = 1; i <= 3; i++)
list_head_insert(list, i);
// list contains 3, 2, 1
list_copy(list, copy);
if(list_length(copy) != 3 || copy->data != 3 || copy->link->data != 2 || copy->link->link->data != 1 )
{
cout << "list_copy function doesn't work\n";
return 0;
}
cout << "list_copy function passes the test\n";
return 2;
}
Edit 3
So far here's what I'm working with I appreciate the comments so far it's just not quite working out. Which is probably my fault for not explaining better.
void list_tail_attach(Node*& head_ptr, const Node::Item& entry)
{
Node *last = new Node; // Creates new Node
last->data = entry; // Points last to data
last->link = NULL;
if(last == NULL)
{
return;
}
if(head_ptr == NULL)
{
head_ptr = last;
}
else
{
Node *temp = head_ptr;
while(temp->link != NULL)
{
temp = temp->link;
}
temp->link = last;
}
}
Node* list_copy_front(Node* source_ptr, size_t n)
{
if(source_ptr == NULL)
{
return NULL;
}
Node *new_head_ptr = new Node;
Node *cursor = source_ptr;
size_t i = 0;
while(cursor!= NULL && i < n)
{
list_tail_attach(new_head_ptr, cursor->data);
cursor = cursor->link;
i++;
}
return new_head_ptr;
}
I am not allowed to change the way the function takes it's input so, that's why I left Node *last.
I left list_tail_attach(new_head_ptr, cursor->data) because without it I get an invalid conversion error. However when I run the above code I still receive an SIGSEGV error for while(temp->link != NULL) in list_tail_attach and on list_tail_attach(new_head_ptr, cursor->data); in list_copy_front.
Thank you if you are able to comment further
The first test case
Node* list = NULL; // an empty list
Node* copy = NULL;
copy = list_copy_front(list, 3);
gives Node* source_ptr == NULL and expects your function to handle it gracefully.
The function code soon tries to dereference NULL
Node *cursor = source_ptr->link;
The result is a segfault.
First is list_tail_attach, this function I assumed to be attaching an existing Node into a linked list. If the linked list is null then the Node become the head
void list_tail_attach(Node *& head_ptr, Node *& entry)
{
if (entry == NULL) {
return;
}
if (head_ptr == NULL)
{
head_ptr = entry;
}
else
{
Node *temp = head_ptr;
while (temp->link != NULL)
{
temp = temp->link;
}
temp->link = entry;
}
}
I changed the entry into a reference to a pointer to made it easier.
Ok, now move on to the list_copy_front
Node * list_copy_front(Node* source_ptr, size_t n)
{
if (source_ptr == NULL) {
return NULL;
}
Node * new_head_ptr = new Node;
Node * cursor = source_ptr;
size_t i = 0;
while(cursor != NULL && i < n){
list_tail_attach(new_head_ptr, cursor);
cursor = cursor->link;
i++;
}
return new_head_ptr;
}
You have to guard the source_ptr in case it is null.
To attach a new Node
for (int x = 0; x < 5; x++) {
Node * tmp = new Node();
tmp->data = x;
tmp->link = NULL;
list_tail_attach(list, tmp);
}
My professor helped me out with the correct solution. For anyone who views this in the future...
Node* list_copy_front(Node* source_ptr, size_t n)
{
if(source_ptr == NULL) // Takes care of NULL case
{
return NULL;
}
Node *new_head_ptr = NULL; // Creates new head and ensures NULL
Node *cursor = source_ptr; // Sets temp Node = to source
size_t i = 0; // Initializes temp variable
while(cursor!= NULL && i < n) // Loop that continues while n is bigger than i and it is not NULL
{
list_tail_attach(new_head_ptr, cursor->data);
cursor = cursor->link; // Attaches to new list
i++; // Increases count
}
return new_head_ptr;
}
The line that needed to be changed was
Node * new_head_ptr = new Node;
to
Node * new_head_ptr = NULL;

Writing linked list to txt file(Saving process)

struct node
{
string info;
struct node *next;
}*start, *last;
long nodecount=0;
class teditor
{
public:
node* create_node(string);
void insert_pos();
void save();
void display();
void delete_pos();
teditor()
{
start = NULL;
}
};
node *teditor::create_node(string value)
{
struct node *temp, *s;
temp = new(struct node);
if (temp == NULL)
{
cout<<"Memory not allocated "<<endl;
return 0;
}
else
{
temp->info = value;
temp->next = NULL;
return temp;
}
}
void teditor::save()
{
struct node *info;
ofstream listfile;
listfile.open("example.txt",ios::out|ios::app |ios::binary) ;
node *temp;
temp=start;
if(!listfile){
cout<<"\nError";
}
else{
while(temp!=NULL)
{
listfile.write((char*)(temp),sizeof(nodecount));
temp=temp->next;
}
}
listfile.close();
cout<<"\n\n\n\t\tLink list has been saved in file example.txt in current folder.";
cout<<"\n\n\t\tPress a key to continue ... ";getch();
}
void teditor::insert_pos()
{
string value; int counter;
int pos;
cout<<"Enter the value to be inserted: ";
cin>>value;
struct node *temp, *s, *ptr;
temp = create_node(value);
cout<<"Enter the postion at which node to be inserted: ";
cin>>pos;
nodecount++;
int i;
s = start;
while (s != NULL)
{
s = s->next; counter++;
}
if (pos == 1)
{
if (start == NULL)
{
start = temp;
start->next = NULL;
}
else
{
ptr = start;
start = temp;
start->next = ptr;
}
}
else if (pos > 1 )
{
s = start;
for (i = 1; i < pos; i++)
{
ptr = s;
s = s->next;
}
ptr->next = temp;
temp->next = s;
}
else
{
cout<<"Positon out of range"<<endl;
}
}
void teditor::display()
{
/*
Need to merge as a string and show to display just in one line like writing
why cannot save health because of application saving pointers.
*/
node *temp;
temp=start;
cout<<"\n\n\n";
while(temp)
{
cout<<"\t\t\t"<<temp->info;
temp=temp->next;
}
cout<<"\n\n\t\t "<<nodecount<<" records displayed ,Press a key to continue.....";getch();
}
void teditor::delete_pos()
{
int pos, i, counter = 0;
if (start == NULL)
{
cout<<"List is empty"<<endl;
return;
}
cout<<"Enter the position of value to be deleted: ";
cin>>pos;
struct node *s, *ptr;
s = start;
if (pos == 1)
{
start = s->next;
}
else
{
while (s != NULL)
{
s = s->next;
}
if (pos > 0 && pos <= counter)
{
s = start;
for (i = 1;i < pos;i++)
{
ptr = s;
s = s->next;
}
ptr->next = s->next;
}
else
{
cout<<"Position out of range"<<endl;
}
free(s);
}cout<<s<<" Element Deleted"<<endl;nodecount--;
cout<<"There is left "<<nodecount<<" nodes"<<endl;
}
Hi,guys!I have problem while I trying to save my linked list to txt.Everytime I tryin and txt gave me a chinese writing.Teacher also said I need to merged with string or I need to give node to string that application can easily save that string line.Maybe because of I 'm trying to write node *temp.Anybody know how can I solve my problem?After other processes it will be copy,cut,paste and replace with nodes.
Change
listfile.write((char*)(temp),sizeof(nodecount));
to
listfile << temp->info;
You did not want to write the pointer temp into your files, you wanted the info that is inside the node that temp is pointing at. Then why you are writing temp instead of writing the info? YOu could do that "through" your pointer temp, right?
The below will do the above for you:
listfile << temp->info;
ok, you have a serialization problem. You want text in the file. But you are simply dumping memory to the file.
listfile.write((char*)(temp),sizeof(nodecount));
just writes the raw memory of a node.
Ask yourself - what should the text file look like? What do you expect it to look like in an editor. THen you have to write code to do that.
YOu need to do
listfile << temp->info
How do you want to save the next and prior. Maybe it is implicit in the ordering. SO this is all you need. Maybe you need line numbers ans to say next=4, prior=14
Your problem will be solved after doing these steps:
Right click on the project name, go to properties
In general -> project defaults -> character set
Choose not set

Access violation reading location 0xCCCCCCCC error in linklist

Why does the above error occur when calling showNode()?
#include<iostream>
#define NULL 0
using namespace std;
class myNode{
private:
int data;
myNode* link;
myNode* first;
public:
myNode(){
data=0;
link=NULL;
first=NULL;
}
void insertNode(int value, int iposition){
myNode n;
if (iposition==1)
{
first=&n;
cout<<first<<endl;
n.data=value;
n.link=NULL;
}
if (iposition>1)
{
int nodeCounter=1;
myNode* temp=first;
while (temp->link != NULL)
{
nodeCounter++;
}// this while counts the number of inserted nodes.
if (iposition>nodeCounter)//if the position of the new node is greater than number of inserted node,
//it will be inserted at the end.
{
cout<<"Node will be inserted at end."<<endl;
myNode* ieTemp=first;
while (ieTemp->link != NULL)
{
ieTemp=ieTemp->link;
cout<<ieTemp->data<<endl;
}
ieTemp->link=&n;
n.data=value;
n.link=NULL;
cout<<&n<<" ";
}
else
{
myNode* imTemp=first;
while (iposition-1)
{
imTemp=imTemp->link;
iposition--;
}
n.link=imTemp->link;
n.data=value;
imTemp->link=&n;
}
}
}//end insertNode
void showNode(){
myNode* sTemp=first;
while (sTemp != NULL)
{
cout<<sTemp->data<<" ";
sTemp=sTemp->link;
}
}//end showNode
};
int main(){
myNode a;
a.insertNode(10,1);
a.insertNode(20,2);
a.insertNode(25,3);
a.insertNode(30,4);
a.insertNode(40,5);
a.showNode();
system("pause");
}
First you must declare myNode *n = new myNode(); because you use it outside of insertNode function. Second you may want to check if first node exist to avoid error on inserting first node on any other position than 1 (in your case if your first insert will be like inserNode(x, y != 1) will throw an error because you try to access first node (here: while (temp->link != NULL))) but this node don't exist.
This is what I think you want:
void insertNode(int value, int iposition){
myNode *n = new myNode();
myNode *cur = first;
//insert first node or on first position
if (cur == NULL || iposition <= 1) {
n->data = value;
if (cur == NULL) { //first node
n->link = NULL;
}
else { //first position
n->link = first;
}
first = n;
return;
}
for (int i = 1; i < iposition - 1; i++) { //find given position
if (cur->link == NULL) { //if end
n->data = value;
n->link = NULL;
cur->link = n;
return;
}
cur = cur->link;
}
//here we are on position = iposition-1
n->data = value;
n->link = cur->link;
cur->link = n;
}//end insertNode

Priority Queue using array of linked list C++ [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 7 years ago.
Improve this question
So I'm trying to create a priority queue using an array of linked lists in C++. I'm not finished but if I can fix the constructor I think I can do the rest on my own.
I have a data file, first line has the number of items in the file.
The next line thereafter will have a char and then the priority level starting from 0 to 9.
So I'm sorting the alphabet which has 26 letters (the items). Each letter is given a level of priority.
Ex. Q 5 (the letter Q has the priority 5)
When I run this, it says that the program stopped working and then it starts to look for a solution. Like an error for an infinity loop I think.
#include <iostream>
#include <fstream>
using namespace std;
class Queue
{
private:
struct linkedList
{
char data;
linkedList *next;
};
linkedList* PQ[10];
public:
//bool empty;
//bool empty(int priority);
void add(char info, int lvl);
//void remove();
Queue();
};
int main()
{
int size;
char Info;
int Lvl;
Queue Q;
ifstream dataIn;
dataIn.open("charQueueInput.txt");
if (dataIn.fail())
{
cout << "File does not exist." << endl;
exit(1);
}
dataIn >> size;
dataIn.get();
cout << size;
/*for (int i = 0; i < size; i++)
{
dataIn >> Info;
dataIn >> Lvl;
dataIn.get();
Q.add(Info, Lvl);
}*/
system("pause");
return 0;
}
Queue::Queue()
{
for (int i = 0; i < 10; i++)
{
PQ[i] = NULL;
}
for (int i = 0; i < 9; i++)
{
PQ[i]->next = PQ[i + 1];
}
PQ[9]->next = NULL;
}
void Queue::add(char info, int lvl)
{
if (lvl == 0)
{
PQ[0]->data = info;
linkedList *temp = new linkedList;
temp->next = PQ[1];
PQ[0]->next = temp;
}
else if (lvl == 1)
{
PQ[1]->data = info;
linkedList *temp = new linkedList;
temp->next = PQ[2];
PQ[1]->next = temp;
}
else if (lvl == 2)
{
PQ[2]->data = info;
linkedList *temp = new linkedList;
temp->next = PQ[3];
PQ[2]->next = temp;
}
else if (lvl == 3)
{
PQ[3]->data = info;
linkedList *temp = new linkedList;
temp->next = PQ[4];
PQ[3]->next = temp;
}
else if (lvl == 4)
{
PQ[4]->data = info;
linkedList *temp = new linkedList;
temp->next = PQ[5];
PQ[4]->next = temp;
}
else if (lvl == 5)
{
PQ[5]->data = info;
linkedList *temp = new linkedList;
temp->next = PQ[6];
PQ[5]->next = temp;
}
else if (lvl == 6)
{
PQ[6]->data = info;
linkedList *temp = new linkedList;
temp->next = PQ[7];
PQ[6]->next = temp;
}
else if (lvl == 7)
{
PQ[7]->data = info;
linkedList *temp = new linkedList;
temp->next = PQ[8];
PQ[7]->next = temp;
}
else if (lvl == 8)
{
PQ[8]->data = info;
linkedList *temp = new linkedList;
temp->next = PQ[9];
PQ[8]->next = temp;
}
else if (lvl == 9)
{
PQ[9]->data = info;
linkedList *temp = new linkedList;
temp->next = NULL;
PQ[1]->next = temp;
}
}
Here would be an example of the data file:
7
Q 5
W 3
T 0
Y 4
A 9
B 5
U 0
And you would read it as:
0: T -> U
1.
2.
3. W
4. Y
5. Q -> B
6.
7.
8.
9. A
T, U, W, Y, Q, B, A
The problem is that you access PQ before allocating memory.
class Queue
{
private:
struct linkedList
{
char data;
linkedList *next;
};
linkedList* PQ[10]; // Allocates pointer only
The class only allocates pointers to linkenList but not any instances.
Later you have:
// In constructor
Queue::Queue()
{
for (int i = 0; i < 10; i++)
{
PQ[i] = NULL;
}
for (int i = 0; i < 9; i++)
{
PQ[i]->next = PQ[i + 1]; // PQ[i] is NULL so run time error
}
and also later
void Queue::add(char info, int lvl)
{
if (lvl == 0)
{
PQ[0]->data = info; // Access to non-allocated element!
linkedList *temp = new linkedList;
temp->next = PQ[1];
where you access PQ[0]->data. But the element has not been allocated so you get a run time problem.
Instead of
if (lvl == 0)
{
PQ[0]->data = info;
linkedList *temp = new linkedList;
temp->next = PQ[1];
PQ[0]->next = temp;
}
you need something like:
if (lvl == 0)
{
if (PQ[0] == nullptr)
{
PQ[0] = new linkedList; // If head of queue is null, allocate
// new element for head
PQ[0]->next = nullptr;
}
linkedList *temp2 = PQ[0];
while(temp2->next != nullptr) // Search the linked list
{ // to find last element
temp2 = temp2->next;
}
// Now temp2 points to the last element in the list
temp2->next = new linkedList; // Allocate new element and add it
// to the list after temp2
// to get a linked list
temp2 = temp2->next; // Make temp2 point to the new element
temp2->next = nullptr; // Remember to initialize next of new element
temp2->data = info; // Save info
}
And in the constructor:
Queue::Queue()
{
for (int i = 0; i < 10; i++)
{
PQ[i] = nullptr; // Use nullptr instead of NULL
}
// Remove this block
// for (int i = 0; i < 9; i++)
// {
// PQ[i]->next = PQ[i + 1];
// }
// PQ[9]->next = NULL;
}
It is not the pointers in the array which shall be linked.
Each pointer is a pointer to the HEAD of a linked list, i.e. 10 independent linked lists. So don't link them.
And finally - use the array in the add() function! Don't do the big if-statement.
void Queue::add(char info, int lvl) // Tip: Consider making lvl an unsigned int
{
if ((lvl >= 10) || (lvl < 0)) return; // Ignore if lvl is out of range
if (PQ[lvl] == nullptr) // <---- USE lvl to index array
{
PQ[lvl] = new linkedList; // If head of queue is null, allocate
// new element for head
PQ[lvl]->next = nullptr;
}
linkedList *temp2 = PQ[lvl];
while(temp2->next != nullptr) // Search the linked list
{ // to find last element
temp2 = temp2->next;
}
// Now temp2 points to the last element in the list
temp2->next = new linkedList; // Allocate new element and add it
// to the list after temp2
// to get a linked list
temp2 = temp2->next; // Make temp2 point to the new element
temp2->next = nullptr; // Remember to initialize next of new element
temp2->data = info; // Save info
}
BTW - remember to create a destructor which deletes all elements in the 10 linked lists.

Add method not returning any values

I am writing an add method for a Linked List class in C++. The add method is written to handle a variety of situations that may occur based on the input of the method. I have added "cout" statements in order to try and track which loops/if-statements the method is going into, but nothing is being printed from the method. The input for the method are the index of the node and the data that is held in the node.
void linkedList::add(int pos, string item)
{
Node *temp = new Node;
Node *nextTemp = new Node;
if(pos == 0)
{
cout<< "hey";
if(head != NULL)
{
cout<< "hey1";
temp->setData((head->getPosition()+1),
head->getItem(), head->getNextNode());
head->setData(pos, item, temp);
currentNode = head;
size++;
}
else
{
cout<< "hey2";
head->setData(pos, item, temp);
currentNode = head;
size++;
}
}
else if(pos == size)
{
cout<< "hey3";
while(currentNode != NULL)
{
cout<< "hey4";
currentNode = currentNode->nextNode;
}
temp->setData(pos, item, nextTemp);
currentNode->nextNode = temp;
size++;
}
else
{
cout<< "hey5";
for(int i = 0; i<size; i++)
{
cout<< "hey6";
if(i == currentNode->getPosition())
{
cout<< "hey7";
temp->setData(currentNode->getPosition(),
currentNode->getItem(), currentNode->getNextNode());
currentNode->setData(pos, item, temp);
size++;
}
currentNode = currentNode->nextNode;
while(currentNode->getPosition() < (size+1))
{
cout<< "hey8";
currentNode->setPosition(i+1);
currentNode = currentNode->nextNode;
}
}
}
}
Any help would be appreciated. Thank you.