We're supposed to implement a program to check whether the braces, brackets and parens in a given expression all match using a stack structure in C++ for my CS class. Unfortunately, I'm kinda stuck on this one, since I keeps telling me something doesn't match, even when it most decidedly does.
Here's what I got so far:
#include <stdlib.h>
#include <iostream>
#include <string>
#include <cstring>
using namespace std;
struct cell {int value; cell* next; };
cell* top;
int numElem;
void init()
{
top = NULL;
numElem = 0;
}
int pop()
{
int res;
if (top != NULL)
{
res = top -> value;
top = top -> next;
numElem--;
} else {
cout << "FAIL: Stack empty!\n";
res = -1;
}
return res;
}
void push(int element)
{
cell* cat = new cell;
cat -> value = element;
cat -> next = top;
top = cat;
}
void match(char expr[])
{
bool pass = true;
char expected;
char encountered;
char closing;
for (int i=0; pass && (i<strlen(expr)); i++)
{
if ((i==40)||(i==91)||(i==123))
push(i);
else
{
if (i==41)
expected = 40;
if (i==93)
expected = 91;
if (i==125)
expected = 123;
encountered = pop();
if (expected != encountered)
closing = i;
pass = false;
}
}
if (pass)
cout << "Parentheses match OK!\n";
else
cout << encountered << " has opened, but closing " << closing;
cout << " encountered!\nParentheses do not match\n";
}
int main(int argc, char * argv[])
{
init();
match(argv[1]);
return 0;
}
Since the stack framework existed from a previous exercise and worked fine there, I'm strongly assuming whatever error there is should be in void match
else
cout << encountered << " has opened, but closing " << closing;
cout << " encountered!\nParentheses do not match\n";
The second line always prints. It should be
else
{
cout << encountered << " has opened, but closing " << closing;
cout << " encountered!\nParentheses do not match\n";
}
Also
if (expected != encountered)
closing = i;
pass = false;
should also be
if (expected != encountered)
{
closing = i;
pass = false;
}
Do you come from python? Indentation doesn't affect logic in C++, it just affects readability.
In your match function you should test characters, not their indices:
void match(char expr[])
{
...
for (int i=0; pass && (i<strlen(expr)); i++)
{
char c = expr[i]; // use this c instead of i below!!!!!!!
if ((c==40)||(c==91)||(c==123))
push(c);
else
{
if (c==41)
expected = 40;
if (c==93)
expected = 91;
if (c==125)
...
Also you did not update counter in your push:
void push(int element)
{
...
++numElems; // Was missing!!!!
}
Related
#include <iostream>
#include <string>
using namespace std;
#define Max 100000
class Stack {
private:
int top =-1;
char letters[Max];
public:
void setTop(int t) {
top = t;
}
int getTop() {
return top;
}
bool isEmptyStack() {
if (top == -1) {
return true;
}
else{ return false;
}
}
char push(char x,int s) {
if (top != s - 1){
top++;
x = letters[top];
return x;
}
}
char pop() {
if ((isEmptyStack())==false){
cout << "the deleted value is: " << l[top]<<endl;
top--;
return l[top];
}
}
};
void reverse(char letters[], char temp[], int size, Stack stack) {
int i=0;
for (i = 0; i < size; i++) {
stack.push(letters[i],size);
}
i = 0;
cout << temp<<endl;
while (stack.isEmptyStack() == false)
{
letters[-1] = stack.getTop();
stack.pop();
stack.push(letters[i],size);
i++;
}
/* for (int i = 0; i < size; i++) {
cout << temp[i];
}*/
}
int myStringLength(const char* letter)
{
for (int i = 0, c = 0; letter[i] != '\0'; i++, c++) {
if (letter[i] != '\0')
for (; letter[i] != '\0'; i++, c++)
if (letter[i] == '\0') break;
return c;
}
}
int main()
//initializes the main function
{
Stack stack;
string w;
std::cout << "Enter a Word: ";
getline(cin,w);
char* letters = &w[0];
// sets the character text array to set the number of characters equal to the size of the string
//calls the processData function
std::cout << letters<<endl;
int size = myStringLength(letters);
reverse(letters, letters, size, stack);
return 0;//returns the function at 0.
}
I set out to create a program that will check if a word is a palindrome(meaning it is spelled the same normally and if the word is reversed.) I am not yet at that point that is just the final objective. In my code, I have created a stack class because I wanted to feel the satisfaction of getting the same result using my own code. My problem is the stack is not reversing it is returning some weird characters that I don't have the keys on my keyboard to replicate.
The desired outcome should be word's reversed characters.
if the word is food the function should be returning doof. I have already compared the reversed stack to the original and printed the final statement. I fixed the char letters[];
If you're open to using a simple function instead of a Stack then you could use the following program since it is much more simple than your Stack version and hence less-error prone.
#include <iostream>
#include <string>
bool checkIfPalindroom(const std::string &str)
{
for(int i=0;i<(str.size()/2);i++)
{
if (str[i] != str[str.size() - i - 1])
{
return false;//if this if is satisfied even once, return false
}
}
return true;//if the control flow reaches here this will mean that no if was satisfied and hence return true
}
int main()
{
std::string myString = "Somearbitrarystring";
if(checkIfPalindroom(myString))//call the function
{
std::cout<<"The given string: "<<myString <<" is a palindrome"<<std::endl;
}
else
{
std::cout<<"The given string: "<<myString<<" is not a palindrome"<<std::endl;
}
return 0;
}
Assignment: For this assignment, you are to write a program, which will calculate the results of Reverse Polish expressions that are provided by the user.
You must handle the following situations (errors):
Too many operators (+ - / *)
Too many operands (doubles)
Division by zero
The program will take in a Polish expression that separates the operators and operands by a single space, and terminates the expression with an equals sign.
The program will continue to take and evaluate expressions until the user enters a zero (0) on a line by itself followed by a new line.
Problem 1: I am having a problem with telling the user that there are too many operators and operands. I tried to code it but I have no
idea where to begin with this.
Problem 2: I want the program to end when the user inputs 0, but it is not doing anything when I do it in my program.
#include<iostream>
#include<iomanip>
#include<string>
#include<sstream>
using namespace std;
class Node
{
double data;
Node *top;
Node *ptr;
public:
Node()
{
top = NULL;
ptr = NULL;
}
bool isEmpty()
{
return top == 0;
}
void pushValue(double val)
{
Node *next = new Node;
next->data = val;
next->ptr = top;
top = next;
}
double popVal()
{
if (isEmpty())
{
cout << "Error: Too many operators" << endl;
}
else
{
Node *next = top->ptr;
double ret = top->data;
delete top;
top = next;
return ret;
}
}
//Displays the answer of the equation
void print()
{
cout << "= " << top->data << endl;
}
};
bool isOperator(const string& input)
{
string ops[] = { "+", "-", "*", "/" };
for (int i = 0; i < 4; i++)
{
if (input == ops[i])
{
return true;
}
}
return false;
}
//This function tells the operators what to do with the values.
void performOp(const string& input, Node& stack)
{
double Val1, Val2;
int errorCheck = 0;
Val1 = stack.popVal();
Val2 = stack.popVal();
if (input == "+")
{
stack.pushValue(Val1 + Val2);
}
else if (input == "-")
{
stack.pushValue(Val1 - Val2);
}
else if (input == "*")
{
stack.pushValue(Val1 * Val2);
}
else if (input == "/" && Val2 != 0)
{
stack.pushValue(Val1 / Val2);
}
if (input == "/" && Val2 == 0)
{
cout << "Error: Division by zero" << endl;
errorCheck = 1;
}
if (errorCheck == 0)
{
stack.print();
}
}
int main()
{
cout << "Reverse Polish Notation Calculator!" << endl;
cout << "-------------------------------------------------------------------" << endl;
cout << "Enter your values followed by your operators(Enter 0 to exit)" << endl;
string input;
Node stack;
//Checks the user's input to see which function to use.
while (true)
{
cin >> input;
double num;
if (stringstream(input) >> num)
{
stack.pushValue(num);
}
else if (isOperator(input))
{
performOp(input, stack);
}
else if (input == "0")
{
return 0;
}
}
}
I am trying to implement a system that would perform something like say the user enters 4 5 +. It would add the 4 and 5 (9) and push 9 into the stack.
For some reason the values in the stack are huge numbers so I believe it has something to do with a pointer or accessing a wrong field but I'm pulling my hair out trying to find the error. Any help on what I'm doing wrong?
#include "stack.h"
int main()
{
stack Test;
bool stop = false;
float runningtotal = 0;
while (stop == false)
{
char input;
cin >> input;
if (input == '+') {
int value1 = Test.top();
Test.pop();
int value2 = Test.top();
Test.pop();
cout << value1+value2 << endl;
Test.push(value1 + value2);
}
cout << Test.top();
std::getchar();
std::getchar();
}
And the implementation of stack
#include "stack.h"
stack::stack()
{
maxsize = MaxSize;
currentsize = 0;
sptr = new StackElement[maxsize];
}
stack::~stack()
{
delete [] sptr;
}
void stack::push(StackElement data)
{
if (currentsize < maxsize)
{
sptr[currentsize] = data;
currentsize++;
} else {
cout << "Stack is full ;-;";
}
}
void stack::pop()
{
if (currentsize == 0) {
cout << "Empty stack? ;-;";
return;
}
currentsize--;
}
StackElement stack::top()
{
if (currentsize == 0) {
cout << "Empty stack u ninja ;-;";
return NULL;
} else {
return (sptr[currentsize]);
}
}
void stack::push(StackElement data)
{
if (currentsize < maxsize)
{
sptr[currentsize] = data;
currentsize++; //<--- incrementing after so nothing in [currentsize] now
} else {
cout << "Stack is full ;-;";
}
}
StackElement stack::top()
{
if (currentsize == 0) {
cout << "Empty stack u ninja ;-;";
return NULL;
} else {
return (sptr[currentsize]);// should use currentsize-1
// latest filled cell
// since its pushing from top
}
}
Be sure to convert those ascii codes(49 ish) from keyboard to integer type explanations.
input - 48 should do it.
It's crashing at the very end of the main() function where it needs to delete the starters objects. The error message that pops up when I run the program says: Debug assertion failed! Expression: _BLOCK_IS_VALID(pHead->nBlockUse). How do i fix it from crashing when deleting the starters objects?
#include <iostream>
#include <fstream>
#include "olympic.h"
using namespace std;
ofstream csis;
int main() {
const int lanes = 4;
Ranker rank(lanes);
csis.open("csis.txt");
// First make a list of names and lane assignments.
Competitor* starters[lanes];
starters[0] = new Competitor("EmmyLou Harris", 1);
starters[1] = new Competitor("Nanci Griffith", 2);
starters[2] = new Competitor("Bonnie Raitt", 3);
starters[3] = new Competitor("Joni Mitchell", 4);
// The race is run; now assign a time to each person.
starters[0]->setTime((float)12.0);
starters[1]->setTime((float)12.8);
starters[2]->setTime((float)11.0);
starters[3]->setTime((float)10.3);
// Put everyone into the ranker.
for (int i = 0; i < lanes; i++)
rank.addList(starters[i]);
// Now print out the list to make sure its right.
cout << "Competitors by lane are:" << endl;
csis << "Competitors by lane are:" << endl;
for (int i = 1; i <= lanes; i++)
rank.getLane(i)->print();
// Finally, show how they finished.
cout << "Rankings by finish are:" << endl;
csis << "Rankings by finish are:" << endl;
for (int i = 1; i <= lanes; i++)
rank.getFinish(i)->print();
for (int i = 0; i < lanes; i++)
delete starters[i];
csis.close();
}
ranker.cpp:
#include "ranker.h"
#include "competitor.h"
#include <stdlib.h>
Ranker::Ranker(int lanes) {
athlete = new Competitor*[lanes];
numAthletes = 0;
maxAthletes = lanes;
}
int Ranker::addList(Competitor* starter) {
if (numAthletes < maxAthletes && starter != NULL) {
athlete[numAthletes] = starter;
numAthletes++;
return numAthletes;
}
else
return 0;
}
Competitor* Ranker::getLane(int lane) {
for (int i = 0; i < numAthletes; i++) {
if (athlete[i]->getLane() == lane) {
return athlete[i];
}
}
return NULL;
}
Competitor* Ranker::getFinish(int position) {
switch(position) {
case 1:
return athlete[3];
break;
case 2:
return athlete[2];
break;
case 3:
return athlete[1];
break;
case 4:
return athlete[0];
break;
}
return NULL;
}
int Ranker::getFilled() {
return numAthletes;
}
Ranker::~Ranker() {
delete [] athlete;
}
competitor.h:
#ifndef _COMPETITOR_H
#define _COMPETITOR_H
class Competitor {
private:
char* name;
int lane;
double time;
public:
Competitor(char* inputName, int inputLane);
Competitor();
void setTime(double inputTime);
char* getName();
int Competitor::getLane();
double getTime();
void print();
~Competitor();
};
#endif
competitor.cpp:
#include "competitor.h"
#include <string>
#include <iostream>
#include <iomanip>
using namespace std;
Competitor::Competitor(char* inputName, int inputLane) {
name = inputName;
lane = inputLane;
}
Competitor::Competitor() {
name = 0;
lane = 0;
time = 0;
}
void Competitor::setTime(double inputTime) {
time = inputTime;
}
char* Competitor::getName() {
return name;
}
int Competitor::getLane() {
return lane;
}
double Competitor::getTime() {
return time;
}
void Competitor::print() {
cout << setw(20) << name << setw(20) << lane << setw(20) << setprecision(4) << time << endl;
}
Competitor::~Competitor() {
delete [] name;
}
Call stack:
before crash: http://i.imgur.com/d4sKbKV.png
after crash: http://i.imgur.com/C5cXth9.png
After you've added Competitor class, it seems the problem is that you delete its name in Competitor's destructor. But you assign it from string literal which can't really be deleted. I'm sure the stack trace leading to assertion will prove that.
One way of solving the problem would be using std::string to store the name.
Problem is when deleting the char* value on destructor, which is assigned with const char instead new char. So i have slightly changed the constructor to copy the const char to new char.
Competitor::Competitor(char* inputName, int charlen, int inputLane)
{
name = new char[charlen + 1];
memcpy(name , inputName, charlen );
name [charlen] = '\0';
lane = inputLane;
}
My program is to print the queue of information from a file but i have problem with my following code. When i run the program it keep loop. I cant figure out the problem. Any help?
#include <iostream>
#include <fstream>
#include <string>
#include <iomanip>
#include <queue>
#include <list>
using namespace std;
void simulation(ifstream &infile);
void processArrival(int *newEvent, ifstream &inFile, list<int> eventList,queue<int> printQueue);
void processDeparture(int *newEvent, list<int> eventList,queue<int> printQueue);
string name[100];
int timeAccepted[100];
int fileSize[100];
int i = 1;
int j = 1;
int currentTime;
bool checker = true;
int main(void)
{
ifstream inFile;
string fileName;
int i = 0;
inFile.open("123.txt", ios::in);
simulation(inFile);
/*while(inFile.peek() != EOF )
{
inFile>>name[i]>>timeAccepted[i]>>fileSize[i];
i++;
}
for(int s = 0; s < i; s++)
{
cout << name[s] << timeAccepted[s] << fileSize[s] <<endl;
}*/
return 0;
}
void simulation(ifstream &inFile)
{
queue<int> printQueue;
list<int> eventList;
int *newEvent;
while(inFile.peek() != '\n')
{
inFile>>name[0]>>timeAccepted[0]>>fileSize[0];
}
eventList.push_front(timeAccepted[0]);
int checkEmpty = eventList.empty();
newEvent = &eventList.front();
while(checkEmpty ==0)
{
newEvent = &eventList.front();
if(checker)
{
processArrival(newEvent, inFile, eventList, printQueue);
}
else
{
processDeparture(newEvent, eventList, printQueue);
}
checkEmpty = eventList.empty();
}
}
void processArrival(int *newEvent, ifstream &inFile, list<int> eventList,queue<int> printQueue)
{
int atFront=0;
atFront = printQueue.empty();
cout << atFront <<endl;
printQueue.push(*newEvent);
cout << printQueue.front() <<endl;
eventList.remove(*newEvent);
int temp;
if(atFront==1)
{
currentTime = *newEvent + fileSize[0];
cout << name[0] << " ## " << *newEvent << " ## " << currentTime << endl;
eventList.push_back(currentTime);
}
checker = false;
if(inFile.peek() != EOF )
{
inFile>>name[i]>>timeAccepted[i]>>fileSize[i];
eventList.push_back( timeAccepted[i] );
i++;
checker = false;
if(eventList.back() <= eventList.front())
{
temp = eventList.back();
eventList.back() = eventList.front();
eventList.front() = temp;
checker = true;
}
}
}
void processDeparture(int *newEvent, list<int> eventList,queue<int> printQueue)
{
printQueue.pop();
eventList.pop_front();
int checkEmpty = 1;
checkEmpty = printQueue.empty();
int temp;
if(checkEmpty ==0)
{
currentTime = *newEvent + fileSize[j];
cout << name[j] << " " << *newEvent << " " << currentTime << endl;
eventList.push_back(currentTime);
checker = true;
if(eventList.back() < eventList.front())
{
temp = eventList.back();
eventList.back() = eventList.front();
eventList.front() = temp;
checker = false;
}
j++;
}
}
Your processArrival and processDeparture functions are taking their eventList and printQueue arguments by value. This means that when you call them, for example in this line:
processArrival(newEvent, inFile, eventList, printQueue);
Copies of eventList and printQueue are made and passed into the processArrival function. The processArrival function then operates on those copies, and the original data is never modified. In particular, this means that the original eventList will never have any items removed from it, so it will never be empty -- it will just keep trying to process the first event over and over again.
The solution is to pass these parameters by reference. i.e. change the definition of processArrival to
void processArrival(int *newEvent, ifstream &inFile, list<int>& eventList, queue<int>& printQueue)
Note the & characters that I have inserted before eventList and printQueue. These cause references to the original data, rather than copies of the original data, to be passed into the processArival function. This means that processArrival will operate directly on the original data as you intend it to. Don't forget to make the corresponding change to processDeparture as well.