Cannot convert parameter 1 from Person to Person *[] - c++

I'm trying to make program that reads from a file and adds to a binary tree, but when I try to compile I get an error:
"Error 1 'treePersons::display' : cannot convert parameter 1 from 'Node *' to 'Person *[]'"
The error appears in the call to display() in main()
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
struct Person{
int social;
int birthday;
string first;
string last;
string state;
double balance;
Person();
Person(int s, int b, string f, string l, string t, double a)
{
social = s;
birthday = b;
first = f;
last = l;
state = t;
balance = a;
}
};
struct Node{
Person data;
Node *left;
Node *right;
Node();
Node(Person x){
data = x;
left = NULL;
right = NULL;
}
};
class treePersons
{
protected:
public:
Node *root;
treePersons(){
root = NULL;
}
int fileName(Person *data[])
{
ifstream fin;
fin.open ("dbfile1.txt");
if (!fin.is_open())
cout << "File not found" << endl;
int i;
for(i = 0; i<100; i++)
while(fin.good())
{
fin >> data[i]->social >> data[i]->birthday >> data[i]->first >> data[i]->last >> data[i]->state >> data[i]->balance;
i++;
}
return i;
}
void add(Person *data[], Node*root)
{
int i = fileName(data);
if(root == NULL)
{
root = new Node();
}
for(int l = 0; l<i; l++)
{
if(data[i]->last == root->data.last)
{
if(data[i]->first != root->data.first)
{
if(data[i]->first < root->data.first)
{
add(data, root->left);
}
else if(data[i]->first > root->data.first)
{
add(data, root->right);
}
else if(data[i]->last == root->data.last && data[i]->first == root ->data.first)
{
cout << "already exists" << endl;
}
else if(data[i]->first < root->data.first)
{
add(data, root->left);
}
else if(data[i]->first > root->data.first)
{
add(data, root->right);
}
}
}
}
}
void printAlphabetically(Node *root)
{
if (root != NULL)
{
printAlphabetically(root->left);
cout << root->data.last << endl;
printAlphabetically(root->right);
}
return;
}
void display(Person *data[],Node *root)
{
add(data,root);
printAlphabetically(root);
};
};
struct State{
string state;
Person data;
State* left;
State * right;
State();
State(Person x)
{
data = x;
left = NULL;
right = NULL;
}
};
class treeState{
protected:
State *root;
public:
treeState()
{
root = NULL;
}
};
void main(){
treePersons T;
T.display(T.root->data,T.root);
}

It's very simple to see what's wrong with your code. You have the following:
treePersons T;
T.display(T.root->data, T.root);
Let's have a look at what a treePersons is:
class treePersons
{
Node *root;
...
};
It contains a single member: a Node. A Node is:
struct Node
{
Person data;
Node *left;
Node *right;
...
};
Your treePersons::display() function has the following signature:
void display(Person *data[], Node *root)
And you are passing a t.root->data (a Person) and t.root (a Node*)
The problem is you are attempting to pass a Person as a Person*[] which just isn't going to happen. There's no way to make that Person into a Person[], and you probably meant to make display take a Person* pointer, which will allow you pass a single Person or a container of Person: void display(Person* data, Node* root);
Of course, doing so will lead you down a big trail of problems as #R Sahu pointed out in the comments (most of your functions take a Person*[]. The solution here is to rethink what you are doing, and as #R Sahu suggests start much smaller and build up your program from there.
Consider also using std::vector when you need containers, and std::unique_ptr or std::shared_ptr where you require pointers (otherwise just use objects!). Also read (really read) the compiler output. It's telling you what the problem is, you just need to read.

Related

Difficulty printing data in my binary tree in print method

