C++ Linked List node counting (need help) - c++

I'm trying to create a program that gets string input from a text file, inserting the content into a list, word by word. I also have to calculate the numbers of the duplicates. My program works fine for the small input text file (1 line of string). But whenever I feed it with a bigger text file, it crashes. Any help will be great.
Here is my code:
#include <iostream>
#include <fstream>
#include <sstream>
using namespace std;
class Bag
{
private:
struct BagNode
{
string dataValue;
int dataCount;
BagNode *next;
BagNode(string);
};
BagNode *root;
string removePunctuations(string);
string toLower(string);
void insertData(string);
public:
Bag();
void procesFile(string, string);
void removeData(string);
void traverse();
};
Bag::BagNode::BagNode(string _data)
{
dataValue.assign(_data);
dataCount=1;
next = NULL;
}
Bag::Bag()
{
root = NULL;
}
void Bag::procesFile(string ifile, string ofile)
{
ifstream infile;
infile.open(ifile.c_str());
if (!infile.good())
{
cout<<"Input file not opening."<<endl;
return;
}
string line;
while(getline(infile,line))
{
stringstream lineStream(line);
string token = "";
while(lineStream >> token)
{
insertData(removePunctuations(token));
}
}
infile.close();
traverse();
cout<< endl <<"File processed successfully." << endl;
}
string Bag::removePunctuations(string data)
{
int length = data.size();
for(int i = 0; i < length; i++)
{
if(ispunct(data[i]))
{
data.erase(i--, 1);
length = data.size();
}
}
return data;
}
string Bag::toLower(string data)
{
for(int i = 0; data[i]; i++){
data[i] = tolower(data[i]);
}
return data;
}
void Bag::insertData(string data)
{
BagNode *n = new BagNode(data);
if (root == NULL)
{
root = n;
return;
}
BagNode *temp = root;
BagNode *prev = NULL;
string tdata;
data.assign(toLower(data));
while(temp != NULL)
{
tdata.assign(temp->dataValue);
tdata.assign(toLower(tdata));
if (tdata.compare(data) == 0)
{
temp->dataCount++;
return;
}
else
{
if (data.compare(tdata) < 0)
{
if (temp == root)
{
n->next = temp;
root = n;
return;
}
else
{
n->next = temp;
prev->next = n;
return;
}
}
}
prev = temp;
temp = temp->next;
}
n->next = temp;
prev->next = n;
}
void Bag::removeData(string data)
{
BagNode *temp = root;
BagNode *prev = NULL;
if (root->dataValue.compare(data)==0)
{
if (root->dataCount > 1)
root->dataCount--;
else
{
delete root;
root = NULL;
}
cout<<"Data removed successfully."<<endl;
return;
}
while (temp != NULL)
{
if (temp->dataValue.compare(data)==0)
{
if (temp->dataCount > 1)
temp->dataCount--;
else
{
prev->next = temp->next;
delete temp;
temp = NULL;
}
cout<<"Data removed successfully."<<endl;
return;
}
prev = temp;
temp = temp->next;
}
cout<<"Data not found match."<<endl;
}
void Bag::traverse()
{
if (root == NULL)
{
cout<<"No data."<<endl;
return;
}
BagNode *temp = root;
while(temp != NULL)
{
if (temp->dataCount > 1)
cout << temp -> dataValue << "(" << temp->dataCount << ")" << endl;
else
cout << temp -> dataValue << endl;
temp = temp->next;
}
}
int main(int argc, char *argv[])
{
bool outputConsole = false;
string infile, outfile = "\0";
cout << "Welcome!" << endl;
int option = -1;
do{
if (argc==1 || option == 1)
{
cout << "Enter the input file: ";
cin >> infile;
cout << "Enter the output file: ";
cin >> outfile;
}
else
{
infile.assign(argv[1]);
if (argc == 3)
outfile.assign(argv[2]);
}
Bag b;
b.procesFile(infile,outfile);
//b.traverse();
cout<<endl<<"If you want to input another file press 1 or 2 to quit: ";
cin>>option;
}while (option != 2);
return 0;
}

If ordering of words is not an issue,you should really try and use a hash table instead of a linked list as hash table is suitable for keeping track of duplicates.This will lead to O(1) insert operation (in ideal situation)

