So I am trying to improve this code in c++. What this does it creates two classes: Student and Studentlist. Any suggestions on improving the linked list data structure here will be greatly appreciated.
#include <iostream>
using namespace std;
//declaring a class student
class Student
{
public:
char *RollNo;
Student *next;
//function student that includes arguments roll number and a pointer poniting to next node student
Student(char *rollNo, Student *Next)
{
this->RollNo = rollNo;
this->next = Next;
}
//fucntion to get roll number
char* getRollNo()
{
return RollNo;
}
//function to get the pointer to next node named student
Student *getNext()
{
return next;
}
void setNext(Student *aNode)
{
this->next = aNode;
}
};
//declareing a class StudentList
class StudentList
{
public:
Student *head;
// default constructor
StudentList()
{
head = NULL;
}
void Add(char *aRollNo)
{
Student *newStudent = new Student(aRollNo, NULL);
Student *temp = head;
if (temp != NULL)
{
while (temp->getNext() != NULL)
{
temp = temp->getNext();
}
temp->setNext(newStudent);
}
else
{
head = newStudent;
}
}
void display()
{
Student *temp = head;
if (temp == NULL)
{
cout << "no student data in the Student List" << endl;
return;
}
if (temp->getNext() == NULL)
{
cout << temp->getRollNo();
}
else
{
do
{
cout << temp->getRollNo() << " --next--> ";
temp = temp->getNext();
} while (temp != NULL);
cout << " end --> null" << endl;
}
}
};
main()
{
StudentList list;
list.Add("My Roll Number is 411\n");
list.display();
cout << "--------------------------------\n";
system("pause");
return 0;
}
The declaration of main() is not complete.
main()
See What is the proper declaration of main?
Also literal strings have a type of char const*. So your method call Add("XXX") has no matching point in the class. The closest you have is Add(char*) which does not match the const part.
Personally I would avoid using C-Strings in C++. You should look at using std::string to handle strings of characters it will avoid many problems.
while you are always add at the last i recomended you to replace your Add algorithm code with this
Student* Add(char *aRollNo,Student* last)
{
Student *newStudent = new Student(aRollNo, NULL);
Student *temp = last;
if (head == NULL){
head=newStudent;
temp=head;}
else
temp=temp->setNext(newStudent);
return temp;
}
Related
I created this program that should check the string entered by user in form of characters using doubly linked lists in C++, however I got stuck at the last point in which I should compare the original word with the reversed one to see if the two words are palindrome or not, how to store the content of function display() and reverse() to a string variable so that I can return the value and compare them?
Also, reverse() function doesn't display the reversed word
This is my code:
#include <iostream>
using namespace std;
class Storage {
public:
char lett;
Storage* next;
Storage* prev;
};
void push(char lett1, Storage** head) {
Storage* n = new Storage();
n->lett = lett1;
n->next = NULL;
if (*head == NULL) {
*head = n;
}
else {
n->next = *head;
*head = n;
}
}
void display(Storage* head, int no) {
Storage* s = head;
while (head != NULL) {
int i = 0;
cout << head->lett;
s = head;
head = head->next;
}
}
void reverse(Storage* tail) {
Storage* t = tail;
// Storage* original= tail;
while (t != NULL) {
cout << t->lett;
t = t->prev;
}
}
/*
string checkPalindrome() {
string check;
if ()
check == "Yes";
else
check == "No";
return check;
}
*/
int main() {
Storage* head = NULL; Storage* tail = NULL;;
char lett;
int size;
string result;
cout << ":: Palindrome Program ::\n" << endl;
cout << "Enter total character: ";
cin >> size;
cout << "Enter character: ";
for (int i=0; i < size; i++) {
cin >> lett;
push(lett, &head);
}
cout << "Your word: ";
display(head, size); //compare content of this
cout << "\nReversed word: ";
reverse(tail); // with this
/*
result = checkPalindrome();
cout << "Palindrome: " << result << endl;
*/
return 0;
}
You have some bugs in your code. First of all my tip is that you need to make a class/struct which will hold the head and tail of your list. For example:
class DLList{
public:
NODE *head;
NODE *tail;
};
Also, as you can see you should have a class for your list nodes, and every node should have a pointer to the next node, and to the node before. Don't forget to make the first node previous pointer to point to NULL, and also the last nodes next pointer. Some other things I noticed is that you forgot to deallocate the dynamic/heap memory. Fix that with using 'free' or consider using smart pointers, so you don't have any memory leaks. At the end, try to avoid using namespace std;. It is considered a bad habit, due to bad performance. Hope it helped you. Here is the not optimized code snippet.
#include <iostream>
using namespace std;
class Storage {
public:
char lett;
Storage* next;
Storage* prev;
};
void push(char lett1, Storage** head, Storage **tail) {
Storage* n = new Storage();
n->lett = lett1;
n->next = NULL;
n->prev = NULL;
if (*head == NULL) {
*head = n;
*tail = n;
}
else {
n->next = *head;
(* head)->prev = n;
*head = n;
}
}
std::string display(Storage* head) {
Storage* s = head;
std::string org = "";
while (s != NULL) {
org += s->lett;
s = s->next;
}
return org;
}
std::string reverse(Storage* tail) {
Storage* t = tail;
std::string rev = "";
// Storage* original= tail;
while (t != NULL) {
rev += t->lett;
t = t->prev;
}
return rev;
}
bool checkPalindrome(Storage* head, Storage* tail) {
return display(head) == reverse(tail);
}
int main() {
Storage* head = NULL; Storage* tail = NULL;;
char lett;
int size;
cout << ":: Palindrome Program ::\n" << endl;
cout << "Enter total character: ";
cin >> size;
cout << "Enter character: ";
for (int i = 0; i < size; i++) {
cin >> lett;
push(lett, &head,&tail);
}
cout << "Your word: ";
cout<<display(head)<<endl; //compare content of this
cout << "\nReversed word: ";
cout<<reverse(tail)<<endl; // with this
cout << "\nPalindrome: " << checkPalindrome(head, tail) << endl;
return 0;
}
If you want to build a string with the characters in the linked list, you can use the std::string::operator+= to concatenate the single characters together.
For instance, considering your display function:
void display(Storage* head, int no) {
Storage* s = head;
while (head != NULL) {
int i = 0;
cout << head->lett;
s = head;
head = head->next;
}
}
instead of using cout << head->lett to print a single character, just concatenate that character to the result string using string::operator+=:
// Assume: std::string result
result += head->lett;
You could write a function that takes the linked list of characters as input, and returns a std::string, along these lines:
std::string ToString(const Storage* head) {
std::string result;
// For each node in the linked list
while (...) {
// Append current node's character to the result string
result += currentNode->lett;
}
return result;
}
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);
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
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();
This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 10 years ago.
Hey guys Im working on my first linked list to hold student records (name id gpa addr) but im getting errors i was wondering if you guys can spot the error?
#include <iostream>
#include <string>
using namespace std;
int main()
{
struct Student
{
string name;
string address;
double id;
double gpa;
Student *next;
};
Student *head;
head = NULL;
string Student_name;
double Student_id;
double Student_gpa;
string Student_address;
for (int i = 0; i<20; i++)
{
cout << "What is the student's name?";
getline (cin, Student_name);
cout << "What is " << Student_name << "'s ID Number?";
cin >> Student_id;
cout << "What is " << Student_name << "'s GPA?";
cin >> Student_gpa;
cout << "What is " << Student_name << "'s address?";
getline (cin, Student_address);
}
Student *newStudent;
Student *Student_ptr;
newStudent = new Student;
newStudent->name = Student_name;
newStudent->id = Student_id;
newStudent->gpa = Student_gpa;
newStudent->address = Student_address;
newStudent->next = NULL;
if (!head)
head = newStudent;
else
{
Student_ptr = head;
while (Student_ptr -> next)
Student_ptr = Student_ptr->next;
Student_ptr->next = newStudent;
}
cout << endl;
Student *Display_ptr;
Display_ptr = head;
while (Display_ptr)
{
cout << Display_ptr-> name << endl;
cout << Display_ptr-> id << endl;
cout << Display_ptr-> gpa << endl;
cout << Display_ptr-> address << endl;
Display_ptr = Display_ptr->next;
cout << endl;
}
return 0;
}
Well, I don't know about using a template, unless if you mean using the std list rather than making your own. Having the struct Student within the body of the main function doesn't seem great to me. This is part of the rewriting of the code that would be good to do. and making something like
using namespace std;
namespace MyDataStructs{
class MyLinkedListNode
{
public:
MyLinkedListNode():
name("Empty"),
address("Empty"),
studentID(0.0),
gpa(0.0),
next(NULL)
{
}
~MyLinkedListNode();
void setName(const string& a_name){name = a_name;}
void setAddress(const string& a_address){address = a_address;}
void setID(const int& a_Id){studentID = a_Id;}
void setGPA(const double& a_GPA){gpa = a_GPA;}
void setNextNode(MyLinkedListNode* a_node){next = a_node;}
string getName(){return name;}
string getAddress(){return address;}
int getId(){return studentID;}
double getGPA(){return gpa;}
MyLinkedListNode* getNextNode(){return next;}
private:
string name;
string address;
int studentID;
double gpa;
MyLinkedListNode *next;
};
class MyLinkedList
{
MyLinkedList():
m_size(0)
{
}
~MyLinkedList()
{
clear();
}
void push_back(const MyLinkedListNode& a_node)
{
MyLinkedListNode* newNode = new MyLinkedListNode(a_node);
if(m_end == NULL)
{
m_head = newNode;
m_end = newNode;
}
else
{
m_end->setNextNode(newNode);
m_end = newNode;
}
m_size++;
}
bool deleteNode(const int& a_index)
{
if(a_index >= m_size)
return false;
if(m_head == NULL)
return false;
m_size--;
MyLinkedListNode* currentNode;
if(a_index == 0)
{
currentNode = m_head->getNextNode();
delete m_head;
m_head = currentNode;
return true;
}
curentNode = m_head;
MyLinkedListNode* previousNode;
for(int i = 0; i < a_index; i++)
{
previousNode = currentNode;
currentNode = currentNode->getNextNode();
}
if(currentNode == m_end)
{
m_end = previousNode;
}
previousNode->setNextNode(currentNode->getNextNode());
delete currentNode;
return true;
}
void clear()
{
MyLinkedListNode* currentNode = m_head;
MyLinkedListNode* nextNode;
while(currentNode != NULL)
{
nextNode = currentNode->getNextNode();
delete currentNode;
currentNode = nextNode;
}
}
private:
MyLinkedListNode* m_head;
MyLinkedListNode* m_end;
int m_size;
};
}//MyDataStructs
I dunno, I got bored, what do you guys think.... fun to revisit some basic data structures though.
Well, it would be best to make the actual linked list it's own class, and you could even make the struct it's own class, so you can re-use the classes in the future. The Node could be a template class, but the actual linked list class could stay the same; it'd just have a data member of type "LinkedListNode" which would change depending on what data you need.
The way it's set up now, you'd have to re-write most of this stuff. just to implement a second linked list with a minor change. Making the linked list a class also means you can write actual insert/delete/searc/etc. functions, instead of doing that stuff in main.
struct definitions should not go inside of main(). Technically, since this is C++, you should really be using classes instead of structs.
More importantly, your loop needs to be allocating new data structures each iteration. That is, each time the user enters student information, that should go inside of a new linked list element and then added to the existing list.