I'm trying to add data to a binary tree, however when I run a method that prints the data of the binarytree in order, nothing prints, and the program exits when it should be printing. I've tested it to see if data is actually being added by having the name and weight values of the rootNode print themselves inside the add method everytime its called, but I cannot get the same results inside of the inOrder method. I believe my issue has something to do with the node being passed.
#include <iostream>
using namespace std;
struct node {
int weight;
string name;
node *left, *right;
};
struct node* newNode(int dataw, string datan)
{
struct node* node = (struct node*)malloc(sizeof(struct node));
node->weight = dataw;
node->name = datan;
node->left = NULL;
node->right = NULL;
return (node);
}
void add(node *rootNode, int dataw, string datan)
{
int lowest_weight;
if (rootNode == NULL )
{
rootNode = newNode(dataw,datan);
lowest_weight = dataw;
}
else
{
if (datan < rootNode->name)
{
if (rootNode->left == NULL)
{
rootNode->left = newNode(dataw,datan);
}
else
{
add(rootNode->left,dataw,datan);
}
}
else
{
if (rootNode->right == NULL)
{
rootNode->right = newNode(dataw,datan);
}
else
{
add(rootNode->right, dataw, datan);
}
}
}
}
void inOrder(node *next)
{
if (next!=NULL)
{
inOrder(next->left);
cout << next->name << " " << next->weight << endl;
inOrder(next->right);
}
}
int main()
{
node *rootNode = NULL;
int height {}, leaves {}, weight {};
string name;
do
{
cout << "Enter name: ";
cin >> name;
if (name == "-1")
break;
cout << "Enter weight: ";
cin >> weight;
add(rootNode, weight, name);
} while (name!="-1");
inOrder(rootNode);
return 0;
}
Resolved it, had to assign the rootNode declaration to a new node method call so the data is not always NULL
node *rootNode = newNode(weight,name);

Singly Linked List using Arrays: It's crashing on run-time

Whats wrong with this code?
I am writing this code to implement singly linked list using arrays but its not working. Im using code::blocks and its crashing on run time. Please help.
I must have missed out on something when it was taught in the class. xD
#include<iostream>
#include<stdio.h>
using namespace std;
class Node
{
int data;
Node *next;
public:
Node(int n)
{
data=n;
next=NULL;
}
friend class List;
};
class List
{
Node *listptr;
public:
void create();
void display();
};
void List::create()
{
Node *temp;
int n, num;
cout << "Enter number of nodes:" << endl;
cin >> n;
cout << "/nEnter the data" << endl;
for(int i=0; i<n; i++)
{
cin >> num;
Node *new_node=new Node(num);
if(listptr==NULL)
listptr=temp=new_node;
else
{
temp->next=new_node;
temp=temp->next;
}
}
}
void List::display()
{
Node *temp=listptr;
while(temp!=NULL)
{
cout << temp->data << "->";
temp=temp->next;
}
}
main()
{
List l1;
l1.create();
l1.display();
}
listptr not initialized, you can initialize in constructor.
List() {
listptr = 0;
}
Class List should be
class List
{
Node *listptr;
public:
List() {
listptr = 0;
}
void create();
void display();
};
Try following piece of code -
First Creating Node
class ListElement
{
int data;
ListElement* next;
public:
void set_element(int item) { data = item; }
int get_value() { return data; }
friend class List;
};
Another class for further operation
class List
{
ListElement *Start, *Tail, *New;
public:
List() { Start = Tail = New = NULL; } // initialise all pointer value to NULL
void add_element(int element) {
// Create a new Node
New = new ListElement;
New->set_element(element);
New->next = NULL;
// adding value or linkig each node to each other
(Start == NULL) ? Start = New : Tail->next = New;
Tail = New;
}
// print the whole linked list
void print()
{
ListElement* Current = Start;
while (Current != NULL)
{
cout << Current->get_value() << endl;
Current = Current->next;
}
}
};
Main Function
int main()
{
List L;
int num_of_element, element;
cin >> num_of_element;
for (int i(0); i < num_of_element; i++) {
cin >> element;
L.add_element(element);
}
L.print();
}
Hope it'll work.

