How to use Doubly Linked List with Dynamic Array? - c++

My homework is about making a schedule with doubly-linked list. We can create a dynamic array for keeping days. But every day has to have a doubly-linked list which contains time slots. Vectors and arrays are forbidden from use, instead of linked lists. I have difficulty about functions.
This is my header file:
#ifndef _SCHEDULE_H
#define _SCHEDULE_H
#include <string>
using namespace std;
struct Node
{
string courseName;
int time;
Node *next; //forward direction
Node *prev; //backward direction
Node::Node() {}
Node::Node(const string &cName,const int&time, Node * pRight, Node * pLeft)
: courseName(cName),time(time),next(pRight), prev(pLeft)
{}
};
class Schedule
{
public:
Schedule(); //Constructor
//adding new course depend on time
void addCourse(string courseName, char day, int time,Node *Days[6]);
// delete course depend on time
void deleteCourse(char day, int time,Node *Days[6]);
// display a particular course's time
void displayCourse(string courseName,Node *Days);
//prints schedule
void print(Node *Days);
private:
Node *head; //Head node, start of a linked list based on Day
Node *tail; //Tail node, end of a linked list based on Day
};
#endif
Here's my implementation file:
#include <iostream>
#include "Schedule.h"
using namespace std;
Schedule::Schedule()
{
head=new Node(" ",0,NULL,NULL);
tail = NULL;
}
void Schedule::addCourse(string courseName, char day, int time,Node *Days[6])
{
int i;
if (day=='M')
{i=0;}
else if(day=='T')
{i=1;}
else if(day=='W')
{i=2;}
else if(day=='R')
{i=3;}
else if(day=='F')
{i=4;}
else if(day=='S')
{i=5;}
Node*cur=Days[i]->next=head;
if(Days[i]->next==NULL)
{
Days[i]=new Node;
Days[i]->next->courseName=courseName;
Days[i]->time=time;
Days[i]->next=NULL;
Days[i]->prev=NULL;
cout<<"The course "<<courseName<<" is added on "<<day<<" "<<time<<endl;
}
else if(time<Days[i]->next->time && time!=Days[i]->next->time)
{
Node*newcourse=new Node;
//Days[i]=new Node;
Days[i]->next->courseName=courseName;
Days[i]->next->time=time;
Days[i]->next=head;
Days[i]->prev=NULL;
Days[i]->next=newcourse;
cout<<"The course "<<courseName<<" is added on "<<day<<" "<<time<<endl;
}
else if(time>Days[i]->next->time)
{
while(Days[i]->next!=NULL && Days[i]->next->time<time && Days[i]->next->time!=time)
{
Days[i]->next=Days[i]->next->next;
}
if(Days[i]->next->time==time)
{
cout<<"Time conflict"<<endl;
}
else
{
Node*newcourse=new Node;
Days[i]->next->courseName=courseName;
Days[i]->next->time=time;
Days[i]->next=Days[i]->next->next;
Days[i]->prev=Days[i]->next;
Days[i]->next->next=newcourse;
cout<<"The course "<<courseName<<" is added on "<<day<<" "<<time<<endl;
}
}
}
void Schedule::deleteCourse(char day, int time,Node *Days[6])
{
int d;
if (day=='M')
{d=1;}
else if(day=='T')
{d=1;}
else if(day=='W')
{d=2;}
else if(day=='R')
{d=3;}
else if(day=='F')
{d=4;}
else if(day=='S')
{d=5;}
Node*cur=Days[d]->next=head;
if(Days[d]->next==NULL)
{
cout<<"Schedule is empty for this day"<<endl;
}
else
{
}
}
void Schedule::displayCourse(string courseName,Node *Days)
{
}
void Schedule::print(Node *Days)
{
}
Here is my main:
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include "Schedule.h"
using namespace std;
Node *Days = new Node[6];
void CoutSelection()
{
cout<<endl<<endl;
cout<<"Welcome to Schedule Maker. Please select an option:"<<endl;
cout<<" 1) Load the course schedule from a known file"<<endl;
cout<<" 2) Add a time slot manually"<<endl;
cout<<" 3) Remove a time slot manually"<<endl;
cout<<" 4) Print a particular course's time slot"<<endl;
cout<<" 5) Print all schedule"<<endl;
cout<<" 6) Exit" <<endl;
cout<<endl;
cout<<" Please enter your selection as 1-2-3-4-5-6"<<endl;
cout<<endl;
}
int main()
{
int selection;
CoutSelection();
cin>>selection;
Schedule list;
while (selection!=6)
{
if (selection==1)
{ string fileName;
cout<<"Please enter the filename that you want to load"<<endl;
cin>>fileName;
ifstream input;
input.open(fileName);//open file
if(!input.is_open())//control if correctly open
{
cout<<"Couldn't open input file: "<<fileName<<endl;
}
else
{
string cname,line; //course name and day identifier
char day;
int time; //time
while(!input.eof())
{getline(input, line);
stringstream ss(line);
int num;
ss>>cname>>day>>num;
list.addCourse(cname,day,time,*Days[6]);
}
}
}
else if (selection==2)
{
int timeAdded;
string cnameAdded;
char dayAdded;
cout<<"Please enter course name,day and it's time that you want to add like : coursename dayidentifier time"<<endl;
cout<<"Enter the day as M/T/W/R/F/S. (MONDAY:M, TUESDAY:T, WEDNESDAY:W, THURSDAY:R, FRIDAY:F, SATURDAY:S)"<<endl;
cin>>cnameAdded>>dayAdded>>timeAdded;
list.addCourse(cnameAdded,dayAdded,timeAdded,*Days[6]);
}
else if(selection==3)
{
char dayDeleted;
int timeDeleted;
cout<<"Please enter the day and time that you want to delete like : dayidentifider time"<<endl;
cout<<"Enter the day as M/T/W/R/F/S. (MONDAY:M, TUESDAY:T, WEDNESDAY:W, THURSDAY:R, FRIDAY:F, SATURDAY:S)"<<endl;
cin>>dayDeleted>>timeDeleted;
list.deleteCourse(dayDeleted,timeDeleted,*Days[6]);
}
else if(selection==4)
{
string coursedisplayed;
cout<<"Please enter course name that you want to display"<<endl;
cin>>coursedisplayed;
list.displayCourse(coursedisplayed,*Days);
}
else if(selection==5)
{
list.print(*Days);
}
CoutSelection();
cin>>selection;
}
return 0;
}
What is wrong with my code? If I handle one of the functions, I'm sure I can do other functions.
Errors :
error C2664: 'Schedule::addCourse' : cannot convert parameter 4 from 'Node' to 'Node *[]'
IntelliSense: no operator "*" matches these operands
operand types are: * Node