Related

Program.exe has triggered a breakpoint in destructor of linked list class

When I run my program, everything works as expected until the destructor of the LList class. On the line that says delete current;, I get the following error:
BlankConsoleLab.exe has triggered a breakpoint.
I have been trying to solve this issue for a long time. I would appreciate it if perhaps someone could try to point out what I am doing wrong here.
Below is my code for the program. Thank you
Linked List Class
class LList
{
private:
Node* head;
Node* tail;
int size = 0;
public:
LList()
{
head = nullptr;
tail = nullptr;
size = 0;
}
LList(Node* h, Node* t)
{
this->head = h;
this->tail = t;
}
~LList()
{
Node* current = head;
while (current != nullptr) {
Node* next = current->m_next;
delete current;
current = next;
}
}
void print()
{
//temporary node pointer to traverse through the linked list
Node* temp = head;
cout << endl << "<MY LINKED LIST>\n";
while (temp != nullptr)
{
cout << temp->m_data.firstName << " ";
cout << temp->m_data.lastName << " ";
cout << temp->m_data.hrWage << " ";
cout << temp->m_data.hrWork << " " << endl;
temp = temp->m_next;
}
cout << endl;
}
void removeFirst()
{
//case 1: linked list is empty (never enters loop)
//case 2: linked list is not empty
if (head != nullptr)
{
Node* temp = head;
head = head->m_next;
delete temp;
//decrease size tracker of the linked list
size--;
}
}
void removeLast()
{
//case 1: linked list is empty (never enters loop)
//case 2: linked list has one node
if (head->m_next == nullptr)
{
removeFirst();
}
//case 3: linked list has more than one node
else if (head != nullptr)
{
Node* cur = head;
Node* prev = nullptr;
while (cur->m_next != nullptr)
{
prev = cur;
cur = cur->m_next;
}
tail = prev;
tail->m_next = nullptr;
delete cur;
//decrease size tracker of the linked list
size--;
}
}
//void removeAt(int pos)
//{
// //Case 1: input is invalid (less than 1 or greater than size)
// if (pos < 1 && pos > size)
// {
// return;
// }
// //Case 2: input is position 1
// else if (pos == 1)
// {
// removeFirst();
// }
// //Case 3: input is the last position (input equals size)
// else if (pos == size)
// {
// removeLast();
// }
// //Case 4: input is valid, and not 1 or last position (greater than 1 and less than size)
// else if (head != nullptr)
// {
// Node* cur = head;
// Node* prev = nullptr;
// for (int i = 1; i < pos; i++)
// {
// prev = cur;
// cur = cur->m_next;
// }
// prev->m_next = cur->m_next;
// delete cur;
// size--;
// }
//}
Node* swap(Node* lh, Node* rh)
{
Node* temp = rh->m_next;
rh->m_next = lh;
lh->m_next = temp;
return rh;
}
void readBin()
{
ifstream file;
file.open("C:\\Users\\there\\source\\repos\\cst126-lab9-JEmersonLawrance\\BlankConsoleLab\\Employee Data.bin", ios::binary);
if (file)
{
Node* cur = head;
Node* prev = nullptr;
for (int i = 0; i < 4; i++)
{
file.read((char*)&cur->m_data.firstName, sizeof(cur->m_data.firstName));
file.read((char*)&cur->m_data.lastName, sizeof(cur->m_data.lastName));
file.read((char*)&cur->m_data.hrWage, sizeof(cur->m_data.hrWage));
file.read((char*)&cur->m_data.hrWork, sizeof(cur->m_data.hrWork));
prev = cur;
cur = cur->m_next;
}
return;
}
else
{
cout << "File could not be opened..\n" << endl;
}
file.close();
}
void writeBin()
{
ofstream file;
file.open("Employee Data Output.bin", ios::binary);
if (file)
{
Node* cur = head;
Node* prev = nullptr;
while (cur != nullptr)
{
file.write((char*)&cur->m_data.firstName, sizeof(cur->m_data.firstName));
file.write((char*)&cur->m_data.lastName, sizeof(cur->m_data.lastName));
file.write((char*)&cur->m_data.hrWage, sizeof(cur->m_data.hrWage));
file.write((char*)&cur->m_data.hrWork, sizeof(cur->m_data.hrWork));
prev = cur;
cur = cur->m_next;
}
}
else
{
cout << "File could not be opened..\n" << endl;
}
file.close();
}
};
Node Class
class Node
{
public:
Employee m_data;
Node* m_next;
Node()
{
m_data.firstName = "";
m_data.lastName = "";
m_data.hrWage = 0;
m_data.hrWork = 0;
m_next = nullptr;
}
Node(Node* next)
{
m_data.firstName = "";
m_data.lastName = "";
m_data.hrWage = 0;
m_data.hrWork = 0;
m_next = next;
}
Node(const Node& copy)
{
m_data.firstName = copy.m_data.firstName;
m_data.lastName = copy.m_data.lastName;
m_data.hrWage = copy.m_data.hrWage;
m_data.hrWork = copy.m_data.hrWork;
}
Node operator = (const Node& copy)
{
m_data.firstName = copy.m_data.firstName;
m_data.lastName = copy.m_data.lastName;
m_data.hrWage = copy.m_data.hrWage;
m_data.hrWork = copy.m_data.hrWork;
return *this;
}
~Node()
{
}
};
Employee Class
struct Employee
{
public:
string firstName;
string lastName;
int hrWage;
int hrWork;
Employee()
{
firstName = "";
lastName = "";
hrWage = 0;
hrWork = 0;
}
Employee(string first, string last, int wage, int work)
{
firstName = first;
lastName = last;
hrWage = wage;
hrWork = work;
}
~Employee()
{
}
void getInput()
{
for (int i = 0; i < 4; i++)
{
cout << "EMPLOYEE # " << i+1 << ":\n" << endl;
cout << "First name: ";
cin >> this[i].firstName;
cout << "Last name: ";
cin >> this[i].lastName;
cout << "Hourly Wage: ";
cin >> this[i].hrWage;
cout << "Hours Worked: ";
cin >> this[i].hrWork;
}
}
void writeBin()
{
ofstream file;
file.open("C:\\Users\\there\\source\\repos\\cst126-lab9-JEmersonLawrance\\BlankConsoleLab\\Employee Data.bin", ios::binary);
if (file)
{
for (int i = 0; i < 4; i++)
{
file.write((char*)&this[i].firstName, sizeof(this[i].firstName));
file.write((char*)&this[i].lastName, sizeof(this[i].lastName));
file.write((char*)&this[i].hrWage, sizeof(this[i]).hrWage);
file.write((char*)&this[i].hrWork, sizeof(this[i]).hrWork);
}
}
else
{
cout << "File could not be opened..\n" << endl;
}
file.close();
}
};
Main Function
int main()
{
cout << "In this program, LIST will read the user information"
<< " in from a binary file, and output it into a different binary"
<< " file.\n" << endl;
Employee data[4];
data->getInput();
data->writeBin();
//creating linked list
Node fourth;
Node third(&fourth);
Node second(&third);
Node first(&second);
LList LIST(&first, &fourth);
LIST.readBin();
LIST.writeBin();
LIST.print();
return 0;
}
In main(), you are constructing your LIST object with pointers to local Node objects that are created in automatic memory within main()'s call frame. When main() exits, all of its local variables are destroyed automatically. But, when the LIST object is destroyed, its destructor tries to call delete on those Node objects which were not created in dynamic memory with new. Thus, your code exhibits undefined behavior.