How to create and execute a copy constructor for a linked list?

I have tried looking at videos and older posts but it is still very difficult to understand the concept of copy constructors. Would someone clear it up for me? My class did not really cover this part 100% my professor focused mainly on constructors and destructors.
Main CPP
#include <iostream>
#include "Header.h"
using namespace std;
int main()
{
node access;
access.getData();
access.outData();
system("pause");
return 0;
}
Header File
#include <iostream>
using namespace std;
class node
{
public:
node(); // Had to create my own default constructor because of my copy constructor.
node(const node &n); // This is a copy constructor.
~node();
void getData();
void outData();
private:
int num;
int lCount = 0; // Counts the number of nodes, increments after each user input.
int *ptr; // Where the linked list will be copied into
node *next;
node *first;
node *temp;
node *point;
};
node::node()
{
num = 0;
}
node::node(const node &n)
{
temp = first;
ptr = new node;
for (int i = 0; i < lCount; i++)
{
ptr[i] = temp->num;
temp = temp->next;
}
}
node::~node() // Deletes the linked list.
{
while (first != NULL)
{
node *delP = first; // Creates a pointer delP pointing to the first node.
first = first->next; // "Removes first node from the list and declares new first.
delete delP; // Deletes the node that was just removed.
}
cout << "List deleted" << endl;
}
void node::getData() // Simple function that creates a linked list with user input.
{
int input = 0;
point = new node;
first = point;
temp = point;
while (input != -1)
{
cout << "Enter any integer, -1 to end." << endl;
cin >> input;
if (input == -1)
{
point->next = NULL;
break;
}
else
{
lCount++;
point->num = input;
temp = new node;
point->next = temp;
point = temp;
}
}
}
void node::outData()
{
temp = first;
cout << "Original" << endl;
while (temp->next != NULL)
{
cout << temp->num << endl;
temp = temp->next;
}
cout << "Copied" << endl;
for (int i = 0; i < lCount; i++)
{
cout << ptr[i] << endl;
}
}
This little snippet is what I am having trouble with in particular:
node::node(const node &n)
{
temp = first;
ptr = new node;
for (int i = 0; i < lCount; i++)
{
ptr[i] = temp->num;
temp = temp->next;
}
}
I figured it out! I was tinkering with a much simpler copy constructor. I was having trouble understanding syntax, everything was very complicated and it was overwhelming to look at.
#include <iostream>
using namespace std;
class node
{
public:
node(int x); // Normal Construtor
node(const node &cpy); // Copy Constructor
void change(); // Changes data value
void outData();
private:
int data;
};
int main()
{
node var1(123);
var1.outData();
node var2 = var1;
var2.outData();
var2.change();
var1.outData();
var2.outData();
system("pause");
return 0;
}
node::node(int x)
{
data = x;
}
node::node(const node &cpy)
{
data = cpy.data;
}
void node::outData()
{
cout << data << endl;
}
void node::change()
{
int userIn;
cin >> userIn;
data = userIn;
}
Output:
123
123
(input: 4444)
Output:
123
4444

Adding new Node to a linked list with two classes