Aside from all the problems presented by #WhozCraig, which I think you should tackle for your own good. Your compiler is talking to you, and it is telling you that your addCourse method receives a pointer to a Node Array.
But in your main you called it with the following list.addCourse(cname,day,time,*Days[6]);. By doing *Days[6] you are telling the method you want to send what is pointed by Days[6]. Thus your compiler is receiving a Node object and not a pointer to a node array.
Try it with the following list.addCourse(cname,day,time,Days);, this will send the pointer to the first element in days.
One pointer to keep in mind, which you'll teacher will likely notice:
You have memory leaks, which is another VERY important subject.

Related

Compiler is throwing error in main that this is not declare before

#include<iostream>
#include<string>
using namespace std;
class customerNode{
public:
int c_id;
int quantity;
string c_name;
string type;
customerNode* next_node;
};
class Queue{
public:
customerNode* front=NULL;
customerNode* rear=NULL;
int getc_id();
string getc_name();
int getquantity();
int setc_id(int c_id);
string setc_name(string c_name);
int setquantity(int quantity);
void display();
void enqueue(int c_id,int quantity,string c_name);
void dequeue();
int nor_queue,exp_queue;
};
int Queue::getc_id(){
int c_id;
cout<<"enter customer id:"<<endl;
cin>>c_id;
return c_id;
}
int Queue::getquantity(){
int quantity;
cout<<"enter quantity customer purchased:"<<endl;
cin>>quantity;
return quantity;
}
string Queue::getc_name(){
string c_name;
cout<<"enter customer name:"<<endl;
cin>>c_name;
return c_name;
}
int Queue::setc_id(int c_id){
return c_id;
}
int Queue::setquantity(int quantity){
return quantity;
}
string Queue::setc_name(string c_name){
return c_name;
}
void Queue:: enqueue(int c_id,int quantity,string c_name){
int exp_queue,nor_queue;
cout<<"enter customer information"<<endl;
customerNode* new_node=new customerNode;
new_node->c_id=c_id;
new_node->c_name=c_name;
new_node->quantity=quantity;
new_node->next_node=NULL;
if(front==NULL){
rear=front;
rear=new_node;
rear->next_node=NULL;
}
else{
while(rear->next_node!=NULL)
rear=rear->next_node;}
rear->next_node=new_node;
rear=new_node;
if(new_node->quantity<=5)
{
new_node->type="express";
exp_queue++;
cout<<"customer entered in express queue"<<endl;
cout<<"total customer in express queue="<<exp_queue<<endl;
}
else{
new_node->type="normal";
nor_queue++;
cout<<"customer entered in normal queue"<<endl;
cout<<"total customer in normal queue="<<nor_queue<<endl;
}
}
void Queue::display(){
customerNode* ptr=front;
cout<<"normal queue customer information"<<endl;
while(ptr!=NULL)
{
if(ptr->type=="normal"){
cout<<"custumer name:"<<setc_name(ptr->c_name)<<endl;
cout<<"custumer id:"<<setc_id(ptr->c_id)<<endl;
cout<<"item puchased by custumer :"<<setquantity(ptr->quantity)<<endl;
nor_queue--;
cout<<"total customer in normal queue:"<<nor_queue<<endl;
}
ptr=ptr->next_node;
}
cout<<"express queue customer information"<<endl;
while(ptr!=NULL)
{
if(ptr->type=="normal"){
cout<<"custumer name:"<<setc_name(ptr->c_name)<<endl;
cout<<"custumer id:"<<setc_id(ptr->c_id)<<endl;
cout<<"item puchased by custumer :"<<setquantity(ptr->quantity)<<endl;
nor_queue--;
cout<<"total customer in normal queue:"<<exp_queue<<endl;
}
}
}
main(){
Queue q;
char i;
do{
q.enqueue(c_id,quantity,c_name );
cout<<"do you want to enter another customer?input y or Y for yes and n or N for no:";
cin>>i;
}
while(i=='y'||i=='Y');
q.display();
return(0);
};`
in mian fuction i m getting error c_id,quantity,c_name is not declare before,when i use int c_id,int quantity,string c_name than it shows expected primary expression befor int and strinng..i dont know which expression is missing or how to resolve the error,
please help me to solve this i hve to submit assing as soon as possible.
A much simpler example with similar error is:
#include <iostream>
struct foo {
int x = 0;
int y = 0;
void assign(int a, int b){
x = a;
y = b;
}
};
int main()
{
foo f;
f.assign(x,y);
}
The error is:
<source>: In function 'int main()':
<source>:14:14: error: 'x' was not declared in this scope
14 | f.assign(x,y);
| ^
<source>:14:16: error: 'y' was not declared in this scope
14 | f.assign(x,y);
| ^
x and y are declared in the scope of the class. Instances of foo have members of that name. To access those members you would write f.x or f.y.
c_id,quantity, and c_name are not declared in your main. I am not eniterly sure what you want to do and it is too much code to adress all its issues. Though, if you want to declare variables of that name in main then you need to do that:
int main(){ // main must return int
Queue q;
char i;
int c_id = 42;
int quantity = 0;
string c_name{"some fancy name"};
q.enqueue(c_id,quantity,c_name );
// ...
}
It is a little surprising that you write code with advanced stuff like pointers, classes and what not, but don't know about scope. Try to search for "scope" and read about it.
There are more issues in your code. For example int Queue::setquantity(int quantity){ return quantity;} does not set anything. Though, as I wrote before, this is just way too much code to adress all of them. I can only advise you to start with less code and only write more when you know the code you have already does compile and passes your tests. And thats not just an advise for a beginner, but anybody is making mistakes and you rather want to fix one problem then many at the same time.

Using C++ how do I access data from a .txt file as part of a linked list when I have both integers and character arrays?

My problem is I have numbers of file type int as well as a char array of length 50 in a .txt file. I have a linked list (queue structured) program that is essentially an event calendar that has an index for searching a specific entry, the day of the week, a date, and a message (information about the event). Without reading from the file I can create events, delete events, modify events, display all the events or display a single event. What I need to add: 1. The ability to save all of the events when the program is terminated. 2. Then the next time it is opened I need to be able to read thee info from the .txt file and create a new event for each event in the .txt file. My text file entries.txt is shown right above the code. Each line is as follows: 1. Index, 2. Day of the week (Sunday=1), 3. Day, 4. Month, 5. Year, 6. Message. Below it shows each event on one line but in my .txt file each number/char is a new line.
1
4
22
4
2015
Baseball_game_at_7
2
3
13
3
2015
This_event_is_for_nothing
3
5
17
6
2015
Birthday
#include <iostream>
#include <fstream>
#include <string>
#include <ctime>
#include <cmath>
using namespace std;
class Event{
protected:
int index;
enum DAY{Sunday=1, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday};
int date[3];
char msg[50];
public:
Event *next;
Event *prev;
Event(){
next=NULL;
prev=NULL;
}
int a;
int day, day1;
virtual void getindex(int b){
index=b;
}
virtual int getindex2(){
a=index;
return a;
}
virtual void getindex3(int c){
index=c;
}
virtual void getday2(int d){
day=d;
}
virtual void getdate2(int e, int f, int g){
date[0]=e;
date[1]=f;
date[2]=g;
}
virtual void getmessage2(char h[50]){
msg=h;
}
virtual void getdate(){
cout<<"\nOptions:\n1. Sunday\n2. Monday\n3. Tuesday\n4. Wednesday\n5. Thursday\n6. Friday\n7. Saturday\nWhich day would you like to select (enter the day): ";
cin>>day;
cout<<"Please enter the date you would like to use (In the form of dd mm yyyy): ";
cin>>date[0];
cin>>date[1];
cin>>date[2];
}
virtual void getcurrentdate(){
time_t now=time(0);
tm *local=localtime(&now);
time_t y=1900+local->tm_year;
time_t m=1+local->tm_mon;
time_t d=local->tm_mday;
time_t day1=local->tm_wday;
day=day1+1;
date[0]=d;
date[1]=m;
date[2]=y;
}
virtual void getmessage(){
cout<<"Please enter your message (Use _ for any spaces): ";
cin>>msg;
}
virtual void display(){
cout<<"\nThe index is: "<<index<<endl;
switch(day){
case Sunday:
cout<<"The day of the week is: Sunday"<<endl;
break;
case Monday:
cout<<"The day of the week is: Monday"<<endl;
break;
case Tuesday:
cout<<"The day of the week is: Tuesday"<<endl;
break;
case Wednesday:
cout<<"The day of the week is: Wednesday"<<endl;
break;
case Thursday:
cout<<"The day of the week is: Thursday"<<endl;
break;
case Friday:
cout<<"The day of the week is: Friday"<<endl;
break;
case Saturday:
cout<<"The day of the week is: Saturday"<<endl;
break;
}
cout<<"The date is: "<<date[0]<<"/"<<date[1]<<"/"<<date[2]<<endl;
cout<<"The message is: "<<msg<<endl;
}
};
class Queue{
Event *Front, *Rear;
public:
Queue(){
Front=NULL;
Rear=NULL;
}
int index;
int input4;
void newevent(int x){
Event *temp;
temp=new Event;
if(Front==NULL){
Front=temp;
Rear=Front;
temp->prev=NULL;
}else{
Rear->next=temp;
temp->next=NULL;
temp->prev=Rear;
Rear=temp;
}
index=x;
temp->getindex(index);
cout<<"\nOptions:\n1. Enter a date manually\n2. Use the current system date and time\nWhat would you like to do: ";
cin>>input4;
switch(input4){
case 1: // Get date manually
temp->getdate();
break;
case 2: // Get current date
temp->getcurrentdate();
break;
}
temp->getmessage();
temp->display();
temp=NULL;
}
int p;
Event *temp2;
void deleteevent(){
Event *temp=Front;
Front=temp->next;
delete temp;
}
int c,d, input1, input3;
void modifyevent(int z){
d=z;
Event *temp=Front;
while(temp!=NULL){
for(c=1;c<d;c++){
temp=temp->next;
}
input1=0;
while(input1!=3){
cout<<"\nOptions:\n1. Change the date\n2. Change the message\n3. exit\nWhat would you like to update: ";
cin>>input1;
switch(input1){
case 1: // Change date
cout<<"Options:\n1. Enter a date manually\n2. Use the current system date and time\nWhat would you like to do: ";
cin>>input3;
switch(input3){
case 1: // Get date manually
temp->getdate();
break;
case 2: // Get current date
temp->getcurrentdate();
break;
}
break;
case 2: // Change message
temp->getmessage();
break;
case 3: // Exit
break;
default:
cout<<"You entered an invalid number!";
}
}
temp=NULL;
}
}
int e,f;
void display(int z){
f=z;
Event *temp=Front;
while(temp!=NULL){
for(e=1;e<f;e++){
temp=temp->next;
}
temp->display();
temp->next;
temp=NULL;
}
}
void displayall(){
Event *temp=Front;
while(temp!=NULL){
temp->display();
cout<<"\n";
temp=temp->next;
}
}
int end;
int x;
int y;
int a;
int b;
int g[3];
char h[50];
void readfromfile(){ // This was my attempt at the problem
ifstream fin;
fin.open("entries.txt");
Event *temp;
x=1;
y=1;
end=1;
while(fin>>y){
end++;
}
for(x;x<end;x++) { // till end-of-file
a=fin>>x;
x++;
b=fin>>x;
x++;
g[0]=fin>>x;
x++;
g[1]=fin>>x;
x++;
g[2]=fin>>x;
x++;
h=fin.getline(x);
temp=new Event;
if(Front==NULL){
Front=temp;
Rear=Front;
temp->prev=NULL;
}else{
Rear->next=temp;
temp->next=NULL;
temp->prev=Rear;
Rear=temp;
}
temp->getindex3(a);
temp->getday2(b);
temp->getdate2(g[0],g[1],g[2]);
temp->getmessage2(h);
temp=NULL;
}
fin.close();
}
void writetofile(){ //I understand this is blank, I havn't made it this far
}
};
int main(){
ofstream myfile;
myfile.open("entries.txt", ios::app);
cout<<"\nWELCOME TO YOUR EVENT PLANNER\n";
Queue a;
a.readfromfile();
int inp=0;
int i=0;
int num=4;
int type;
int counter=0;
int displayevent, modifyevent;
while(inp!=6){
cout<<"\nOptions:\n1. Create new event\n2. Delete the oldest event\n3. Modify an event\n4. Display all events\n5. Display a specific event\n6. Exit event planner\nWhat do you want to do: ";
cin>>inp;
switch(inp){
case 1: // New event
a.newevent(num);
num++;
counter++;
break;
case 2: // Delete event
a.deleteevent();
counter--;
break;
case 3: // Modify event
cout<<"\nEnter the index of the event you would like to modify: ";
cin>>modifyevent;
a.modifyevent(modifyevent);
break;
case 4: // Display all events
a.displayall();
break;
case 5: //Display single event
cout<<"\nEnter the index of the event you would like to display: ";
cin>>displayevent;
a.display(displayevent);
break;
case 6: // Exit event planner
break;
default:
cout<<"You entered an invalid number";
break;
}
}
cout<<"The current number of events is "<<counter<<endl;
myfile.close();
return 0;
}
Queue.readfromfile() was my attempt at reading the file and inputting each event in the file as a new event. I need to know how to get each line of the text file saved as something different so it can be sent to a function in the class above.
Queue.writetofile() was intentionally left blank because I haven't even made it that far yet. I should be able to figure it out pretty easily. I wanted to finish reading files first.
Since you didn't search StackOverflow, I will give you a synopsis of how to input your stuff.
Let the Object read its data members.
There several methods on how to do this, but we'll stick with overloading the extraction operator.
class Event
{
private:
int index;
int day_of_week;
unsigned int day;
unsigned int month;
unsigned int year;
std::string message; // Don't use char array here.
public:
friend std::istream& operator>>(std::istream& inp, Event& e);
};
std::istream&
operator>>(std::istream& inp, Event& e)
{
inp >> e.index;
inp >> e.day_of_week >> e.day >> e.month >> e.year;
std::getline(inp, e.message);
return inp;
}
To read an Event your code fragment would look like:
Event e;
my_input_file >> e;
Reading and storing many objects
Your loop for reading in many Events would look like:
std::vector<Event> event_container;
Event single_event;
while (my_input_file >> single_event)
{
event_container.push_back(single_event);
}
A Linked List of Events
A linked list is a container and can be reused for different objects.
To create a linked list of events, you should use std::list:
std::list<Event> event_container;
Event single_event;
while (my_input_file >> single_event)
{
event_container.push_back(single_event);
}
Linked List Class Assignment
If you happen to need to write a Linked List due to a class assignment, you should isolate the implementation of the list from the data:
struct Node
{
Node(Element * p_data = NULL)
: p_element(p_data), next(NULL)
{ ; }
Element * p_element;
Node * next;
};
struct Element_Linked_List
{
Node * p_head;
Node * p_tail;
Element_Linked_List()
: p_head(NULL), p_tail(NULL)
{ ; }
};
By loosely coupling the data (Element) from the container, you will be able to use this linked list in other assignments coming up.
Extending Encapsulation -- A date class
I recommend you take this a step further a move some of the workload and complexity to a Date class.
struct Date_DoW
{
static const char dow_names[] =
{
"Day Of Rest", "Monday", "Tuesday", "Wednesday",
"Thursday", "Friday", "Saturday", "Sunday",
}
enum Day_Of_Week {Monday = 1, Tuesday, Wednesday,
Thursday, Friday, Saturday, Sunday};
private:
void print_dow_name(Day_Of_Week dow, std::ostream& out)
{
out << dow_names(dow);
}
// etc...
};
You would augment the class above for days, months and years.
An advantage to refactoring the date as a separate object, is that you can test it separately, get it working, and not have to recompile it. You can also reuse it in other assignments.
I would do this by using the built-in getline() function to convert each line of the file into a string, then parse each string individually. You may also want to consider using delimiters inside the input file to help with the parsing process.
EDIT: Here is an example from a program i wrote a couple of months ago. The program finds all the possible ways in which a list of songs can be arranged on one or more LP records. This is the part of the program that parses the input file:
vector<song> songs;
string input, title, min, sec, infile;
ifstream inputStream;
cout << endl << "Enter input file name:" << endl;
getline(cin, infile);
inputStream.open(infile, ios::in);
while (inputStream.good() && !inputStream.eof())
{
getline(inputStream, input);
input = regex_replace(input, regex("^\\s+"), "");
input = regex_replace(input, regex("\\s+"), " ");
if (input != "" && input[0]!='#') // # symbol can be used to comment out lines in the input file
{
title = input.substr(0, input.find_last_of(" "));
min = input.substr(title.length() + 1, input.find_last_of(":") - input.find_last_of(" ") - 1);
sec = input.substr(title.length() + min.length() + 2, input.length() - (title.length() + min.length() + 2));
songs.push_back(song(title, stoi(min), stoi(sec)));
}
}
inputStream.close();
The calls to regex_replace are just to remove any unintentional whitespace padding from the data (not important if the input file is guaranteed to not have excess padding). The important part is that i am using getline(inputStream, input) to retrieve the data in the file one line at a time, then using the .substr() function of std::string to parse the data on the delimiter (not necessary if you know the exact length of the data being parsed).
For reference, here is how the input file is formatted:
Custard Pie 4:13
The Rover 5:37
In My Time of Dying 11:04
Houses of the Holy 4:02
Trampled Under Foot 5:37
Kashmir 8:32
In the Light 8:46
Bron-Yr-Aur 2:06
Down by the Seaside 5:13
Ten Years Gone 6:32
Night Flight 3:36
The Wanton Song 4:10
Boogie with Stu 3:53
Black Country Woman 4:24
Sick Again 4:42

How store class objects in vector<vector<class *>> and access and pass them to function either by reference or value

#ifndef BINARY_TREE_H
#define BINARY_TREE_H
#include<iostream>
#include<vector>
using namespace std;
class Binary_Tree;
static int levelCount=0;
extern vector<vector<Binary_Tree*>> vec;
extern vector<Binary_Tree*> tempVec;
class Binary_Tree
{
public:
Binary_Tree()
{
childNum=0;
data=0;
level=0;
prev=NULL;
next[0]=NULL;
next[1]=NULL;
};
Binary_Tree(int d)
{
childNum=0;
data=d;
level=0;
prev=NULL;
next[0]=NULL;
next[1]=NULL;
levelCount++;
}
void insert_node(int,int,int);
int get_level();
int get_childCount();
friend int set_childNum(Binary_Tree*);
private:
int childNum;
int data;
int level;
Binary_Tree *prev;
Binary_Tree *next[2];
};
#endif // BINARY_TREE_H
Here is the implementation file
#include<iostream>
#include<cmath>
#include "Binary_Tree.h"
using namespace std;
void Binary_Tree::insert_node(int lev, int d, int sib)
{
if(vec.empty())
{
cout<<"You Have to create Root first";
}
else
{
if(set_childNum(vec[lev][sib-1])==0)
{
cout<<"Child cant be created parent Node already has two childs.";
}
else
{
childNum=set_childNum(vec[lev][sib-1]);
data=d;
level=lev+1;
prev=vec[lev][sib];
next[0]=NULL;
next[1]=NULL;
tempVec.clear();
for(int i=0; i<pow(2,(lev+1)); i++)
{
if(i==childNum-1)
{
tempVec.push_back(this);
}
else
tempVec.push_back(vec[lev][i]);
}
vector<vector<Binary_Tree*>>::iterator itr=vec.begin()+(lev+1);
vec.erase(itr);
vec.insert(itr,tempVec);
}
}
}
int set_childNum(Binary_Tree *lstNdAdr)
{
if(lstNdAdr->get_childCount()==0)
return 1;
else if(lstNdAdr->get_childCount()==1)
return 2;
else
return 0;
}
int Binary_Tree::get_level()
{
return level;
}
int Binary_Tree::get_childCount()
{
if(next[0]==NULL)
{
return 0;
}
else if(next[0]!=NULL && next[1]==NULL)
{
return 1;
}
else
{
return 2;
}
}
MAIN.cpp
#include <iostream>
#include<cmath>
#include"Binary_Tree.h"
using namespace std;
vector<vector<Binary_Tree*>> vec;
vector<Binary_Tree*> tempVec;
int main()
{
Binary_Tree tree;
here:
cout<<"Enter your Choice:1.Create Root Of Tree\n"
<<"2.Insert node\n"<<endl;
int choice;
cin>>choice;
switch(choice)
{
case 1:
{
int d;
cout<<"Enter Data to insert: ";
cin>>d;
Binary_Tree treeDummy(d);
tree=treeDummy;
tempVec.push_back(&tree);
vec.push_back(tempVec);
}
break;
case 2:
{
int lev;
int sibbling;
int d;
cout<<"Enter at which level and data and parent's sibling-no.: ";
cin>>lev;
cin>>d;
cin>>sibbling;
if(sibbling>pow(2,lev))
cout<<"Illegal Sibbling Number."<<endl;
else
tree.insert_node(lev,d,sibbling);
}
break;
}
int x;
cin>>x;
if(x==5)
{
cout<<endl<<endl;
goto here;
}
return 0;
}
in above code i am trying to create a binary tree type structure which can be manipulated and traversed dynamically that is any node can be inserted and can be removed at run time (although its incomplete because i am stuck at a problem). While pushing back the tempVec vector the code produces a segmentation fault and i am also doubtful in passing the object stored in vetcor> vec to the functions in the implementation (I am new to Stl and first time dealing with vector of vectors containing pointer to the class types)
The nested vector's entries are only filled if i is set to 1. But you attempt to access its element [0][0] regardless. You have out of bounds access when i is not 1.
There are numerous problems present in your code, that and combined with the poor style and formatting makes it not so fun to debug.
Binary_Tree treeDummy(d);
tree = treeDummy;
tempVec.push_back(&tree);
I'm not sure what you're trying to do here but the above looks wrong. You are shallow copying treeDummy's data over to tree. You'll lose the link to whatever child node tree points to. Afterwards you're pushing that same tree instance into your temporary vector. That means all the elements in your vector ends up pointing to the local variable tree in main. So even if no segfault occurred you would run into aliasing problems since they all refer to the same tree object and not a separate unique BinaryTree instance.
vector< vector<Binary_Tree*> >::iterator itr=vec.begin()+(lev+1);
vec.erase(itr);
vec.insert(itr,tempVec);
Your BinaryTree::insert_node is using an invalidated iterator after performing erase which is undefined behavior.
childNum = set_childNum(vec[lev][sib-1]);
// ...
prev = vec[lev][sib];
The above can access an out-of-bound index in your vector. eg. You push_back a tempVec with only 1 element in it and then call insert_node with sib = 1.
// ...
if(x == 5)
{
cout<<endl<<endl;
goto here;
}
The use of goto is also completely unnecessary here and should be replaced with a traditional while loop that checks for condition != 5.
The higher level problem in your program, however, is that there's no clear constraints and invariants in its design. What assumptions and preconditions do each of those functions need to work? Why use vectors to hold BinaryTree nodes when the class itself should be dealing with that. You should get the overall design sorted out first, otherwise you'll just play whack-a-mole as other bugs crop up.

Segmentation Fault in Loop's Condition

The following code is to sort a linked list after creating it. The sorting algorithm used is somewhat similar to Bubble Sort. I am checking the two consecutive nodes and swapping them if necessary. I used the debugger which told me that the fault is raised while condition checking for the loops which are used while sorting.
#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<conio.h>
using namespace std;
struct link_list
{
char value[20];
struct link_list *next;
};
int main()
{
struct link_list *head=NULL;
int i,j;
char input[20];
char ch;
struct link_list *loop_var,*temp2,*prev_node,*temp4=NULL;
temp3=NULL;
do
{
cout<<"\nEnter the string you want to insert";
cin>>input;
cout<<"\nDo you want to continue entering?";
cin>>ch;
if (head==NULL)
{
head=new link_list;
strcpy(head->value,input);
head->next=NULL;
continue;
}
for (loop_var=head;loop_var->next!=NULL;loop_var=loop_var->next);
temp2=new link_list;
loop_var->next=temp2;
strcpy(temp2->value,input);
temp2->next=NULL;
}while(ch=='y' || ch=='Y');
for (loop_var=head;loop_var->next!=NULL;loop_var=loop_var->next)
{
cout<<loop_var->value<<"\n";
}
cout<<loop_var->value<<"\n";
char arr[20];
for (loop_var=head;loop_var->next!=NULL;loop_var=loop_var->next)
{
cout<<"\nLoop1";
for (temp4=head;temp4->next!=NULL;temp4=temp4->next)
{
cout<<"\nLoop2";
temp2=temp4;
if (strcmp(temp2->value,temp2->next->value)>0)
{
cout<<"\nSwap Enter";
if (temp2==head && temp2->next->next==NULL)
{
cout<<"\nSpecial1";
temp2->next->next=temp;
temp2->next=NULL;
}
else if (temp2==head)
{
cout<<"\nSpecial2";
head=temp2->next;
temp2->next=head->next;
head->next=temp2;
}
else if (temp2->next->next==NULL)
{
cout<<"\nSpecial3";
prev_node->next=temp2->next;
prev_node->next->next=temp2;
temp2->next=NULL;
}
else
{
cout<<"\nNormal1";
prev_node->next=temp2->next;
temp2->next=prev_node->next->next;
prev_node->next->next=temp2;
cout<<"\nNormal2";
}
}
prev_node=temp4;
cout<<"\nLoop2PreExit";
fflush(stdin);
cout<<"\nLoop2Exit";
}
cout<<"\nLoop1Exit";
}
for (loop_var=head;loop_var->next!=NULL;loop_var=loop_var->next)
{
cout<<loop_var->value<<"\n";
}
cout<<loop_var->value;
getch();
}
temp2->next->next=temp;
"temp" is not defined anywhere... if your compiler filled in that hole for you, then this is what is causing your loop's condition to segfault.
Also, naming every other variable "temp#" is an easy way to have mistakes like this.

File I/O in C++ - Having some trouble writing back data?

This project is a basic ATM program. I'm using a file to store all the account details. So, every time I run the .exe file, It will read the data from the file and insert it into an AVL tree. And when I close the program, all the data in the AVL nodes will be inserted back into the file.
Data is stored in the file in this order (Each separated by a newline char) ID, Password, Name, Add, City, Pin, Balance.
Sample file --
12
4576
Vert
No_999,GoLane
Dallas
89777
50000
16
2342
Nerd
No_888,FoLane
Chicago
89999
30000
The problem is I cannot write back data into the file. Any suggestions please?
P.S. Please excuse my inline class methods please...
Program--
#include<iostream>
#include<conio.h>
#include<string.h>
#include<fstream>
using namespace std;
fstream file("one2.txt",ios::in|ios::out);//Opening the file 'one2.txt' in global scope
//AVL tree code starts here
class avl
{
struct node //The structure node which is going to hold the data sets in the tree
{
int id,pwd;
char name[15],add[30],city[10];
int pn;
double bal;
node *left, *right;
int height;
//node constructors
node(int i,int p,char nam[15], char a[30], char c[10],int pin,double b, node * l,node * r,int h)
{
id=i;
pwd=p;
strcpy(name,nam);
strcpy(add,a);
strcpy(city,c);
pn=pin;
bal=b;
left=l;
right=r;
height=h;
}
node()
{
left=right=NULL;
id=pwd=pn=0;
bal=0;
height=-1;
}
};
node *root;
node *nullnode;
int Height(node *t)const //Func to return the height of a node
{
return((t==NULL)? -1:t->height);
}
int max(int a,int b)
{
return(a>b)?a:b;
}
//Beginning of Insert() -- To create and insert data into the nodes
void insert(const int &x,int p, char nam[15], char a[30], char c[10],int pin,double b, node *&t)
{
if(t==NULL)
t = new node(x,p,nam,a,c,pin,b,NULL,NULL,-1);
else if(x<t->id)
{
insert(x,p,nam,a,c,pin,b,t->left);
if(Height(t->left) - Height(t->right)==2)
{
if(x<t->left->id)
single_rotate_with_left(t);
else
double_rotate_with_left(t);
}
}
else if(x>t->id)
{
insert(x,p,nam,a,c,pin,b,t->right);
if(Height(t->right)-Height(t->left)==2)
{
if(x>t->right->id)
single_rotate_with_right(t);
else
double_rotate_with_right(t);
}
}
else
t->height=max(Height(t->left),Height(t->right)+1);
}
//End of insert()
//Func to print the node data. Just a sample to check if all the data
// were inserted into the tree
//Inorder traversal
void print(node *&t)
{
if(t!=NULL)
{
print(t->left);
cout<<endl;
cout<<"ID "<<t->id<<" Name "<<t->name;
cout<<endl<<t->pwd<<endl<<t->add<<"\n"<<t->city;
cout<<"-"<<t->pn<<endl<<t->bal<<endl;
print(t->right);
}
}
//Think there's gonna be no problem with the rotation and other AVL tree func codes.
//Beginning of AVL rotations
void single_rotate_with_left(node *&k2)
{
node *k1=k2->left;
k2->left=k1->right;
k1->right=k2;
k2->height=max(Height(k2->right),Height(k2->left))+1;
k1->height=max(Height(k1->left),(k2->height))+1;
k1=k2;
}
void single_rotate_with_right(node *&k2)
{
node *k1=k2->right;
k2->right=k1->left;
k1->left=k2;
k2->height=max(Height(k2->left),Height(k2->right))+1;
k1->height=max(Height(k1->right),(k2->height))+1;
k1=k2;
}
void double_rotate_with_left(node *&a)
{
single_rotate_with_right(a->left);
single_rotate_with_left(a);
}
void double_rotate_with_right(node *&a)
{
single_rotate_with_left(a->right);
single_rotate_with_right(a);
}
//End of AVL rotations
//Function to return the node. The 'id' variable to be searched is passed as a param
node*& search(int x,node *&t)
{
if(t->id>x)
return search(x,t->left);
else if(t->id<x)
return search(x,t->right);
else if(t->id==x)
{
return t;
}
else
return nullnode;
}
//End of search. I'm using this in the loadnode() function.
//This is where I try to write data back into the file.
void update1(node *&t,int x) // x is the control variable
{
if(x==1)
//This block will be executed only once when the function is called for the
//first time. Used to seek to the beginning of the file
{
file.seekg(0,ios::beg);
x++;
}
if(t!=NULL)// Inorder traversal in the tree
{
update1(t->left,x);
//writing the data in the same order as it was stored.
file<<t->id<<endl;
file<<t->pwd<<endl;
file<<t->name<<endl;
file<<t->add<<endl;
file<<t->city<<endl;
file<<t->pn<<endl;
file<<t->bal<<endl;
update1(t->right,x);
}
}
public:
//Avl Constructor - This one is the one which is actually used.
avl(int x,int p,char nam[15], char a[30], char c[10],int pin,double b)
{
root= new node(x,p,nam,a,c,pin,b,NULL,NULL,-1);
nullnode=new node;
}
avl()
{
root->left=root->right=NULL;
root->height=-1;
}
//Call to the private insert function
void insert1(const int &x,int p,char nam[15], char a[30], char c[10],int pin,double b)
{
insert(x,p,nam,a,c,pin,b,root);
}
//Call to the private print() function
void display()
{
cout<<endl;
print(root);
}
//Function to write a new value for 'bal' variable to a node.
//I'm actually using this to update a node anconfirm whether the value of the updated node
//is reflected back at the node
void loadnode(int x)
{
node *&t=search(x,root);
cout<<"\nLoaded node...\n";
cout<<t->id;
cout<<" "<<t->name;
t->bal=40000;
cout<<"\nUpdated Bal.."<<t->bal;
}
void update()
{
//file.seekp(0);
update1(root,1);
}
};//End of AVL Class
main()
{
cout<<"The output..\n";
int i, p, pn;
char n[15],a[30],c[10];
double b;
int prev_id=0;
file>>i>>p>>n>>a>>c>>pn>>b;
prev_id=i;
avl list(i,p,n,a,c,pn,b);
while(file)
{
file>>i>>p>>n>>a>>c>>pn>>b;
if(prev_id!=i)
// I'm using this because i got a weird scenario in which the last record was repeated twice.
{
list.insert1(i,p,n,a,c,pn,b);
}
prev_id=i;
}
cout<<endl<<"The elements in AVL tree are...\n\n";
list.display();
list.loadnode(12);//12 is the id i used for one of my records.
//Calling to write back the data into the file.
list.update();
file.close();
getch();
return 0;
}
//End of program
If file.good() returned false, some previous operation on the file failed (maybe even a read operation) and raised one of the error flags of the file object. An ugly way to solve it is to use file.clear() which will clear the error flag and allow next actions to execute successfully. A better way to solve it will be to check after each operation if there's an error (file.good() is false) and understand why this operation fails and fix it.
call seekp() to move the write pointer to the begining of the stream (fstream). seekg() moves the get pointer - not going to help when writing...