C++ tree data structure Access violation with String

I am trying to make a tree data structure with c++. Originally I tested with int data, it was going fine. However, when I try to use a string data type, it keeps showing an unhandled exception. It said read access violation, this was 0x5D. I don't know what is causing the error. The complete same code only changing int to string causes the violation.
Main:
#include <bits/stdc++.h>
#include "Tree.h"
using namespace std;
int main()
{
Tree A;
int choice; bool isCre=0;
cout << "Input choice : ";
while (cin >> choice) {
switch (choice)
{
case 1:
if (!isCre) {
A.create_tree(); isCre = 1;
break;
}
else {
A.add_tree();
break;
}
case 2:
A.delete_tree(); break;
case 3:
A.modify_tree(); break;
case 4:
A.display_tree(); break;
}
cout << "Input choice : ";
}
}
Header file:
#ifndef TREE_H
#define TREE_H
#include <bits/stdc++.h>
using namespace std;
class Tree
{
private:
struct Tre
{
Tre* parent; Tre* right; Tre* left;
string data;
Tre(Tre* parent, string data)
{
this->parent = parent;
this->data = data;
left = right = NULL;
}
};
Tre* root;
Tre* create(Tre*& root, string data)
{
Tre* p;
p = new Tre(NULL, data);
root = p;
return root;
}
void dis(Tre* node)
{
if (node == NULL)
return;
cout << node->data << endl;
dis(node->left);
dis(node->right);
}
Tre* search(Tre* node, string data)
{
if (node == NULL)
return NULL;
if (node != NULL && node->data == data)
return node;
/* then recur on left subtree */
Tre* p = search(node->left, data);
// node found, no need to look further
if (p != NULL && p->data == data) return p;
/* node is not found in left,
so recur on right subtree */
Tre* q = search(node->right, data);
if (q != NULL && q->data == data) return q;
}
Tre* add(Tre* root, string find, string input)
{
Tre* p = root;
p = search(root, find);
if (p->left != NULL)
{
p->right = new Tre(p, input);
//p->left = new Tre(p, input);
}
else if (p->left == NULL)
{
p->left = new Tre(p, input);
//p->right = new Tre(p, input);
}
return root;
}
Tre* del(Tre* root, string data)
{
Tre* p = root, * q;
p = search(root, data);
q = p->parent;
if (q->right != NULL && q->right->data == data)
{
q->right = NULL;
delete p;
}
else if (q->left->data == data)
{
q->left = NULL;
delete p;
}
return root;
}
Tre* modify(Tre* root, string find, string input)
{
Tre* p = root;
p = search(p, find);
p->data = input;
return root;
}
public:
void create_tree();
void display_tree();
void add_tree();
void delete_tree();
void modify_tree();
};
#endif
#endif
Implementation file:
#include "Tree.h"
void Tree::create_tree()
{
string data;
cout << "Input data : "; cin >> data;
create(root, data);
}
void Tree::display_tree()
{
dis(root);
}
void Tree::add_tree()
{
string find, input;
cout << "Parent data : "; cin >> find;
cout << "New data : "; cin >> input;
add(root, find, input);
}
void Tree::delete_tree()
{
string data;
cout << "Delete data : "; cin >> data;
del(root, data);
}
void Tree::modify_tree()
{
string find, input;
cout << "Find data : "; cin >> find;
cout << "New data : "; cin >> input;
modify(root, find, input);
}

