Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 1 year ago.
Improve this question
Whenever I try to launch the program it tells me this:
"Microsoft Visual Studio
There were build errors. Would you like to continue and run the last successful build?"
The assignment that this code is based on:
Create a data structure called “Staque” which can store only integers. The way Staque works is as follows:
If the number that you are trying to store in the Staque is even, it is pushed in front of the Staque
If the number that you are trying to store in the Staque is odd, it is pushed at the end of the Staque
When you try to remove a number from the Staque, you always do it from either the front or from the back of the Staque following the LIFO rule.
Write a C++ code to implement a Staque. Since the data structure is all about inserting and deleting numbers, it would be a good option to use a linked list to implement Staque. Here’s how your user interface should like:
Insert the numbers 1, 3, 2, 4, 6, 8 9 in the Staque.
Display the Staque: This is how the Staque will look like given that the above numbers were pushed in the Staque in the order given above: (front) 8 6 4 2 1 3 9 (back)
Delete 2 even numbers and 1 odd number from the Staque and then display the Staque:
Since deletion always follows the LIFO order, the numbers to be removed are 8 first and then 6(the 2 even numbers) and 9(odd) from the back of the Staque. The Staque shall then look like: (front) 4 2 1 3 (back).
Run you program for at least 3 different input series & corresponding 3 different removal series.
Here is my code:
'
#include<iostream>
#include<cstdlib>
using namespace std;
struct node {
int info;
struct node* next;
};
class Staque {
private:
struct node* head;
int size;
public:
struct node* createNewNode(int);
void insertAtFront(int);
void insertAtLast(int);
void deleteFromFront();
void deleteFromLast();
void displayList();
Staque() {
head = NULL;
size = 0;
}
};
struct node* Staque::createNewNode(int value) {
struct node* temp;
temp = new(struct node);
temp->info = value;
temp->next = NULL;
return temp;
}
void Staque::insertAtFront(int value) {
struct node* temp, * p;
temp = createNewNode(value);
if (head == NULL) {
head = temp;
head->next = NULL;
}
else {
p = head;
head = temp;
head->next = p;
}
cout << "\nElement inserted at front successfully.";
size++;
}
void Staque::insertAtLast(int value) {
struct node* temp, * s;
temp = createNewNode(value);
if (head == NULL) {
head = temp;
head->next = NULL;
}
else {
s = head;
while (s->next != NULL) {
s = s->next;
}
temp->next = NULL;
s->next = temp;
}
cout << "\nElement inserted at end successfully.";
size++;
}
void Staque::deleteFromFront() {
if (size == 0)
return;
struct node* s;
s = head;
if (head == NULL) {
cout << "\nThe staque is Empty";
return;
}
if (s->info % 2 == 0) {
head = head->next;
free(s);
size--;
cout << "\nEven element deleted.";
if (size == 0)
head = NULL;
}
}
void Staque::deleteFromLast() {
if (size == 0)
return;
struct node* s, * temp;
s = head;
if (head == NULL) {
cout << "\nThe staque is Empty";
return;
}
while (s->next != NULL) {
temp = s;
s = s->next;
}
if (s->info % 2 != 0) {
temp->next = NULL;
free(s);
size--;
cout << "\nOdd element deleted";
if (size == 0)
head = NULL;
}
}
void Staque::displayList() {
struct node* temp;
if (head == NULL) {
cout << "\nThe staque is Empty";
return;
}
temp = head;
cout << "\nElements of staque are: ";
while (temp != NULL) {
cout << temp->info << " ";
temp = temp->next;
}
cout << endl;
}
//main function
int main() {
int choice, value;
Staque sq;
while (1) {
cout << endl << "\nMenu:";
cout << "\n1.Insert ";
cout << "\n2.Delete even number";
cout << "\n3.Delete odd number";
cout << "\n4.Display staque";
cout << "\n5.Exit " << endl;
cout << "\nEnter choice : ";
cin >> choice;
switch (choice) {
case 1:
cout << "\nEnter integer to insert: ";
cin >> value;
if (value % 2 != 0) {
sq.insertAtLast(value);
}
else {
sq.insertAtFront(value);
}
break;
case 2:
sq.deleteFromFront();
break;
case 3:
sq.deleteFromLast();
break;
case 4:
sq.displayList();
break;
case 5:
exit(0);
}
}
return 0;
}
'
error message from the output:
error C4703: potentially uninitialized local pointer variable 'temp' used
1>Done building project "Staque.vcxproj" -- FAILED.
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
Replace
while (s->next != NULL) {
temp = s;
s = s->next;
}
with
do {
temp = s;
s = s->next;
} while (s != nullptr);
Otherwise Staque::deleteFromLast() can't delete an odd element if it is a single element in the list. Moreover temp is left uninitialized.
Related
#include <iostream>
#include <cstdlib>
using namespace std;
struct node
{
int data;
struct node* link;
};
struct node* front;
struct node* rear;
void insert()
{
struct node*temp;
temp = (struct node*)malloc(sizeof(struct node));
cin >> temp->data;
if (front == NULL)
{
front = rear = temp;
}
else
{
rear->link = temp;
rear = rear->link;
}
rear->link = front;
}
void del()
{
struct node* temp;
temp = front;
if (front == NULL)
cout << "Underflow";
else
{
front = front->link;
free(temp);
}
rear->link = front;
}
void disp()
{
struct node* temp;
temp = front;
if (front == NULL)
cout << "Empty";
else
{
do
{
cout << temp->data << "->";
temp = temp->link;
} while (temp != front);
}
rear->link = front;
}
int main()
{
int n;
bool run = true;
while (run)
{
cin >> n;
switch (n)
{
case 1:
insert();
break;
case 2:
del();
break;
case 3:
disp();
break;
case 4:
run = false;
break;
}
}
return 0;
}
I am new to the concept.I wrote a code for insertion deletion and display of elements using queue implementing the concept of linked list..The program is working fine without any errors . But when the output is displayed . I need to display the output along with the first element I inserted..E.g: My input is
1
2
1
3
1
4
3
The output is 2->3->4->
but the output I need is 2->3->4->2->
I want to see the first element again at the last
All you have to do is just adding a single line after the do-while loop as follows:
do
{
cout << temp->data << "->";
temp = temp->link;
} while (temp != front);
cout<< front->data << "->";
assuming front is the head of your linked-list. Now I've a question for you, what you gonna do if there is a single entry? Since it is going to be displayed twice.
Simple enough, change this
do
{
cout<<temp->data<<"->";
temp=temp->link;
}
while(temp!=front);
to this
int first = temp->data;
do
{
cout<<temp->data<<"->";
temp=temp->link;
}
while(temp!=front);
cout<<first<<"->"; // print first element again
I tried implementing Linked List using C++ using a structure.
I've included three functions - Size, Insertion and Deletion from the end.
The program compiled successfully. During execution, when I tried to give input for the LLInsert() function, there was just a cursor blinking on my execution window. I don't know if the function returned to main.
Also the LLSize() doesn't return 0 when I try to find the Size of a empty list.
I can't seem to figure out what I'm doing wrong. Here is my code.
#include<iostream>
using namespace std;
struct LL {
LL *next = NULL;
int data;
};
int LLSize(LL *head) {
LL *current = new LL;
current = head;
int count = 0;
while(current != NULL) {
current = current -> next;
count ++;
}
return count;
}
void LLInsert(LL *head,int value) {
LL *current = new LL;
current = head;
LL *Newnode = new LL;
Newnode -> data = value;
Newnode -> next = NULL;
if(head == NULL) {
head = Newnode;
return;
}
while(current->next != NULL) {
current = current->next;
}
current->next = Newnode;
return;
}
int LLDelete(LL *head) {
LL *current = new LL;
current = head;
int deleteddata;
while(current->next->next != NULL) {
current = current->next;
}
current->next->data = deleteddata;
current->next = NULL;
return deleteddata;
}
int main() {
int choice;
LL *A;
while(1) {
cout << "1. Size\n2. Insert\n3. Delete\n4. Exit" << endl;
cout << "Enter a choice : ";
cin >> choice;
switch(choice) {
case 1 : {
cout << "\nLength = " << LLSize(A) << endl;
break;
}
case 2 : {
int value;
cout << "\nEnter the element to insert : ";
cin >> value;
LLInsert(A,value);
break;
}
case 3 : {
cout << LLDelete(A);
break;
}
case 4 : {
exit(0);
}
default : {
cout << "\nInvalid choice. Enter a valid choice " << endl;
break;
}
}
}
}
Don't use using namespace.
Create a type for the list and a type for the nodes
struct LL {
LL* next;
int data;
};
struct L {
LL* head;
};
Use references and don't allocate new memory in each function
int LLSize(L& list) {
LL *current = list.head;
Check if the head of the list is set and use nullptr
if (list.head == nullptr) {
Use an instance of the list and not a pointer
int main() {
int choice;
L A;
Use a debugger like gdb to analyze your program.
Clean up at the end. Delete memory you allocated with new. One delete for each new.
This is my code:
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
struct node
{
string program;
node *next;
}
bool isEmpty(node *head)
{
if (head == NULL)
return true;
else
return false;
}
void insertAsFirstElement(node *&head, node *&tail, string program)
{
node *temp = new node;
temp->program = program;
temp->next = NULL;
head = temp;
tail = temp;
}
void initialize(node *&head, node *&tail, string program)
{
if (isEmpty(head))
insertAsFirstElement(head, tail, program);
else
{
node* temp = new node;
temp->program = program;
temp->next = NULL;
tail->next = temp;
tail = temp;
}
}
void insert(node *& head, node *& tail, string program, int num)
{
if (isEmpty(head))
insertAsFirstElement(head, tail, program);
else
{
string free ("FREE");
int i = 0;
while (head != NULL)
{
while (head->program.compare(free) != 0)
head = head->next;
while (head->program.compare(free) == 0)
{
head->program = program;
tail->next = head;
tail = head;
i++;
if (i == (num-1))
return;
}
}
}
}
void showList(node *current)
{
if (isEmpty(current))
cout << "The list is empty. \n";
else
{
int i = 0;
cout << "The list contains: \n";
while(current != NULL)
{
cout << current->program << " ";
if ((i + 1) % 8 == 0)
cout << "\n";
current = current->next;
i++;
}
}
}
int main()
{
cout << "Menu";
cout << "\n1. Add program\n";
cout << "2. Print Memory\n";
cout << "3. Exit\n";
node *head = NULL;
node *tail = NULL;
int choice;
string name;
int memory;
int numPages;
for (int i = 0; i <= 31; i++)
{
initialize(head, tail, "FREE");
}
showList(head);
do
{
cout << "choice - ";
cin >> choice;
switch (choice)
{
case 1:
cout << "Program name - ";
cin >> name;
cout << "Program size - ";
cin >> memory;
if (memory % 4 == 0)
numPages = memory / 4;
else if (memory % 4 != 0)
numPages = memory / 4 + 1;
insert(head, tail, name, numPages);
cout << "Program " << name << " added succesfully.\n";
case 2:
showList(head);
}
} while (choice!=3);
return 0;
}
The error is in the insert function because when I try printing the linked list after I call the insert function it never stops printing, but I don't understand my mistake.
Also in the switch in the main when insert 2 as choice it only runs case 2, but when I insert 1 as choice it runs both case 1 and case 2.
EDIT: I haven't changed anything and now once I call the insert function the program stops running
Regarding switch case, you need to add break; after case 1:
"The error is in the insert function"
So why do you not fix it?
I agree, that your insert function is flawed. Below I have marked 3 lines that probably contribute to the code's problems.
Key Idea: When inserting the second and subsequent items to a linked list, your code should modify only 'head' or 'tail', never both.
When inserting at the head, the tail should not change.
When inserting at the tail, the head should not change.
vv vv
void insert(node *& head, node *& tail, string program, int num)
{
if (isEmpty(head))
insertAsFirstElement(head, tail, program);
else
{
string free ("FREE");
int i = 0;
while (head != NULL)
{
while (head->program.compare(free) != 0)
head = head->next; <<<<<<<<<<<<<<<<<<<<<
while (head->program.compare(free) == 0)
{
head->program = program; <<<<<<<<<<<<<<<<<<<<
tail->next = head;
tail = head; <<<<<<<<<<<<<<<<<<<<
i++;
if (i == (num-1))
return;
}
}
}
}
Your switch statement is missing a break; statement. Since there is no break statement for case 1, the compiler continues through case 1 and 2, since case 2 follows case 1.
Here is a more clear description from Tutorialspoint:
When the variable being switched on is equal to a case, the statements following that case will execute until a break statement is reached.
When a break statement is reached, the switch terminates, and the flow of control jumps to the next line following the switch statement.
Not every case needs to contain a break. If no break appears, the flow of control will fall through to subsequent cases until a break is reached.
See this code:
switch (choice)
{
case 1:
// ... Add the rest of your code here
break // <-- this is required so that the switch is termintated after completing the appropriate case instead of continuing on to the next case
case 2:
showList(head); // there are no more cases after this, so only this case runs if switch(2) occurs.
}
The code bellow inserts nodes correctly but
I have a problem that when try to print the list the program unfortunately stop working.
The error message is : your project has stopped working.
This is my code:
#include <iostream>
#include <string>
using namespace std;
typedef struct st {
string data;
int ISBN;
string Title;
string Author;
int publishedyear;
bool borrow;
st* next;
} NODE;
NODE* add(NODE* head, int isbn)
{
NODE *p1, *p2;
NODE* n;
n = new NODE;
n->ISBN = isbn;
if (head == NULL) {
head = n;
return head;
}
if (n->ISBN < head->ISBN) {
n->next = head;
head = n;
return head;
}
p1 = p2 = head;
while (p2 != NULL) {
if (n->ISBN < p2->ISBN) {
n->next = p2;
p1->next = n;
return head;
}
else {
p1 = p2;
p2 = p2->next;
}
}
n->next = p2;
p1->next = n;
return head;
}
void print(NODE* head)
{
NODE* p;
p = head;
if (head == NULL) {
cout << "empty list" << endl;
}
while (p != NULL) {
cout << "Book ISBN Is : " << p->ISBN << endl;
p = p->next;
}
}
void main()
{
// cout << "hi";
NODE* head;
head = NULL;
string op;
int isbn;
cout << "Enter the opertion in the following format : op , ISBN" << endl;
while (1) {
cin >> op;
if (op == "add") {
cin >> isbn;
if (op == "add") {
head = add(head, isbn);
cout << "book with thie ISBN code " << isbn << " is added successfuly."
<< endl;
}
}
else if (op == "print") {
print(head);
}
else {
cout << "Enter vaild operation! ." << endl;
}
}
}
any suggestions ?
The answer was pointed out, but... I feel awfully unsatisfied by the state of your code, so allow me to give you a few tips.
Note: unless the point is to build a list, do reuse the existing standard containers (vector, in particular) and algorithms (sort) rather than building your own.
Let's start with the basics, this is the year 2016 you should have access to C++11 by now.
C++11 allows to initialize data-members straight at the point of declaration, and I recommend that you do it for all built-in types (integrals, booleans, floating points and pointers) since by default they otherwise contain garbage which is puzzling.
struct Node {
std::string data;
int ISBN = 0;
std::string title;
std::string author;
int publishedyear = 0;
bool borrow = false;
Node* next = nullptr;
};
Note that this alone solves your bug. And it also avoids forgetting it the next time.
Secondly, the add method should NOT be responsible for creating a node. This is mixing concerns, and it also leaves most of the node with default values and no way to access it without looking for it by its ISBN.
There's also a point that the add method does not account for: what if the ISBN is already in the list?
// Adds the new node to the list, maintaining the ordering by ISBN.
//
// Returns the new head of the list, unless an existing node in the list already
// has this ISBN in which case returns `nullptr`.
Node* add(Node* head, Node* node) {
assert(node != nullptr && "Null argument provided");
if (head == nullptr) {
return node;
}
if (node->ISBN < head->ISBN) {
node->next = head;
return node;
}
if (node->ISBN == head->ISBN) {
return nullptr;
}
// Find "current" such that "current->ISBN" < "node->ISBN" and
// "node->ISBN" <= "current->next->ISBN"
Node* current = head;
while (current->next != nullptr && node->ISBN > current->next->ISBN) {
current = current->next;
}
if (node->ISBN == current->next->ISBN) {
return nullptr;
}
node->next = current->next;
current->next = node;
return head;
}
Note: assert requires #include <cassert>.
Your print method is already pretty good, congratz!
Just two nitpicks:
if you know that nothing further will be executed, return immediately, don't wait
don't use endl, it both appends an end of line AND flushes the buffer immediately, which leads to performance issues more often than not
// Prints the list, in order.
void print(Node* head) {
if (head == nullptr) {
std::cout << "empty list\n";
return;
}
for (Node* p = head; p != nullptr; p = p->next) {
std::cout << "Book ISBN: " << p->ISBN << "\n";
}
}
And finally, the modified main.
Note that I expanded the help text a bit, and provided a (clean) quit operation.
The main change, however, is dealing without input error. Dealing with output error is left as an exercise to the reader (hint: make them throw).
It would also be a good exercise to properly deal with the allocated memory.
int main() {
std::cout << "Enter one of the following operations when prompted:\n"
" - add <isbn>\n"
" - print\n"
" - quit\n";
Node* head = nullptr;
while (1) {
std::cout << "> ";
std::string op;
if (!(std::cin >> op)) {
std::cerr << "An error occurred reading the operation, sorry\n";
break;
}
if (op == "quit") {
std::cout << "See you later!\n";
break;
}
if (op == "print") {
print(head);
continue;
}
if (op == "add") {
int isbn = 0;
if (!(std::cin >> isbn)) {
std::cout << "Please provide a correct ISBN!\n";
continue;
}
Node* node = new Node();
node->ISBN = isbn;
Node* h = add(head, node);
if (h == nullptr) {
std::cout << "This ISBN was already provided!\n";
delete node;
continue;
}
head = h;
continue;
}
std::cout << "Please enter a valid operation!\n";
}
// Deal with allocated memory ;)
}
st::next is never set to NULL. This makes testing p!=NULL in print somewhat problematic.
Solution: NULL next when the node is the tail node.
#include <iostream>
using namespace std;
struct node {
int item;
node* l;
node* r;
node (int x) {
item = x;
l = 0;
r = 0;
}
node(int x, node* l, node* r) {
item = x;
this->l = l;
this->r = r;
}
};
typedef node* link;
class QUEUE {
private:
link* q;
int N;
int head;
int tail;
public:
QUEUE(int maxN) {
q = new link[maxN + 1];
N = maxN + 1;
head = N;
tail = 0;
}
int empty() const {
return head % N == tail;
}
void put(link item) {
q[tail++] = item;
tail = tail % N;
}
link get() {
head = head % N;
return q[head++];
}
};
link head = 0; // Initial head of the tree
link find(int x) {
if (head == 0) {
cout << "\nEmpty Tree\n";
return 0;
}
link temp = head;
// To find the node with the value x and return its link
QUEUE q(100);
q.put(temp);
while (!q.empty()) {
temp = q.get();
if (temp->item == x) {
return temp;
}
if (temp->l != 0) q.put(temp->l);
if (temp->r != 0) q.put(temp->r);
}
return 0;
}
void print(link temp) {
QUEUE q(100);
q.put(temp);
while (!q.empty()) {
temp = q.get();
cout << temp->item << ", ";
if (temp->l != 0) q.put(temp->l);
if (temp->r != 0) q.put(temp->r);
}
}
void deleteAll(link h) {
// This deletes the entire binary tree
QUEUE q(100);
q.put(h);
while (!q.empty()) {
h = q.get();
if (h->l != 0) q.put(h->l);
if (h->r != 0) q.put(h->r);
delete h;
}
}
int main() {
link temp = 0;
char c;
int n1, n2;
cout << "\n\nPlease enter the input instructions (X to exit program) : \n\n";
do {
cin >> c;
switch (c) {
case 'C': cin >> n1;
if (head == 0) {
head = new node(n1);
cout << "\nRoot node with item " << n1 << " has been created\n\n";
} else {
cout << "\nError: Tree is not empty\n\n";
}
break;
case 'L': cin >> n1 >> n2;
temp = find(n1);
if (temp != 0) {
if (temp->l == 0) {
temp->l = new node(n2);
cout << "\nNode with item " << n2 << " has been added\n\n";
}
else {
cout << "\nError: The specified node already has a left child\n\n";
}
}
else {
cout << "\nError: The specified node doesn't exist\n\n";
}
break;
case 'R': cin >> n1 >> n2;
temp = find(n1);
if (temp != 0) {
if (temp->r == 0) {
temp->r = new node(n2);
cout << "\nNode with item " << n2 << " has been added\n\n";
}
else {
cout << "\nError: The specified node already has a right child\n\n";
}
}
else {
cout << "\nError: The specified node doesn't exist\n\n";
}
break;
case 'P': cin >> n1;
temp = find(n1);
if (head != 0) {
cout << "\nLevel-order traversal of the entire tree: ";
print(temp);
}
else {
cout << "\nError: No elements to print\n\n";
}
break;
case 'D': cin >> n1;
temp = find(n1);
deleteAll(temp);
temp = 0;
break;
case 'X': cout << "\nExiting Program\n\n";
break;
default: cout << "\nInvalid input entered. Try again.\n\n";
}
} while (c != 'X');
system("pause");
return 0;
}
Sample Input:
C 9
L 9 8
R 9 6
L 8 3
R 8 5
R 6 2
L 3 4
L 4 10
L 5 1
R 5 11
L 1 12
R 1 7
It all works fine until I delete a subtree and print when it prints garbage value before crashing. Please help me figure out the bug because I've been trying in vain for hours now.
It all works fine until I delete a subtree and print when it prints garbage value before crashing. Please help me figure out the bug because I've been trying in vain for hours now.
Try the recursive function:
void Delete(link h)
{
if(h)
{
if(h->l) Delete(h->l);
if(h->r) Delete(h->r);
delete(h);
}
}
When you delete a node, you call deleteAll(temp) which deletes temp, but it doesn't remove the pointer value from the l or r of temp's parent node.
This leaves you with a invalid pointer, causing garbage printing and crashing.
Unfortunately, the way your find works currently, you don't know what the current temp node's parent is when you get around to checking its value.
One way to fix it is to have a different type of find (called something like remove) that looks in l and r at each iteration for the value and sets l or r to NULL before returning the pointer. You might have to have a special case for when the value is found in the root.
Edit (sample code added):
I am assuming you are not using recursion for some reason, so my code uses your existing queue based code. I only changed enough to get it working.
findAndUnlink find the node with the value given and "unlinks" it from the tree. It returns the node found, giving you a completely separate tree. Note: it is up to the caller to free up the returned tree, otherwise you will leak memory.
This is a drop in replacement for find in your existing code, as your existing code then calls deleteAll on the returned node.
link findAndUnlink(int x) {
if (head == 0) {
cout << "\nEmpty Tree\n";
return 0;
}
link temp = head;
if (temp->item == x) {
// remove whole tree
head = NULL;
return temp;
}
// To find the node with the value x and remove it from the tree and return its link
QUEUE q(100);
q.put(temp);
while (!q.empty()) {
temp = q.get();
if (temp->l != NULL) {
if (temp->l->item == x) {
link returnLink = temp->l;
temp->l = NULL;
return returnLink;
}
q.put(temp->l);
}
if (temp->r != NULL) {
if (temp->r->item == x) {
link returnLink = temp->r;
temp->r = NULL;
return returnLink;
}
q.put(temp->r);
}
}
return 0;
}