Seg Fault at return statement in function - c++

My program is supposed to convert a prompt from infix to postfix. So far, through a debugger and various other methods, I have located the exact point at which I segfault, but don't understand why.
Here's my code:
Here's itop.h:
using namespace std;
#include <cstdlib>
#include <iostream>
class sNode{
public:
char data;
sNode *next;
};
class stack{
public:
sNode *head;
void push (char);
sNode pop();
int rank(char);
stack()
{
cout << "Initiliazing stack." << endl;
}
};
This is my itop.cpp file:
#include "itop.h"
void stack::push (char a)
{
// cout << "Pushing " << a << endl;
sNode *sn;
sn = new sNode;
sn->data = a;
sn->next = head;
head = sn;
}
sNode stack::pop()
{
// cout << "Popping stack." << endl;
sNode *sn;
sn = head;
head = head->next;
return *sn;
}
int stack::rank(char x)
{
int num = 0;
// cout << "Checking rank." << endl;
if(x == '\0')
{
num = 1;
// cout << "Checking for null" << endl;
return num;
}
else if(x == '+' || x == '-')
{
num = 2;
// cout << "Checking if + or -" << endl;
return num;
// cout << "After return." << endl;
}
else if(x == '*' || x == '/')
{
num = 3;
// cout << "Checking for * or /" << endl;
return num;
}
else
cout << "Error! Input not valid!" << endl;
}
And here's main.cpp:
using namespace std;
#include <iostream>
#include <cstdlib>
#include <cstring>
#include "itop.h"
int main()
{
char *temp1; //Instantiating variables.
char *temp2;
temp1 = new char[20];
temp2 = new char [20];
stack s;
do //Checking commands.
{
cout << "infix_to_postfix> ";
cin >> temp1;
if(strcmp(temp1, "quit") == 0)
{
return 0;
}
if(strcmp(temp1, "convert") != 0)
{
cout << "Error! Invalid command." << endl;
}
cin >> temp2;
if(strcmp(temp1, "convert") == 0)
{
for(int i=0; i<sizeof(temp2); i++)
{
if(isdigit(temp2[i]))
{
cout << atoi(&temp2[i]);
}
else if(s.rank(temp2[i]) < s.rank(s.head->data))
{
sNode temp = s.pop();
cout << temp.data;
}
else
{
s.push(temp2[i]);
}
}
}
else
{
cout << "Error! Command not supported." << endl;
}
}while(strcmp(temp1, "quit") != 0);
return 0;
}
The function is called at
else if(s.rank(temp2[i]) < s.rank(s.head->data))
And the problem is in here:
else if(x == '+' || x == '-')
{
num = 2;
// cout << "Checking if + or -" << endl;
return num;
// cout << "After return." << endl;
}
Specifically right before return num, I get "Segmentation fault (core dumped)" error message. I have used gdb and all I know is that right after "Checking if + or -" I see "$1 = 2". I'm not quite sure what that means, but it is what I want to return.
Thank you for your help.

There are many mistakes in your code. Your stack implementation is wrong. push() for example only sets head over and over again. This results in your stack class being able to ever only hold one element. next is never set to anything, so it contains random garbage. Further down, you have this:
for(int i=0; i<sizeof(temp2); i++)
sizeof(temp2) does not give you the amount of characters of the string temp2 points to. It gives you the size of the pointer temp2 itself. Furthermore, you end up reading s.head from an empty stack, which will be a pointer to random garbage. At that point, all bets are off of course. You can't expect anything else than a crash and burn.

Fix 1:Write a proper constructor.
stack()
{
head=NULL;
cout << "Initiliazing stack." << endl;
}
Fix 2:Write an extra method to check if stack is empty.
int stack::empty()
{
if(head == NULL)
return true;
else
return false;
}
Fix 3:Check if stack empty before using the stack data.
else if(!s.empty() && s.rank(temp2[i]) < s.rank(s.head->data))
{
...
}
Fix 4: Fix the rest of the code logic.

Related

separating C++ code in to multiple files