How to make gotoxy() function select the node in the link list the cursor is on?

I am writing a basic text editor as an assignment and I am having trouble. I am using linked lists and I can move the cursor around the list but every time I try to insert a letter (one letter a node) in between others it just inserts the letter at the end of the list. The code has other errors in general only looking for help on this main question but any suggestions is appreciated.
#include <iostream>
#include <conio.h>
#include <windows.h>
#include <fstream>
#include <string>
using namespace std;
class Node
{
public:
char c;
Node* next;
Node* prev;
};
void gotoxy(int x, int y)
{
COORD pos = { x, y };
HANDLE output = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleCursorPosition(output, pos);
}
void createNew()
{
Node* start = nullptr;
Node* end = nullptr;
Node* prevNode = nullptr;
int xcur = 0, ycur = 0;
char letter = ' ';
while (letter != 27)
{
letter = _getch();
if (letter == 8) // backspace
{
Node *p;
p = end;
end = end->prev;
delete p;
end->next = nullptr;
xcur--;
}
else if (letter == 57) //save press '9'
{
ofstream outdoc;
outdoc.open("TheEditor.txt");
Node* save;
char data;
save = start;
while (save->next != nullptr)
{
data = save->c;
outdoc << data;
save = save->next;
}
outdoc.close();
}
else if (letter == -32)
{
// he pressed right up left or down
letter = _getch();
if (letter == 75) //72 is up 75 left 77 right 80 down
--xcur;
if (letter == 77)
xcur++;
//if (letter == 72)
//ycur++;
//if (letter == 80)
//ycur--;
}
else if (letter == 56) //load file
{
ifstream indoc;
string fname;
cout << "Please enter the name of the file" << endl;
cin >> fname;
indoc.open(fname);
char file[sizeof(indoc)];
for (int j = 0; j < sizeof(fname); j++)
{
indoc >> file[j];
cout << file[j];
j++;
}
}
else if (letter == 13) // enter
{
xcur = 1;
ycur++;
//start = arr[ycur];
}
else // normal eltter
{
Node* p;
p = new Node();
p->c = letter;
p->next = nullptr;
p->prev = nullptr;
if (start == nullptr)
{
start = p;
end = p;
prevNode = p;
}
else if (end->next != nullptr) // insert in middle
{
Node* m = new Node();
m->next = end;
m->c = letter;
m->prev = prevNode;
end->prev = m;
prevNode = m;
}
else
{
p->prev = prevNode;
end->next = p;
end = p;
prevNode = p;
}
//xcur++;
}
system("cls");
// display your linked list here.
Node *p;
p = start;
while (p != nullptr)
{
_putch(p->c);
p = p->next;
}
gotoxy(xcur, ycur);
}
}
void loadFile()
{
string fname;
ifstream indoc;
cout << "Please enter the name of the document" << endl;
cin >> fname;
system("CLS");
indoc.open(fname);
Node* start = nullptr;
Node* end = nullptr;
Node* prevNode = nullptr;
int xcur = 0, ycur = 0;
char letter = ' ';
char file[sizeof(indoc)];
for (int j = 0; j < sizeof(fname); j++)
{
indoc >> file[j];
cout << file[j];
j++;
}
indoc.close();
while (letter != 27)
{
_putch(letter);
if (start == nullptr)
{
Node* p;
p = new Node();
p->c = letter;
p->next = nullptr;
p->prev = nullptr;
start = p;
end = p;
prevNode = p;
}
else
{
Node* t;
t = new Node();
t->c = letter;
t->next = nullptr;
t->prev = prevNode;
end->next = t;
end = t;
prevNode = t;
}
letter = _getch();
if (letter == 57) //save press '9'
{
ofstream outdoc;
outdoc.open("RereTheEditor.txt");
Node* save;
char data;
save = start;
while (save->next != nullptr)
{
data = save->c;
outdoc << data;
save = save->next;
}
outdoc.close();
}
}
}
int main()
{
int choice;
cout << "Welcome to theEditor 2.0!\n"
<< "Please select an option\n"
<< "1. Create New\n"
<< "2. Load File" << endl;
cin >> choice;
system("CLS");
switch (choice)
{
case 1: { createNew(); }
break;
case 2: { loadFile(); }
break;
}
return 0;
}
You must record the corresponding cursor coordinates in each node before you can pass through it.
class Node
{
public:
char c;
COORD pos;
Node* next;
Node* prev;
void setpos(int x, int y)
{
pos.X = x;
pos.Y = y;
}
};
Get the current cursor coordinatesbInfo.dwCursorPosition with GetConsoleScreenBufferInfo:
HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_SCREEN_BUFFER_INFO bInfo;
GetConsoleScreenBufferInfo(hOut, &bInfo);
then go to the link list to find the corresponding node of the same position, then insert, and update the coordinates of each node.