When trying to add a new Node to the liked list it gives me a Segmentation fault. Can someone tell me what is wrong in the implementation of the addBook() function. I am not sure if it's the implementation of the function that is wrong, or the way that I've declared the classes.
class Reservation {
public:
int getID();
string getResevNum();
void setId(int x);
void setReseNum(string y);
private:
int ID;
string reservedNumber;
};
class ReservationCollection {
public:
ReservationCollection();
~ReservationCollection();
int getUserId(int &id);
string getUserBook(string &bookCall);
void findReservation();
void display();
void addBook(int id, string book);
void RemoveBook();
void ShutDown();
private:
struct Node {
Reservation *data;
Node *next;
};
Node *head;
};
ReservationCollection::ReservationCollection() {
Node *head = new Node;
head->next = NULL;
}
ReservationCollection::~ReservationCollection() {
}
void ReservationCollection::addBook(int id, string book){
Node *tmp = new Node;
tmp->data->setId(id);
tmp->data->setReseNum(book);
tmp->next = head->next;
head->next = tmp;
cout <<"Good\n";
}
int Reservation::getID(){
return ID;
}
string Reservation::getResevNum(){
return reservedNumber;
}
void Reservation::setId(int x){
ID = x;
}
void Reservation::setReseNum(string y){
reservedNumber = y;
}
int ReservationCollection::getUserId(int &id){
cout << "Enter Id number " << endl;
cin >> id;
return id;
}
string ReservationCollection::getUserBook(string &bookCall){
cout << "Enter book reservatin " << endl;
cin >> bookCall;
return bookCall;
}
int main()
{
int ID;
string BookNum;
char cmd;
do {
cout << "Enter command: ";
cin >> cmd;
ReservationCollection list;
if (cmd == 'A' || cmd == 'a'){
list.getUserId(ID);
list.getUserBook(BookNum);
list.addBook(ID, BookNum);
}
else if (cmd == 'S' || cmd == 's'){
cout << " list";
}
} while (cmd != 'Q' || cmd == 'q');
}
Wish I could just comment this:
All instances of the line Node *tmp = new Node; should read Node *tmp = new Node();
Don't use pointers if you don't have to. In this example Node has to be a pointer, because the list may have zero nodes, or 1000 nodes, so we need pointers to dynamically allocate memory on demand.
But (Reservation)data does not have to be a pointer. Each node always has one Reservation member.
If you do declare it as pointer then you must allocate it, and free it when it is no longer needed.
head should be initialized to NULL, because the single linked-list has no nodes when it is initialized. The first node inserted becomes the head.
#include <iostream>
#include <string>
using namespace std;
class Reservation
{
private:
int ID;
string reservedNumber;
public:
int getID() { return ID; }
string getResevNum() { return reservedNumber; }
void setId(int x) { ID = x; }
void setReseNum(string y) { reservedNumber = y; }
};
class ReservationCollection
{
public:
struct Node
{
Reservation data;
Node *next;
};
ReservationCollection();
~ReservationCollection();
void addBook(int id, string book);
Node* getHead() { return head; }
private:
Node *head;
};
ReservationCollection::ReservationCollection()
{
head = NULL;
}
ReservationCollection::~ReservationCollection()
{
Node *p = head;
while (p)
{
Node *next = p->next;
cout << "delete: " << p->data.getID() << ", " << p->data.getResevNum() << endl;
delete p;
p = next;
}
}
void ReservationCollection::addBook(int id, string book)
{
Node *node = new Node;
node->data.setId(id);
node->data.setReseNum(book);
//this element is the last element
node->next = NULL;
if (!head)
{
//first element inserted
head = node;
head->next = NULL;
}
else
{
//find the previous node in the list
Node *prev = head;
while (prev->next)
prev = prev->next;
//this node is after previous node
prev->next = node;
}
cout << "Good\n";
}
int main()
{
ReservationCollection list;
list.addBook(0, "Book0");
list.addBook(1, "Book1");
list.addBook(2, "Book2");
list.addBook(3, "Book3");
ReservationCollection::Node *p = list.getHead();
while (p)
{
ReservationCollection::Node *next = p->next;
cout << p->data.getID() << ", " << p->data.getResevNum() << endl;
p = next;
}
}
Creating a Node wont create the structure that Reservation *data; tries to point to, and so you try to access non initialized memory.
You need to initialize data:
tmp->data = new Reservation();

Linked List Operations C++