I hope you are all doing well.
I have the below code which manages a printing queue. I need to separate it into the below files and I dont know how to this. Oddly i've never been asked to do this. Any help you can provide would be greatly appreciated. I am not sure what code goes in which file.
Files I need to separate my code into:
1. heap.h - declaration file for heap.
2. heap.cpp - implementation file for heap.
3. pqtype.h - declaration file for priority queue.
4. pqtype.cpp - implementation file for priority queue.
5. test.cpp - driver file.
My current Code:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <string>
using namespace std;
struct node
{
int priority;
int jNum;
string jName;
struct node *next;
};
class PriorityQueue
{
private:
node *front;
public:
PriorityQueue()
{
front = NULL;
}
void addJob(string item, int priority, int number)
{
node *temp, *q;
temp = new node;
temp->jName = item;
temp->priority = priority;
temp->jNum = number;
//whether queue is empty
if (front == NULL || priority < front->priority)
{
temp->next = front;
front = temp;
}
else
{
q = front;
while (q->next != NULL && q->next->priority <= priority)
q = q->next;
temp->next = q->next;
q->next = temp;
}
}
void printJob()
{
node *temp;
if (front == NULL)
cout << "There Are No Print Requests In The Queue.\n";
else
{
temp = front;
cout << "\nNow printing Request # " << temp->jNum << " " <<"For "<< temp->jName <<"\n"<< endl;
front = front->next;
free(temp);
}
}
void viewJob()
{
node *ptr;
ptr = front;
if (front == NULL)
cout << "There Are No Print Requests In The Queue\n\n";
else
{
while (ptr != NULL)
{
cout << "Job #: " << ptr->jNum << " " <<"For "<< ptr->jName <<"\n"<< endl;
ptr = ptr->next;
}
}
}
};
int main()
{
int choice, priority;
PriorityQueue pq;
char ch;
string jName;
int number = 0;
cout << "Printing Queue\n" << endl;
do
{
cout << "==============" << endl;
cout << "1. Add Job\n";
cout << "2. Print Job\n";
cout << "3. View Job\n";
cout << "4. Exit\n";
cout << "\nEnter Your Option Now : ";
cin >> choice;
switch (choice)
{
case 1:
cout << "Are You A Student (s or S), TA (t or T), Or Instructor (i or I)? ";
cin >> ch;
if (ch == 'i' || ch == 'I')
{
priority = 1;
jName = "Instructor";
cout << "\nJob Successfully Entered.\n\n";
}
else if (ch == 't' || ch == 'T')
{
priority = 2;
jName = "TA";
cout << "\nJob Successfully Entered.\n\n";
}
else if (ch == 's' || ch == 'S')
{
priority = 3;
jName = "Student";
cout << "\nJob Successfully Entered.\n\n";
}
number++;
pq.addJob(jName, priority, number);
break;
case 2:
pq.printJob();
break;
case 3:
pq.viewJob();
break;
case 4:
cout << "\nThank You For Using Printint Queue\nProgram Now Closing...\n\n";
break;
default:
cout << "\nInvalid Choice Selected! \n";
}
}
while (choice != 4);
system("PAUSE");
return 0;
}

Better way to code linked list?