Output of c++ program not coming as expected

I have made a C++ program for a binary tree. But the terminal is not asking the statement for inputting the direction for where the elements are to be placed.
Also when I replace the statement from " node *temp = new node " to "node *temp=NULL" the program stops working .
#include <iostream>
#include <cstring>
using namespace std;
class node {
int data;
node * left;
node * right;
public:
node * level_order(node * first);
node * create_bt(node * first);
void display(node * first);
};
//node *first=NULL;
node * node::create_bt(node * first) {
node * temp = new node;
int ele;
//char dir;
cout << "\n Enter data ";
cin >> ele;
temp->data = ele;
temp->left = NULL;
temp->right = NULL;
if (first == NULL) {
temp = first;
return first;
} else {
char dir[20];
cout << "\n Enter the direction ";
cin >> dir;
node * cur = first;
int j = 0;
while (dir[j] != '\0') {
if (dir[j] == 'l') {
cur = cur->left;
}
if (dir[j] == 'r') {
cur = cur->right;
}
j++;
}
cur = temp;
return first;
}
}
void node::display(node * first) {
if (first == NULL)
return;
cout << "\n " << first->data;
display(first->left);
display(first->right);
}
int main() {
int n;
node s;
node * first = NULL;
cout << "\n No of elements ";
cin >> n;
for (int i = 0; i < n; i++) {
first = s.create_bt(first);
}
s.display(first);
return 0;
}
first=s.create_bt(first); does not changes state, from NULL to 'l' or 'r'. You have to change that.
node*node::create_bt(node *first)
{
node *temp=new node;
int ele;
//char dir;
cout<<"\n Enter data ";
cin>>ele;
temp->data=ele;
temp->left=NULL;
temp->right=NULL;
char dir[20];
cout<<"\n Enter the direction ";
cin>>dir;
if(first==NULL)
{
temp=first;
return first;
}
else
{
node*cur=first;
int j=0;
while(dir[j]!='\0')
{
if(dir[j]=='l')
{
cur=cur->left;
}
if(dir[j]=='r')
{
cur=cur->right;
}
j++;
}
cur=temp;
return first;
}
}
I believe you re looking something like this. This is a basic binary tree, i had to make a basic one in order to understand how it works and how it chooses left and right. I make a class inside a class, in order to have access to my data members (node class, int data, *left , *right) and have them at the same time protected, all-in-one. As you can see "newnode" just creates a node and NULL s the pointers. Thats it. "Find" searches and finds a node with a current key, and returns it when exits. All the rest, i guess, you can understand them, as they are prety much the same with your code. The only thing you have to do is to define, when you want to direct the node you want. REMINDER: You have to find a way to utilize it, so the leafs will not end far-left or far-right.("Enter the direction"). I hope i helped you understand.
#include <iostream>
#include <conio.h>
using namespace std;
class mybTree {
class node {
public:
int data;
node * left;
node *right;
};
node *root;
node *newnode(int num){
node *newnode1;
newnode1 = new (nothrow) node;
newnode1->data = num;
newnode1->left = NULL;
newnode1->right = NULL;
return newnode1;
}
public:
node *find (int key) {
node *current;
current = root;
while (current->data !=key){
if (key<current->data){
current = current->left;
} else {
current = current->right;
}
if (current == NULL){
return NULL;
}
}
return NULL;
}
void display (node *ptr);
void display_tree();
bool insert(int num);
void post_order_delete(node *ptr);
mybTree();
~mybTree();
};
int main(){
char ch = ' ';
int a;
mybTree mybTree1;
while (ch !='0'){
cout << "0->Exit"<<endl<< "1-> add"<<endl<< "2-> find" <<endl<<"3-> Show me the tree\n";
ch = getch();
switch (ch) {
case '0':
break;
case '1':
cout << "number";
cin >> a;
if (!mybTree1.insert(a)){
cout << "Not enough memory" << endl;
}
break;
case '2' :
cout << "Number:" ;
cin >> a;
if (mybTree1.find(a)!=NULL) {
cout << "Found" << endl;
} else {
cout << "Not existed" << endl;
}
break;
case '3':
mybTree1.display_tree();
cout<<endl;
break;
default:
cout << "Wrong Message";
break;
}
}
return 0;
}
void mybTree::display(node *ptr) {
if (ptr == NULL){
return;
}
display(ptr->left);
cout << ptr->data<<endl;
display(ptr->right);
}
void mybTree::display_tree() {
//Displays the Tree
display(root);
}
bool mybTree::insert(int num) {
//It inserts a node. Desides left or right.
node *next,*current,*ptr;
int isleft;
next = current = root;
ptr = newnode(num);
if (ptr == NULL) {
return false;
}
if (root == NULL) {
root = ptr;
return true;
}
while (1){
if (num < current->data){
next = current->left;
isleft = 1;
} else {
next = current->right;
isleft = 0;
}
if (next == NULL){
if (isleft){
current->left = ptr;
} else {
current->right = ptr;
}
return true;
}
current=next;
}
return false;
}
void mybTree::post_order_delete(node *ptr) {
//deletes the node. Usefull for destructor
if (ptr == NULL){
return;
}
post_order_delete(ptr->left);
post_order_delete(ptr->right);
cout << ptr->data;
delete ptr;
}
mybTree::mybTree() {
//Constructor
root = NULL;
}
mybTree::~mybTree() {
//Destructor
post_order_delete(root);
root = NULL;
}