I've got a linked list data base using templates which compiles fine and lets me print out a list of all states and lets me search for a person and print all that persons data (since these methods work, I left them out below to save space).
Below I have a print_people_in_state method, what I need to be able to do is to (given a user input of state) print out the info on all the people from that particular state. However right now when I run it, nothing happens. How can I fix this?
If you want to run the code yourself here is a link to the file that I named data.txt (http://rabbit.eng.miami.edu/class/een118/labs/152/dbfile1.txt)
#include <iostream>
#include <string>
#include <string.h>
#include <fstream>
using namespace std;
struct person
{
int dob,ss_number;
string fname, lname,state;
person()
{ }
person(int a, int b, string c, string d, string e)
{dob=a; ss_number=b; fname=c; lname=d; state=e;}
};
struct state
{
string sname;
person*P;
state()
{}
state(string a)
{sname=a;}
};
template<typename T>struct Link
{
T*data;
Link*extradata;
Link*next;
Link()
{}
Link(T*a,Link<T>*C=NULL)
{
data=a;
next=C;
}
};
template<typename T>
struct List
{int length;
Link<T>*Head,*tail;
List(Link<T>*h=NULL, Link<T>*t=NULL)
{
Head=h;
tail=t;
length=0;
}
void add(T*object)
{
{ if (Head == NULL && tail == NULL)
{ Link<T> * newlink = new Link<T>(object);
Head = newlink;
tail = Head; }
else
{ Link<T> * newlink = new Link<T>(object);
tail->next = newlink;
tail=newlink;} }
}
void print_people_in_state(string search)
{
Link<state>*temp=Head;
if(temp!==NULL)
{
if(temp->data->P->state==search)
{
cout<<temp->data->P->fname<<endl;
}
// temp=temp->next;
}}
};
List<person>*person_from_file(string file)//reads file
{
List<person>* newlist=new List<person>();
// Link<T> * head=NULL;
// Link<T> * temp=NULL;
ifstream fin;
fin.open("data.txt");
if (fin.fail())
cout<<"file not found\n";
if (!fin.fail())
{
while(true)
{
int a,b;
string c,d,e;
fin>>a>>b>>c>>d>>e;
if (fin.fail())break;
person * p=new person(a,b,c,d,e);
newlist->add(p);
}
}
else
cout<<"Can't open file";
fin.close();
return newlist;
}
List<state>*state_from_file(string file)//reads file
{
List<state>* newlist=new List<state>();
// Link<T> * head=NULL;
// Link<T> * temp=NULL;
ifstream fin;
fin.open("data.txt");
if (fin.fail())
cout<<"file not found\n";
if (!fin.fail())
{
while(true)
{
int a,b;
string c,d,e;
fin>>a>>b>>c>>d>>e;
if (fin.fail())break;
state * s=new state(e);
newlist->add(s);
}
}
else
cout<<"Can't open file";
fin.close();
return newlist;
}
int main()
{List<person>*A = person_from_file("data.txt");
List<state> *B= state_from_file("data.txt");
B->print_people_in_state("TX");
return 0;
}
You can simplify Link and List. You can read the file once and fill both lists at the same time. In fact, you don't really need a separate list for states, its usage is confusing.
template<typename T>class Link
{
public:
Link(T *data) { Data = data; Next = NULL; }
T *Data;
Link<T> *Next;
};
template<typename T>struct List
{
int Count;
Link<T> *Head, *Tail;
List() { Head = NULL; Tail = NULL; Count = 0; }
Link<T>* AddData(T *data)
{
Link<T> *node = new Link<T>(data);
Count++;
if (Head == NULL)
{
Head = Tail = node;
}
else
{
Tail->Next = node;
Tail = node;
}
return node;
}
};
int main()
{
List<person> *list = new List<person>;
ifstream fin("data.txt");
while (fin)
{
int a, b;
string c, d, e;
fin >> a >> b >> c >> d >> e;
list->AddData(new person(a, b, c, d, e));
}
Link<person> *node = list->Head;
while (node)
{
if (node->Data->state == "TX")
cout << node->Data->fname << endl;
node = node->Next;
}
return 0;
}