I wrote this Linked List code and I am not able to create a single linked list since the value pointed by memory location of nodeValue in main function keep changing which in turn changes the head and tail value. I solved this by creating a Node object array((like nodeValue[5]) and passing the value, but this limits to 5 values. Is there a way to efficient way to code this without using a array of objects?
#include<iostream>
#include<string>
using namespace std;
class Node
{
public:
int value;
Node *nextNodePointer;
};
class linkedList
{
private:
int count = 0;
public:
Node *Head;
Node *Tail;
void AddNodeAfter(Node *);
//void removeNodeAfter(Node *);
void displayValues();
};
void linkedList::AddNodeAfter(Node *temp)
{
if (this->count == 0)
{
Head = temp;
Tail = temp;
count++;
}
else
{
Tail->nextNodePointer = temp;
Tail = temp;
count++;
}
}
Node createNodeObjects()
{
cout<< endl << "Enter integer value :";
Node temp;
cin >> temp.value;
temp.nextNodePointer = NULL;
return temp;
}
void linkedList::displayValues()
{
if (count == 0)
{
cout << endl << "Nothing to display";
}
else
{
Node value;
value = *Head;
for (int i = 1; i <= count; i++)
{
cout << endl << "Value: " << value.value;
value = *value.nextNodePointer;
}
}
}
int main()
{
cout << "Creating basic linked list" << endl;
linkedList LinkedList;
Node nodeValue;
while (1)
{
cout << endl << "Do you want to add a value to Node ?<Y/N> : ";
char choice;
cin >> choice;
if (choice == 'Y')
{
nodeValue = createNodeObjects();
LinkedList.AddNodeAfter(&nodeValue);
}
else
if (choice == 'N')
{
LinkedList.displayValues();
break;
}
else
cout << "Wrong choice" << endl;
}
}
In C++ , you can use list library ...
http://www.cplusplus.com/reference/list/list/

Error in my c++ code using linkedlist "Stop working" [closed]

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 7 years ago.
Improve this question
my code stop working in that test case, i think that the error in function Checktables but i'm not sure and i can't fix the error please help me to tun this code correctly.
image of a test case and the error
this is a cpp file with main .cpp
#include"Header.h"
string Name;
string namess;
customer::customer()
{
name = "";
gsize = status = 0;
next = NULL;
}
customer::customer(string name1, int gsize1, int status1)
{
name = name1;
gsize = gsize1;
status = status1;
next = NULL;
}
waitinglist::waitinglist()
{
chairnum =50 ;
totalcustomers = tables = 0;
head = tail = NULL;
}
waitinglist::waitinglist(int val)
{
chairnum = 50;
totalcustomers = 0;
tables = 0;
head = tail = NULL;
}
void waitinglist::change()
{
customer*temp ;
temp = head;
cout << "enter the name: ";
cin >> namess;
while (temp != NULL)
{
if (namess == temp->name)
{
if (temp->status==2)
{
temp->status=1;
cout << "done! " << endl ;
break ;
}
}
else if (namess != temp->name)
{
temp = temp->next;
}
}
if (temp == NULL)
{
cout << "can't found! " << endl;
}
}
void waitinglist::newcustomer()
{
customer*tmp = new customer;
cout << "enter the name: "; cin >> tmp->name;
customer*tmpo=new customer;
tmpo=head ;
while (tmpo != NULL)
{
if (tmp->name != tmpo->name)
{
tmpo = tmpo->next;
}
else if (tmp->name == tmpo->name)
{
cout<<"The Name already exist! " << endl ;
cout << "enter the name: "; cin >> tmp->name;
tmpo=head;
}
}
cout << "enter the group number: "; cin >> tmp->gsize;
cout << "enter the status: "; cin >> tmp->status;
if (head == NULL) // linkedlist is empty
{
head = tail = tmp;
totalcustomers++;
}
else
{
tail->next = tmp;
tail=tail->next;
totalcustomers++;
}
}
void waitinglist::checktables()
{
float c=5.00;
customer*temp=head;
customer*found;
cout<<"enter number of tables: ";
cin >> tables ;
while (tables>=1 && temp!=NULL)
{
int x;
float y;
y=((temp->gsize)/c);
x=(temp->gsize)/c;
if (tables<y)
{
temp=temp->next;
}
else if (tables>=y)
{
if (x==y)
{
tables=tables-x ; // Correct Table!
cout<<temp->name<<endl;
}
else if (x!=y)
{
tables=tables-(x+1);
cout<<temp->name<<endl;
}
found=temp ;
delete found; // Discard
break ;
}
}
}
void waitinglist::displayall()
{
customer *tmp;
tmp = head;
if (tmp == NULL)
{
cout << "Empty!";
}
while (tmp != NULL)
{
cout << "Name: " << tmp->name <<endl;
cout << "group number: " << tmp->gsize << endl;
tmp = tmp->next;
}
cout << endl;
}
void waitinglist::diplaycustomer()
{
customer*tmp;
tmp = head;
cout << "enter the name: ";
cin >> Name;
while (tmp != NULL)
{
if (Name == tmp->name)
{
cout << "the name : " << tmp->name << endl;
cout << "the group size = " << tmp->gsize << endl;
cout << "the status = " << tmp->status << endl;
break;
}
else if (Name != tmp->name)
{
tmp = tmp->next;
}
}
if (tmp == NULL)
{
cout << "can't found!" << endl;
}
}
int main()
{
int choice;
string name1 = "";
int gsize1 = 0;
int status1 = 0;
waitinglist mylist;
cout << "Note: 1 in status means the customer not here and 2 means the customer is here.\n";
cout << "Select your option.\n\n";
cout << "(1) Add a new Customer.\n";
cout << "(2) Display information based on Name.\n";
cout << "(3) List all Names.\n";
cout << "(4) to change the status. \n" ;
cout << "(5) Check tables by name. \n";
cout << "(6) quit. \n";
do
{
cout << "\n";
cout << "Enter your choice: --> ";
cin >> choice;
if (1 <= choice && choice <= 5)
{
switch (choice)
{
case 1:
mylist.newcustomer();
break;
case 2:
mylist.diplaycustomer();
break;
case 3:
mylist.displayall();
break;
case 4:
mylist.change() ;
break;
case 5 :
mylist.checktables();
break;
default:
cout << "Invalid choice. Enter again.\n\n";
break;
}
}
else if (choice>6)
{
cout << "Invalid choice. Enter again.\n\n";
break;
}
} while (choice != 6);
return 0;
}
and this is the header file .h
#include<iostream>
#include<string>
using namespace std;
class customer
{
public:
string name;
int gsize;
int status;
customer* next;
customer();
customer(string,int,int);
};
class waitinglist
{
public:
int tables; //number of occupied tables
int chairnum;
int totalcustomers;
customer*head,*tail;
waitinglist();
waitinglist(int);
void newcustomer();
void diplaycustomer();
void displayall();
void change () ;
void checktables();
};
One error is that your checktables function corrupts your linked list structure by calling delete on one of the nodes:
found = temp;
delete found; // Discard
What you've just done in those lines above is to have a linked list with a broken (invalid) link in it. Any functions that now traverses the list (like displaytables) will now hit the broken link, and things start to go haywire.
To delete a node from a linked list, you have to not just call delete, but adjust the link in waitinglist that used to point to that deleted node and have it point to the next node after the deleted one.
Think of it like a real chain -- if one of the links in the chain needs to be removed, you have to physically remove it, and hook the link before it to the next good link. You didn't do this step.
I won't write the code for that, but this is what you should have seen much earlier in the development of your program. Better yet would have been to write a singly-linked list class that adds and removes nodes correctly first. Test it, and then once it can add and remove nodes successfully without error, then use it in your larger program.

Why is this function causing a crash? (Multilist)

I'm working on my first multilist and it has been nothing but a nightmare so far. Right now, I am allowing the user to place the x,y spots (class_number,student_number) in on their own. My node looks like this:
typedef struct node {
int student_number;
int class_number;
struct node* classpointer;
struct node* studentpointer;
}* nodePtr;
Initialized with
List::List() {
head = nullptr;
currClass = nullptr;
currStudent = nullptr;
}
To add in the data values and set up pointers I have two functions.
void List::addNodeToClass() {
nodePtr n = new node;
n->classpointer = NULL;
cout << "What class number would you like to add?" << endl;
int x;
cin >> x;
n->class_number = x;
if(head != NULL) {
currClass = head;
while (currClass->classpointer != NULL) {
currClass = currClass->classpointer;
}
currClass->classpointer = n;
}
else {
head = n;
}
}
And
void List::addNodeToStudent() {
nodePtr n = new node;
n->studentpointer = NULL;
cout << "What student number would you like to add?" << endl;
int x;
cin >> x;
n->student_number = x;
if(head != NULL) {
currStudent = head;
while (currStudent->studentpointer != NULL) {
currStudent = currStudent->studentpointer;
}
currStudent->studentpointer = n;
}
else {
head = n;
}
}
I make function calls to both of these functions in my menu() function, and in main() I only call for menu()
int menu() {
int input;
List List;
while (input != 3) {
cout << " " << endl;
cout << "Press '1' to input a node" << endl;
cout << "Press '2' to view the list of nodes" << endl;
cout << "Press '3' to exit" << endl;
cout << " " << endl;
cin >> input;
if (input == 1) {
List.addNodeToClass();
List.addNodeToStudent();
}
else if (input == 2) {
List.PrintList();
}
else if (input == 3) {
return 0;
}
else {
cout <<"That is an invalid key" << endl;
}
}
}
When I run the program I am able to input the class node, then when I go to enter the student node, after hitting enter the program crashes. I know that there is a lot to look through, but I can't understand why it is. If someone would be able to tell me what I am doing wrong here I would greatly appreciate it. Thank you.
The addNodeToClass function never sets node->studentpointer. So when you follow that pointer in addNodeToStudent, you are dereferencing garbage.
Your code would be safer with a default node constructor:
typedef struct node {
node()
{
student_number = 0;
class_number = 0;
classpointer = nullptr;
studentpointer = nullptr;
}
int student_number;
int class_number;
struct node* classpointer;
struct node* studentpointer;
}* nodePtr;
And this would fix your issue because those attributes are not always initialized in your code (new node does not initialize the node attributes if there is no such constructor).

Segfault with initializing an int

/*Matt Boler
meb0054
hw5.cpp
Compile with gcc in cygwin
*/
#import <iostream>
#import <string>
#import <sstream>
#import <cstdlib>
#import <climits>
#import <assert.h>
using namespace std;
//#define UNIT_TESTING
struct TriviaNode
{
string question;
string answer;
int points;
TriviaNode *next;
};
typedef TriviaNode* NodePtr;
//Input: (1) root is the linked list to be added to
// (2) Question is the question for the node to ask
// (3) Answer is the answer to the node's question
// (4) Points is the point value of the node
//This adds a node to the end of the list
void appendNode(NodePtr& root, string question, string answer, int points);
//Input: (1) root is the linked list to get the length of
//Output: Returns the number of nodes in the linked list
//This calculates the number of nodes in a list
int getListLength(NodePtr& root);
//Input: (1) root is the node to start the list from
//This generates a hardcoded trivia list with 3 predefined questions and answers
void generateHardCodedList(NodePtr& root);
//Input: (1) root is the linked list containing questions to be asked
// (2) numQuestions is the number of questions to be asked from the list
//Output: returns o if answered correctly and 1 if answered incorrectly
//This asks the user a question
int askQuestion(NodePtr& root, int numQuestions);
int main()
{
#ifdef UNIT_TESTING
NodePtr head;
cout << "*** This is a debugging version ***" << endl;
cout << "Unit Test Case 1: Ask no questions. The program should give a warning" <<endl;
askQuestion(head, 0);
cout << "Test Case passed..." << endl;
generateHardCodedList(head);
cout << "Unit Test Case 2.1: Ask one question. The tester enters an incorrect answer" << endl;
assert(askQuestion(head, 1) == 1);
cout << "Test Case passed..." << endl;
cout << "Unit Test Case 2.2: Ask one question. The tester enters a correct answer" << endl;
assert(askQuestion(head, 1) == 0);
cout << "Test Case passed..." << endl;
cout << "Unit Test Case 3.1: Ask all questions. The tester enters incorreect answers" << endl;
assert(askQuestion(head, 1) == 1);
assert(askQuestion(head, 2) == 1);
assert(askQuestion(head, 3) == 1);
cout << "Test Case passed..." << endl;
cout << "Unit Test Case 3.2: Ask all questions. The tester enters correect answers" << endl;
assert(askQuestion(head, 1) == 0);
assert(askQuestion(head, 2) == 0);
assert(askQuestion(head, 3) == 0);
cout << "Test Case passed..." << endl;
cout << "Unit Test Case 4: Ask 5 questions in the linked list" << endl;
askQuestion(head, 5);
cout << "*** END OF THE DEBUGGING VERSION ***" << endl;
#else
{
cout << "Welcome to Matt Boler's Trivia Quiz Game!" << endl;
string userContinue = "";
string no = "No";
NodePtr head;
int numQuestions = 3;
generateHardCodedList(head);
while(userContinue.compare(no) != 0)
{
string question, answer;
int score;
cout << "Enter a question:";
getline(cin, question);
cout << "Enter an answer:";
getline(cin, answer);
cout << "Enter award points:";
cin >> score;
cin.clear();
cin.ignore(INT_MAX, '\n');
cout << "Continue? (Yes/No)" << endl;
getline(cin, userContinue);
numQuestions++;
}
//ANYTHING PAST HERE IN THE ELSE BLOCK FAILS VIA SEGFAULT OR JUST NOT RUNNING. NO IDEA WHY
int score = 0;
NodePtr cur = head;
for(int x = 1; x < numQuestions; x++)
{
cur = cur->next;
if(askQuestion(head, x) == 0)
{
score += cur-> points;
}
}
cout << "Your score is: " << score << endl;
}
#endif
return 0;
}
void appendNode(NodePtr& root, string q, string ans, int pts)
{
NodePtr cur;
NodePtr pre;
cur = new TriviaNode;
assert(cur != NULL);
cur->question = q;
cur->answer = ans;
cur->points = pts;
cur->next = NULL;
if (root == NULL)
root = cur;
else
{
pre = root;
while (pre->next != NULL)
{
pre = pre->next;
}
pre->next = cur;
}
}
void generateHardCodedList(NodePtr& root)
{
string q1 = "How long was the shortest war on record? (Hint: how many minutes)";
string ans1 = "38";
int pts1 = 100;
string q2 = "What was the Bank of America's original name? (Hint: Bank of Italy or Bank of Germany)";
string ans2 = "Bank of Italy";
int pts2 = 50;
string q3 = "What is the best-selling video game of all time? (Hint: Call of Duty or Wii Sports)";
string ans3 = "Wii Sports";
int pts3 = 20;
appendNode(root, q1, ans1, pts1);
appendNode(root, q2, ans2, pts2);
appendNode(root, q3, ans3, pts3);
}
int askQuestion(NodePtr& root, int numQuestions)
{
NodePtr cur;
cur = root;
if(numQuestions > getListLength(root))
{
cout << "Warning: there aren't that many questions in the list" << endl;
}
else if(numQuestions < 1)
{
cout << "Warning: the number of trivia to be asked must be greater than or equal to one" << endl;
}
else
{
for(int i = 1; i < numQuestions; i++)
{
cur = cur->next;
}
cout << "Question: " << cur->question << endl;
cout << "Player answer: ";
string player_answer;
getline(cin, player_answer);
cin.clear();
if (player_answer == cur->answer)
{
cout << "Your answer is correct. You recieve " << cur->points << " points." << endl;
return 0;
}
else
{
cout << "Your answer is wrong. The correct answer is: " << cur->answer << endl;
}
}
return 1;
}
int getListLength(NodePtr& root)
{
if(root == NULL)
{
return 0;
}
int count = 0;
NodePtr cur = root;
while(cur != NULL)
{
cur = cur->next;
++count;
}
return count;
}
This is a program to add trivia questions to a linked list in c++. Anything after the while loop causes an error. Specifically, initializing an int causes a segfault; trying to print to console with cout refuses to print anything out.
In the current version of the code your generateHardCodedList pases the root pointer to appendNode functions without initializing it. The calling code did not initialize root (called head in main), generateHardCodedList does not initialize it either, so appendNode receives a garbage pointer as root. After that all bets are off: your program is already broken.
I don't know why in your case it crashes so much later in the code, but it doesn't matter anyway. Your generateHardCodedList call is already broken.
Either initialize your head pointer with nullptr before passing it to generateHardCodedList, or better initialize it to nullptr inside generateHardCodedList, before trying to call appendNode.