Delete return memory problems

I am writing a simple program for working with structure in C++. But there is a problem with memory. When my program calling a delete_element function it return memory's problem, but delete_all_list function working well. What I did wrong?
#include "iostream"
#include "string.h"
#include "limits" //ignore max
#include "stdlib.h" //atof
using namespace std;
struct Struct {
char text[10];
int age;
Struct *prev;
Struct *next;
};
int input(string msg) {
char str[2];
int check = 0, len = 0, var = 0, i = 0;
while (1){
cin.tellg();
cout<<msg;
cin.getline(str, 2);
if (cin.fail()) {
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
}
len = strlen(str);
check = 0;
for (i=0;i<len;i++) {
if(isdigit(str[i])) {
check++;
}
}
if (check==len && !(check==1 && str[0]=='-') && check != 0 && atoi(str) != 0){
var = atoi(str);
return var;
}
else {
cout<<"Error!"<<endl;
}
}
}
Struct* add_struct_to_list(Struct* prev){
Struct *NewStruct = 0;
char str[10];
int age;
cout<<"Name: ";
cin.getline(str, 10);
if (cin.fail()){
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
}
age = input("Age: ");
NewStruct = new Struct;
strcpy(NewStruct->text, str);
NewStruct->age = age;
NewStruct->prev= prev;
NewStruct->next= 0;
return NewStruct;
}
Struct* add_empty_struct_to_list(Struct* list_begin, int index){
int count = 1;
Struct* node = list_begin;
while (node->next) {
node = node->next;
count++;
}
while (count != index) {
Struct* NewStruct = new Struct;
strcpy(NewStruct->text, " ");
NewStruct->age = 0;
NewStruct->prev = node;
node->next = NewStruct;
NewStruct->next = NULL;
node = NewStruct;
count++;
}
return node;
}
void insert_struct_to_list(Struct* prev, Struct* next){
Struct *NewStruct = 0;
char str[10];
int age;
cout<<"Name: ";
cin.getline(str, 10);
if (cin.fail()){
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
}
age = input("Age: ");
NewStruct = new Struct;
strcpy(NewStruct->text, str);
NewStruct->age = age;
NewStruct->prev= prev;
NewStruct->next= next;
prev->next = NewStruct;
next->prev = NewStruct;
}
void replace_struct_in_list(Struct* ReStruct){
char str[10];
int age;
cout<<"Name: ";
cin.getline(str, 10);
if (cin.fail()){
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
}
age = input("Age: ");
strcpy(ReStruct->text, str);
ReStruct->age = age;
}
Struct* start_new_list(int number) {
Struct* prevStruct = NULL;
Struct* newList = NULL;
for (int counter = 0; counter < number; counter++) {
Struct* newStruct = add_struct_to_list(prevStruct);
if (prevStruct)
prevStruct->next = newStruct;
if (counter == 0)
newList = newStruct;
prevStruct = newStruct;
}
return newList;
}
Struct* find_a_struct(Struct* list_begin, int index){
Struct* node = list_begin->next;
int count = 1;
if (node != NULL) {
while (node->next) {
node = node->next;
count++;
if (count == index) {
break;
}
}
if (count < index) {
node = NULL;
}
}
return node;
}
void add_extra_struct_to_list(Struct* list_begin) {
string command;
Struct* NewStruct = NULL;
int index = input("Enter index of new element (it should be less then 99): ");
Struct* FindedStruct = find_a_struct(list_begin, index);
if (FindedStruct != NULL) {
while (true) {
cout<<"This index is already exist. Replace? (Yes/No): ";
cin>>command;
cout<<endl;
if (command == "Yes" || command == "No") {
break;
}
}
if (command == "No") {
insert_struct_to_list(FindedStruct->prev, FindedStruct);
} else {
replace_struct_in_list(FindedStruct);
}
} else {
NewStruct = add_empty_struct_to_list(list_begin, index);
Struct* ExtraStruct = add_struct_to_list(NewStruct->prev);
NewStruct->next = ExtraStruct;
}
}
void delete_element(Struct* node) {
int index = 0; int count = 1;
bool is_index = false;
do {
index = input("Enter number of index: ");
} while (index <= 0);
do {
node = node->next;
count++;
if (count == index) {
Struct* prevs = 0;
prevs = node->prev;
Struct* nexts = 0;
nexts = node->next;
delete node;
prevs->next = nexts;
nexts->prev = prevs;
is_index = true;
break;
}
} while (node->next);
if (is_index == true) {
cout<<"Done!"<<endl;
} else {
cout<<"Index is out off range!"<<endl;
}
}
void delete_all_list(Struct* list_begin) {
Struct* structToDelete = NULL;
Struct* node = list_begin;
while (node->next) {
structToDelete = node;
node = node->next;
delete structToDelete;
}
delete node;
}
void sort_by_age(Struct* list_begin) {
Struct* node = 0;
Struct* node2 = 0;
int age; char text[10];
for (node = list_begin; node; node = node->next) {
for (node2 = list_begin; node2; node2 = node2->next) {
if (node->age < node2->age) {
strcpy(text, node->text);
strcpy(node->text, node2->text);
strcpy(node2->text, text);
age = node->age;
node->age = node2->age;
node2->age = age;
}
}
}
}
void print_list(Struct* list_begin) {
for (Struct* node = list_begin; node; node = node->next) {
cout<<"Age: "<<node->age<<"; Name: "<<node->text<<endl;
}
}
int main() {
int number;
Struct *NewList = 0;
string command;
bool list = false;
cout<<"\"help\" for more info"<<endl<<endl;
while (true) {
cout<<">>> ";
cin>>command;
cout<<endl;
if (command == "help") {
cout<<"startlist - creating a new double-linked list."<<endl;
cout<<"sortlist - sorting list by age of workers."<<endl;
cout<<"printlist - prining all list's elements."<<endl;
cout<<"addextra - adding extra element to list."<<endl;
cout<<"delete - delete element from list."<<endl;
cout<<"deletelist - delet all list. (Warning: require for create new list!)"<<endl;
cout<<"exit - close program."<<endl;
} else if (command == "startlist") {
if (list == false) {
number = input("Number of worker (it should be less than 99): ");
NewList = start_new_list(number);
cout<<"Done!"<<endl;
list = true;
} else {
cout<<"Error: You allready create one!"<<endl;
}
} else if (command == "sortlist"){
if (list == true) {
sort_by_age(NewList);
cout<<"Done!"<<endl;
} else {
cout<<"Error: You did't create a list or it is already sorted!"<<endl;
}
} else if (command == "printlist") {
if (list == true) {
print_list(NewList);
} else {
cout<<"Error: You did't create a list!"<<endl;
}
} else if (command == "delete") {
if (list == true) {
delete_element(NewList);
} else {
cout<<"Error: You did't create a list!"<<endl;
}
} else if (command == "deletelist") {
if (list == true) {
delete_all_list(NewList);
cout<<"Done!"<<endl;
list = false;
} else {
cout<<"Error: You did't create a list!"<<endl;
}
} else if (command == "addextra") {
if (list == true) {
add_extra_struct_to_list(NewList);
} else {
cout<<"Error: You did't create a list!"<<endl;
}
} else if (command == "exit") {
if (list == true) {
delete_all_list(NewList);
cout<<"Done!"<<endl;
}
break;
} else {
cout<<"Error: There is no such command!"<<endl;
}
cout<<endl;
}
return 0;
}
You have quite a few issues in your program, in the delete_element function your main problem is that you dereference prevs and nexts without checking whether they are NULL.
Adding some simple checks:
if (nexts && prevs)
prevs->next = nexts;
if (prevs && nexts)
nexts->prev = prevs;
Prevents it from segfaulting if any elements are NULL.
Other issues I have found I commented in the live example.
It looks suspicious that count starts from 1 instead 0 in delete_element. Because of this, the first index that your code is able to delete is 2 and you get into trouble if try to delete node 1.
EDIT: And one more thing: deleting the first node and last node needs some special care. For the first node, prev is 0 so you can not say prev->next.