I got an error on second if
Making the exactly same if outside of for seems to work just fine, it returns the value from priority function, but when I try to do it in for it said that I'm trying to pass an invalid parameter to a function which considers it to be fatal.
#include <iostream>
#include <stack>
#include <string>
using namespace std;
int priority(char c);
int main()
{
stack<char>Operator;
string input;
string output;
getline(cin, input);
for (int i = 0; i < input.size(); i++)
{
if (input[i] == '(' || input[i] == ')' || input[i] == '+' || input[i] == '-' || input[i] == '*' || input[i] == '/')
Operator.push(input[i]);
else
output.push_back(input[i]);
if (priority(Operator.top()) == 3)
{
int aux = Operator.top();
Operator.pop();
while (priority(Operator.top() == 4))
{
output.push_back((char)Operator.top());
Operator.pop();
}
Operator.push(aux);
}
if (priority(Operator.top() == 2))
{
Operator.pop();
while (priority(Operator.top()) != 1)
{
output.push_back(Operator.top());
Operator.pop();
}
Operator.pop();
}
}
cout << output;
cin.ignore();
cin.get();
return 0;
}
int priority(char c)
{
if (c == '(')
return 1;
if (c == ')')
return 2;
if (c == '+' || c == '-')
return 3;
if (c == '*' || c == '/')
return 4;
}
The statement Operator.top() is being called on every symbol in the input string. That would probably work in case your string starts with a '(' symbol or with a unary plus, but what would happen in case of "2*2"?
As a perfect solution you should redesign your code to make it a finit automaton. As a simple ad hoc fix you should check if the current symbol is an operation or digit and don't call the Operator.top() in the latter case:
if (isdigit(input[i])) {
output.push_back(input[i]);
}
else {
Operator.push(input[i]);
if (priority(Operator.top()) == 3) {
// ...
}
// ...
}
Related
So, I was doing Data Structure and ALgorithm using C++ and STL, I was trying to implement Infix to postfix using stack. I am not sure what is this issue with the code? There is no compile error and when the code runs it returns -1073741510. I have rechecked the whole code, couldn't found any issues
#include<iostream>
#include<stack>
#include<string>
using namespace std;
int isOperator(char ch)
{
if(ch=='+' || ch == '-' || ch == '*' || ch == '/')
return 1;
else
return 0;
}
int precedence(char ch)
{
//for limited input only
if(ch == '*' || ch == '/')
return 3;
else if(ch=='+' || ch == '-' )
return 2;
else
return 0;
}
string infixtopostfix(string infix)
{
stack <char> st;
int i=0;
string postfix;
while(infix[i]!='\0')
{
if(!isOperator(infix[i]))
{
postfix.push_back(infix[i]);
i++;
}
else
{
if(precedence(infix[i])>precedence(st.top()))
{
st.push(infix[i]);
i++;
}
else{
postfix.push_back(st.top());
st.pop();
}
}
}
while(!st.empty())
{
postfix.push_back(st.top());
st.pop();
}
return postfix;
}
int main()
{
string infix= "a+b";
cout<<"Postfix-->"<<infixtopostfix(infix)<<endl;
return 0;
}
Your postfix string has a size of zero. This means that any attempt to access the characters of that string is an error. If you want to add characters to a string use push_back.
postfix[j] = infix[i];
should be
postfix.push_back(infix[i]);
and (twice)
postfix[j] = st.top();
should be
postfix.push_back(st.top());
and
postfix[j]='\0';
should be removed.
There is no need to nul terminate std::string. Once you have made all these changes you will also see that the j variable can be removed. A std::string knows it's own size, you don't need a separate variable to keep track. It seems that you are programming a std::string as if it's like a C string.
It seems to be a very common misunderstanding that std::string (or a std::vector) automatically grows when you subscript it. This is not true.
EDIT
You have another error here,
if(precedence(infix[i])>precedence(st.top()))
The stack maybe empty when executing this statement, leading to a crash. I'm guessing the code should read
if(st.empty() || precedence(infix[i])>precedence(st.top()))
With that change your code works for me.
Thank You everyone for the help. Here is the final answer which is running without any error.
#include<iostream>
#include<stack>
#include<string>
using namespace std;
int isOperator(char ch)
{
if(ch=='+' || ch == '-' || ch == '*' || ch == '/')
return 1;
else
return 0;
}
int precedence(char ch)
{
//for limited input only
if(ch == '*' || ch == '/')
return 3;
else if(ch=='+' || ch == '-' )
return 2;
else
return 0;
}
string infixtopostfix(string infix)
{
stack <char> st;
int i=0;
string postfix;
while(infix[i]!='\0')
{
if(!isOperator(infix[i]))
{
postfix.push_back(infix[i]);
i++;
}
else{
if(st.empty() || precedence(infix[i])>precedence(st.top()))
{
st.push(infix[i]);
i++;
}
else{
postfix.push_back(st.top());
st.pop();
}
}
}
while(!st.empty())
{
postfix.push_back(st.top());
st.pop();
}
return postfix;
}
int main()
{
string infix= "a+b";
cout<<"Postfix-->"<<infixtopostfix(infix)<<endl;
return 0;
}
My current assignment requires me to allow for a user to pass strings of characters and convert from roman numerals to a decimal value. I've faced an issue that when random words are passed through the program it must return the longest valid prefix and ignore the remaining characters. My code runs through a while loop and once it reaches the break condition it repeats the code again for the remaining characters. I'm unsure what next step I should take to fix this code to output correctly. Following image shows the characters to pass through the code.
Image of test failure
#include <iostream>
#include <ctype.h>
using namespace std;
int
main (){
while (!cin.eof ()){
char inputChar;
int result = 0;
while (cin.get (inputChar))
{
inputChar = toupper (inputChar);
if (inputChar == 'M')
result = result + 1000;
else if (inputChar == 'D')
{
inputChar = cin.peek ();
inputChar = toupper (inputChar);
if (inputChar == 'M')
{
result = result - 500;
continue;
}
else if (inputChar == 'D'){
result = result;
continue;
}
else
{
result = result + 500;
continue;
}
}
else if (inputChar == 'C')
{
inputChar = cin.peek ();
inputChar = toupper (inputChar);
if (inputChar == 'M' || inputChar == 'D')
{
result = result - 100;
continue;
}
else
{
result = result + 100;
continue;
}
}
else if (inputChar == 'L')
{
inputChar = cin.peek ();
inputChar = toupper (inputChar);
if (inputChar == 'M' || inputChar == 'D' || inputChar == 'C')
{
result = result - 50;
continue;
}
else
{
result = result + 50;
continue;
}
}
else if (inputChar == 'X')
{
inputChar = cin.peek ();
inputChar = toupper (inputChar);
if (inputChar == 'M' || inputChar == 'D' || inputChar == 'C'
|| inputChar == 'L')
{
result = result - 10;
continue;
}
else
{
result = result + 10;
continue;
}
}
else if (inputChar == 'V')
{
inputChar = cin.peek ();
inputChar = toupper (inputChar);
if (inputChar == 'M' || inputChar == 'D' || inputChar == 'C'
|| inputChar == 'L' || inputChar == 'X')
{
result = result - 5;
continue;
}
else
{
result = result + 5;
continue;
}
}
else if (inputChar == 'I')
{
inputChar = cin.peek ();
inputChar = toupper (inputChar);
if (inputChar == 'M' || inputChar == 'D' || inputChar == 'C'
|| inputChar == 'L' || inputChar == 'X' || inputChar == 'V')
{
result = result - 1;
continue;
}
else
{
result = result + 1;
continue;
}
}
else{
break;
}
}
if (result != 0)
{
cout << result << endl;
}
}
return 0;
}
Your break statement does not go out of the both while loops. It only breaks the inner loop, not the outer one. You can use a flag to tell the outer loop not to continue:
int main()
{
bool exit_loop = false; // define a flag here
while (!cin.eof()) {
char inputChar;
int result = 0;
if (exit_loop) // check the flag here
break;
while (cin.get(inputChar))
{
and while breaking set the flat to true:
}
else
{
exit_loop = true; // set the flag here
break;
}
Maybe try clearing the buffer at the end of the outer loop. This way the longest prefix is printed and the same word isn't being used again through the iteration.
if (result != 0)
{
cout << result << endl;
}
cin. ignore(10000, '\n'); //used to ignore or clear characters from the input buffer
}
Ok, so I'm working on a project that requires us to translate English to Pig Latin. I was trying to kind of copy and tweak some code I found online that did the opposite because the functions kind of looked similar. In my class, we are given certain functions that have to be implemented in our code.
This has to be present in my source code:
struct Word
{
string english;
string pigLatin;
};
Function 1: Word * splitSentence(const string words, int &size); ~ Takes the English sentence as 1 string
Function 2: void convertToPigLatin(Word [] wordArr, int size); ~ Converts English to Pig Latin
Function 3: void convertToPigLatin(Word [] wordArr, int size); ~ Display
Here is the code that I have.
Edit: The problem I'm having is that I don't have wordArr declared anywhere in my code so it can't compile. I also noticed a few minor errors and changed my code a little. You'll have to excuse me I'm very tired right now.
#include <iostream>
#include <string>
#include <cctype>
using namespace std;
struct Word
{
string english;
string pigLatin;
};
Word * splitSentence(wordArr&; int &);
void convertToPigLatin (Word[], int);
void displayPigLatin (Word[], int);
int main()
{
string userInput;
int size;
cout <<"This is an English to Pig Latin translator.\n";
cout <<"Enter a sentance that you want to translate.\n";
getline(cin, userInput);
Word *wordArr = convertToPigLatin(userInput, size);
displayPigLatin(wordArr, size);
return 0;
}
Word * splitSentence(const Word [] wordArr, int &size)
{
int num = 0;
int phraseLength = userInput.length();
for (int i = 0; i < size; i++)
{
if (isspace(userInput[i]))
{
if (isspace(userInput[ i - 1]))
{
num--;
}
num++;
}
}
if (ispunct(userInput[i]))
{
if (i != (phraseLength - 1))
{
userInput.erase(1--, 1)
}
}
}
void convertToPigLatin(Word wordArr[], int size)
{
for (int i = 0; i < size; i++)
{
int stringLength;
if (i == (size - 1))
{
stringLength = wordArr[i].userInput.length();
}
else
{
stringLength = wordArr[i].userInput.length() - 1;
}
string vowel, way;
vowel = wordArr[i].userInput.at(stringLength - stringLength);
way = wordArr[i].userInput.at(stringLength - 3);
bool markV = ((vowel == 'A') || (vowel == 'a') (vowel == 'E') || (vowel == 'e')
(vowel == 'I') || (vowel == 'i') (vowel == 'O') || (vowel == 'o')
(vowel == 'U') || (vowel == 'u'));
wordArr[i].userInput.erase(stringLength - 3, 3);
if (!(markV && (way == 'w')))
{
wordArr[i].english = way + wordArr[i].userInput;
}
}
displayPigLatin(wordArr, stringLength);
}
void displayPigLatin(const Word wordArr[], int size);
{
cout << "\nHere is your phrase in PigLatin: ";
for (int i = 0 i < size; i++)
{
cout << wordArr[i].userInput << " ";
}
}
Important Note: You can only use range based for-loops in C++11 or higher if your compiler doesn't support C++11 or higher, use regular for-loops...
Given your question, you have to use this structure (It is equivalent to the one in the question):
typedef struct
{
std::string english;
std::string pig_latin;
} Word;
This is a macro which is going to be used to check if the first letter is a vowel or a consonant (Hence, !IS_VOWEL(some_char))...
#define IS_VOWEL(x) ((x) == 'A' || (x) == 'E' || (x) == 'I' || (x) == 'O' || (x) == 'U' || \
(x) == 'a' || (x) == 'e' || (x) == 'i' || (x) == 'o' || (x) == 'u')
Another function which we need to acquire only the part of the word which has letters (not symbols and numbers):
std::pair<unsigned, unsigned> GetWord(std::string word)
{
auto start = word.end();
for (auto it = word.begin(); it != word.end(); ++it)
if (tolower(*it) >= 'a' && tolower(*it) <= 'z' && start == word.end())
start = it;
else if (start != word.end() && !(tolower(*it) >= 'a' && tolower(*it) <= 'z'))
return std::make_pair(std::distance(word.begin(), start), std::distance(word.begin(), it));
return std::make_pair(start == word.end() ? 0 : std::distance(word.begin(), start), std::distance(word.begin(), word.end()));
}
And last but not least, the function to convert English to Pig-Latin (I know it is huge):
std::vector<Word> CreatePigLatinWordsFromEnglish(std::string english, bool sentence_case = true)
{
// You can break it from here to use inside another function (viz., splitSentence)
std::transform(english.begin(), english.end(), english.begin(), ::tolower);
std::stringstream english_stream(english);
std::vector<Word> words;
std::string temporary;
while (std::getline(english_stream, temporary, ' '))
words.emplace_back(Word({ temporary, "" }));
// Till here...
// From here the conversion starts...
for (auto &word : words)
{
auto const word_it = GetWord(word.english);
if (!IS_VOWEL(word.english[word_it.first]) && !std::string(std::next(word.english.begin(), word_it.first),
std::next(word.english.begin(), word_it.second)).empty())
{
word.pig_latin.append(std::string(word.english.begin(), std::next(word.english.begin(), word_it.first)));
word.pig_latin.append(std::string(std::next(word.english.begin(), word_it.first + 1), std::next(word.english.begin(), word_it.second)));
word.pig_latin.append(1, word.english[word_it.first]);
word.pig_latin.append(std::string("ay"));
word.pig_latin.append(std::next(word.english.begin(), word_it.second), word.english.end());
}
else
word.pig_latin = std::string(word.english.begin(), std::next(word.english.begin(), word_it.second)) + "way"
+ std::string(std::next(word.english.begin(), word_it.second), word.english.end());
}
// Conversion ends here...
// Changing the case from lower case to sentence case if needed...
if (sentence_case)
{
words[0].english[0] = toupper(words[0].english[0]);
words[0].pig_latin[0] = toupper(words[0].pig_latin[0]);
}
return words; // Returning the list of words we got...
}
Well, an example to demonstrate this method:
int main()
{
auto const test = "An apple a day keeps the doctor away!";
for (auto word : CreatePigLatinWordsFromEnglish(test))
std::cout << word.pig_latin << " ";
return 0;
}
Output:
Anway appleway away ayday eepskay hetay octorday awayway!
Try it out and see whether it gives you the required result...
Kind regards,
Ruks.
I just had a small question about my program. So, I have a function that evaluates a postfix expression and returns the integer or float calculated. Here are the following functions involved:
#include <iostream>
#include <sstream>
#include <cstring>
#include <stack>
#include <limits>
float postfixUtility::evaluatePostfix(string pexp)
{
stack<int> S;
int pexpLength = pexp.length();
cout << pexpLength << endl;
for (int i = 0; i < pexpLength; i++)
{
if(pexp[i] == ' ' || pexp[i] == ',')
{
continue;
}
else if(isOperator(pexp[i]))
{
int operand2 = S.top(); S.pop();
int operand1 = S.top(); S.pop();
int result = isOperate(pexp[i], operand1, operand2);
S.push(result);
}
else if(isDigit(pexp[i]))
{
int operand = 0;
while(i<pexp.length() && isDigit(pexp[i]))
{
operand = (operand*10) + (pexp[i] - '0');
i++;
}
i--;
S.push(operand);
}
}
return S.top();
}
bool postfixUtility::isDigit(char C)
{
if(C >= '0' && C <= '9')
{
return true;
}
return false;
}
bool postfixUtility::isOperator(char C)
{
if(C == '+' || C == '-' || C == '*' || C == '/')
{
return true;
}
return false;
}
int postfixUtility::isOperate(char operation, int operand1, int operand2)
{
if(operation == '+')
{
return operand1+operand2;
}
if(operation == '-')
{
return operand1-operand2;
}
if(operation == '*')
{
return operand1*operand2;
}
if(operation == '/')
{
return operand1/operand2;
}
}
These functions work together to solve the postfix expression inputted. The expression inputted is not empty and actually holds a postfix expression. However, every time I run the code, it results in a segfault. I am quite baffled actually because it seems to me that my code should work.
Thank you!
EDIT #1: So, the original input to my function is: "(4+3* 12)/ ( 12+ 3/ 2+ 46 /4)"
Then, I put that through another function to convert it to postfix. This is that function:
int postfixUtility::priority(char a)
{
int temp;
if (a == '^')
temp = 1;
else if (a == '*' || a == '/')
temp = 2;
else if (a == '+' || a == '-')
temp = 3;
return temp;
}
string postfixUtility::getPostfix(string nexp)
{
stack<char> operator_stack;
stringstream output;
for (unsigned i = 0; i < nexp.length(); i++) {
if (nexp[i] == '+' || nexp[i] == '-' || nexp[i] == '*' || nexp[i] == '/' || nexp[i] == '^') {
while (!operator_stack.empty() && priority(operator_stack.top()) <= priority(nexp[i])) {
output << operator_stack.top();
operator_stack.pop();
}
operator_stack.push(nexp[i]);
} else if (nexp[i] == '(') {
operator_stack.push(nexp[i]);
} else if (nexp[i] == ')') {
while (operator_stack.top() != '(') {
output << operator_stack.top();
operator_stack.pop();
}
operator_stack.pop();
} else {
output << nexp[i];
}
}
while (!operator_stack.empty()) {
output << operator_stack.top();
operator_stack.pop();
}
//cin.ignore(numeric_limits<streamsize>::max(), '\n');
return output.str();
}
Which converts it to: "43 12*+ 12 3 2/+ 46 4/+/", is that wrong? Would that be the reason why I am getting a segfault?
EDIT #2: So, I have commented out 2 lines in my code and I am no longer getting a segfault.
float postfixUtility::evaluatePostfix(string pexp)
{
stack<int> S;
int pexpLength = pexp.length();
for (int i = 0; i < pexpLength; i++)
{
if(pexp[i] == ' ' || pexp[i] == ',')
{
continue;
}
else if(isOperator(pexp[i]))
{
float operand2 = S.top();
//S.pop();
float operand1 = S.top();
//S.pop();
float result = isOperate(pexp[i], operand1, operand2);
S.push(result);
}
else if(isDigit(pexp[i]))
{
int operand = 0;
while(i<pexp.length() && isDigit(pexp[i]))
{
operand = (operand*10) + (pexp[i] - '0');
i++;
}
i--;
S.push(operand);
}
}
return S.top();
}
However, the answer is supposed to be 1.6, but I am getting 1. Any reason why that is happening?
EDIT #3: I changed the isOperate function to the following:
float postfixUtility::isOperate(char operation, float operand1, float operand2)
{
if(operation == '+')
{
return operand1+operand2;
}
else if(operation == '-')
{
return operand1-operand2;
}
else if(operation == '*')
{
return operand1*operand2;
}
else if(operation == '/')
{
return operand1/operand2;
}
}
However, I still get 1 as a result.
Those pops where important:
float operand2 = S.top();
//S.pop();
float operand1 = S.top();
//S.pop();
Without popping the last element, operand1 will always be equal to operand2 and dividing a number by itself usually results in 1.
The reason you where getting a segfault in the first place is that your postfix converter is giving you (very) wrong results (which should be clear from the fact that its output contains numbers not present in its input). Let's have look at the first part of the output you posted: 43 12*+. Your parser will identify 43 and 12 as numbers and push them on the stack. It will identify * as an operator, take the two numbers from the stack, multiply them and push the result on the stack. Then it will encounter + and try to take two operands from the stack. However, there's only one element on the stack, namely the result of the multiplication. Calling top() on an empty stack is causing your segfault.
Edit: It is generally a good idea to do a sanity check before performing a operation that could result in undefined behavior for incorrect input.This allows you to either do something to solve the problem or to produce an error message containing diagnostic information (e.g. in your case the operator, the position in the string, the string itself, etc.). This will help you identify such problems more easily.
tl;dr: Fix your postfix converter.
I have a homework and its just bugging for the last 2 days, I've been doing exactly what the pseudo code and still haven't got it right yet.
For example, if I put in "mike]" or "mike]123", my program will crash, due to the stack is empty...From what I observe, the program will crash when:
- The stack is empty
- And there is a close parenthesis
PS: with the help of us2012, I can fix the crash problem. However, the result is not right.
Instead of printing out "invalid", it outputs "valid"
:(
Here is the pseudo code from my professor:
def parse_parenthesis(str):
stack = create a new empty stack of OpenParen objects
for i from 0 to str.size() - 1:
if str[i] is an open parenthesis
stack.push(new OpenParen(str[i]))
else if str[i] is not a close parenthesis:
# str[i] is not a parenthesis of any kind, so ignore it
continue
# otherwise str[i] must be a close parenthesis, try to
# match it with the most recent open paren, on the top
# of the stack
else if stack is empty
return false;
else if stack.peek() is of the same type as str[i]:
# close properly
stack.pop()
else
return false;
if stack is not empty
return false;
else
return true
and here is what I have so far:
.cpp file
bool ParenMatching(const string& s, unique_ptr<string>& output)
{
unique_ptr<OpenParen> stack(new OpenParen);
bool validOpen, validClose, valid;
bool match; //haveCloseParen;
/*string unMatch = "Unmatch";
string unExpected = "Unexpected close paren";
string noError = "No Error";*/
for (size_t i = 0; i < s.length(); i++)
{
// check if its open parenthesis
validOpen = stack->IsOpenParen(s[i]);
// check if its close parenthesis
validClose = stack->IsCloseParen(s[i]);
// if there is open paren, push into the stack
if(validOpen)
stack->PushObj(s[i]);
else if(!validClose)
{
continue;
}
else if(stack->GetObj().IsEmpty())
valid = false;
else if(match = IsMatchParen(s[i], stack))
stack->PopObj();
else
valid = false;
}
if(!stack->GetObj().IsEmpty())
valid = false;
else
valid = true;
return valid;
}
bool IsMatchParen(const char c, const unique_ptr<OpenParen>& stack)
{
bool valid;
if(c == ')' && stack->PeekObj() == '(')
valid = true;
else if (c == ']' && stack->PeekObj() == '[')
valid = true;
else if (c == '}' && stack->PeekObj() == '{')
valid = true;
else if (c == '>' && stack->PeekObj() == '<')
valid = true;
else
valid = false;
return valid;
}
OpenParen.cpp
// Check if its open paren
bool OpenParen::IsOpenParen(const char c)
{
bool isOpen;
if(c == '(' || c == '[' || c == '{' || c == '<')
isOpen = true;
else
isOpen = false;
return isOpen;
}
// check if its close paren
bool OpenParen::IsCloseParen(const char c)
{
bool isClose;
if(c == ')' || c == ']' || c == '}' || c == '>')
isClose = true;
else
isClose = false;
return isClose;
}
gcc 4.7.3: g++ -Wall -Wextra -std=c++0x parens.cpp
#include <iostream>
#include <stack>
#include <string>
#include <vector>
bool isOpen(char c) {
return c == '(' || c == '[' || c == '{' || c == '<'; }
bool isClose(char c) {
return c == ')' || c == ']' || c == '}' || c == '>'; }
bool isMatch(char c1, char c2) {
return (c1 == '(' && c2 == ')')
|| (c1 == '[' && c2 == ']')
|| (c1 == '{' && c2 == '}')
|| (c1 == '<' && c2 == '>'); }
bool parse(const std::string& s) {
std::stack<std::string::value_type> stk;
for (std::string::size_type i = 0; i < s.size(); ++i) {
if (isOpen(s[i])) { stk.push(s[i]); }
else if (isClose(s[i])) {
if (!stk.empty() && isMatch(stk.top(), s[i])) { stk.pop(); }
else { return false; } } }
return stk.empty(); }
int main() {
std::vector<std::string> ptests = {
"", "()", "()()", "(())", "a(a)a" };
std::vector<std::string> ftests = {
"(", ")", ")(", ")()(", "))((" };
for (const auto& t : ptests) {
if (!parse(t)) { std::cout << "fail: " << t << std::endl; } }
for (const auto& t : ftests) {
if (parse(t)) { std::cout << "fail: " << t << std::endl; } }
}
One important thing you should keep in mind about C++ : Multiple else ifs do not live at the same level. That's because else if is not a single entity, it's an else that belongs to the preceding statement and an ifthat begins a new statement, so
if (cond1)
a();
else if (cond 2)
b();
else if (cond 3)
c();
else
d();
is actually
if (cond1)
a();
else {
if (cond 2)
b();
else {
if (cond 3)
c();
else
d();
}
}
Therefore, your check whether the stack is empty needs to be before the check whether the current close parens matches the top of the stack. Otherwise, your program will try to examine the top of the stack when it's empty, and that results in a crash.
Also, setting valid = false is not the right thing to do when you find a condition that indicates a non-match. The loop will still continue and can reset valid to true in a later iteration. You need to immediately return false, as you can already see in your pseudocode.