I was trying to write this code for converting infix expression to postfix expression but I'm getting a segmentation fault for some values. Code is :
#include <cmath>
#include <cstdio>
#include <vector>
#include <iostream>
#include <algorithm>
#include <stack>
#include <bits/stdc++.h>
using namespace std;
int prec(char ch){
if(ch=='^')
return 3;
else if(ch=='*' || ch=='/')
return 2;
else if(ch=='+' || ch=='-')
return 1;
else
return 0;
}
int main() {
/* Enter your code here. Read input from STDIN. Print output to STDOUT */
stack <char> st;
string s;
cin>>s;
for(int i=0;i<21;i++){
if((s[i]>='a' && s[i]<='z') || (s[i]>='A' && s[i]<='Z'))
cout<<s[i];
else{
if( st.empty())
st.push(s[i]);
else if( s[i]=='(' || prec (s[i])> prec(st.top()))
st.push(s[i]);
else if( s[i]==')'){
while(st.top()!='(')
{cout<<st.top(); st.pop();}
st.pop();
}
else{
while(prec(st.top())>=prec(s[i]))
{
cout<<st.top(); st.pop();
}
}
}
}
return 0;
}
For smaller expressions, it gives an answer but for an expression like a+b*(c^d-e)^(f+g*h)-i it gives segmentation fault.
Firstly, the iteration should be just in the strings.
This means that
for(int i=0;i<21;i++){
should be
for(int i=0;i<s.size();i++){
Secondly, you forgot to check if the stack is empty in the loop.
This means that
while(prec(st.top())>=prec(s[i]))
should be
while(!st.empty() && prec(st.top())>=prec(s[i]))
Related
code just turns infix to infix but I can't figure out why?, my code is supposed to turn infix to rpn but this line here:
while( !presedence.empty() && presedence.top() >= num2 )
{
output.push(oprators.top());
oprators.pop();
presedence.pop();
}
is the one that causes error, I think, because if I remove the '='
it just works, be it without allowing letters of the same precedence to join the output queue.
full code:
#include <cmath>
#include <stack>
#include<queue>
#include <iostream>
#include <regex>
#include <vector>
#include <thread>
#include <bitset>
#include <ctime>
#include <string.h>
#include <math.h>
#include <bits/stdc++.h>
#define M_PI 3.14159265358979323846264338327950288419716939937510582097494
#include<windows.h>
#define gkey GetAsyncKeyState
using namespace std;
#define rxs regex_search
#define loop while(true)
double a;
double num1;
double c3 = 299792458;
double c3sq = 89875517873681764;
int mc;
string again;
stack<int> presedence;
stack<string> oprators;
queue<double> numbers;
stack<char> test;
double num5;
double num6;
int E;
int abrt = 0;
double num2;
double ans = num1 + num2;
int num;
int numalt = 0;
int numaltt = 0;
//int nums [] = {srand(time(0));rand();}
bool autoregex(string test){
regex e ("[-+]?([0-9]*\.[0-9]+|[0-9]+)");
if (regex_match (test,e))
return true;
return false;
}
bool autrege(string test){
regex aret("SIN|LOG|sqrt|sin|log|tan|pi|e|ln|EE|[^0-9a-z$##&\]");
if (regex_match (test,aret)){
return true;
}
else{
return false;}
}
void namehere(string test){
if(autrege(test) == true){
regex bret("[+-]");
regex cret("[/*xX]");
regex dret("SIN|LOG|sqrt|sin|log|tan|pi|!|e|ln|EE|\\^");
regex omega("\\)");
regex canmae("\\(");
if (regex_match (test,bret)){num2 = 1;};
if (regex_match (test,cret)){num2 = 2;};
if (regex_match (test,dret)){num2 = 3;};
if (regex_match (test,omega)){num2 = 4;numaltt = numaltt + 1;};
if (regex_match (test,canmae)){num2 = 4;numalt = numalt + 1;};
}
}
int main()
{
vector<double> vec;
again = "n";
while(again == "n"&&abrt == 0){
// queue<double> numbers; stack<int> pres;
queue<string> output;
int test;
string name;
getline(cin, name);
istringstream iss(name);
string token;
while(iss >> token)
{
if(autoregex(token) == true){
output.push(token);
}
if(autrege(token)== true)//token area
{
namehere(token);
num6++;
if(num2 == -1){cout<<"wrong move: ";again = "n";again = "y";cout<<num2<<endl;}
while(presedence.empty() == 1 && oprators.empty() == 1)
{
presedence.push(num2);
oprators.push(token);
}
while(presedence.top() < num2 && !presedence.empty())
{
oprators.push(token);
presedence.push(num2);
}
while(presedence.top() >= num2 && !presedence.empty())
{
output.push(oprators.top());
oprators.pop();
presedence.pop();
}
//3-T 2-ME
}
}
while(presedence.empty() != 1 && oprators.empty() != 1){ output.push(oprators.top());
oprators.pop();presedence.pop();}
while(!output.empty()){cout<<output.front()<<", ";output.pop();}
}
while(again != "n"&&abrt == 0){
}
}
it breaks when I try to see if the top of the operator stack is greater than the current operator,any reasons?
NOTE: This answer refers to revision 2 of the question, which was about why OP's code was crashing. Meanwhile, OP has applied the fix mentioned in my answer (which seems to have fixed the crash), and has overwritten the question to address the next problem in the code. Therefore, this answer of mine no longer corresponds to the question in its current state.
The line
while(presedence.top() >= num2 && !presedence.empty())
is wrong. You should check whether the stack is empty before accessing the topmost element:
while( !presedence.empty() && presedence.top() >= num2 )
Otherwise, your program will be invoking undefined behavior if the stack is indeed empty.
I am tasked with writing a Shunting-Yard algorithm for use in my final project (a calculator). I have written the program the way that makes sense to me, however, I am not getting any output when calling the main algorithm function (toRPN). I believe this is an issue with passing the values between parse and toRPN because I have tested parse directly within main and it works fine, but when I try to do a print test in the toRPN function, it prints nothing. Could someone point me in the right direction?
Header:
#include <iostream>
#include <math.h>
#include <vector>
#include <stack>
#include <queue>
using namespace std;
#ifndef SHUNTING_YARD_ALGORITHM_SHUNTINGYARD_H
#define SHUNTING_YARD_ALGORITHM_SHUNTINGYARD_H
class ShuntingYard {
public:
stack <string> stack;
vector <string> tokens;
queue <string> outputList;
vector <char> operators;
vector <int> precedence;
vector <char> associativity;
ShuntingYard ();
bool hasOnlyDigits(const string s);
int getPrecedence(const string s);
int getAssociativity(const char c);
vector<string> parse(const string input) const;
string mainAlgorithm(const string);
};
#endif //SHUNTING_YARD_ALGORITHM_SHUNTINGYARD_H
cpp:
#include "ShuntingYard.h"
#include <iostream>
#include <math.h>
#include <vector>
#include <stack>
#include <queue>
#include <sstream>
#include <numeric>
using namespace std;
stack <string> stack1;
queue <string> outputList;
vector <string> operators;
vector <int> precedence;
vector <char> associativity;
ShuntingYard::ShuntingYard () = default;
bool hasOnlyDigits(const string s){
return s.find_first_not_of( "0123456789" ) == string::npos;
}
int getPrecedence(const string s) {
for(int i = 0; i < operators.size(); i++) {
if (s == operators[i])
return precedence[i];
}
}
char getAssociativity(const string s) {
for(int i = 0; i < operators.size(); i++) {
if (s == operators[i])
return associativity[i];
}
}
vector<string> parse(const string input) {
// Parses the string by white space
istringstream ss(input);
vector <string> tokenVector;
// Fill vector with ss
for (string input; ss >> input;) {
tokenVector.push_back(input);
}
return tokenVector;
}
string toRPN(const string s) {
// Delimit string by white space and store in vector
vector <string> tokens = parse(s);
// Test print
for (int i = 0; i < tokens.size(); i ++)
cout << tokens[i];
//Change "rt" to "$" to be easily accessed
for (int i = 0; i < tokens.size(); i ++) {
if (tokens[i] == "rt")
tokens[i] = "$";
}
// Stores operators and their precedence/associativity to vectors using same index
operators.push_back("+"); precedence.push_back(2); associativity.push_back('L');
operators.push_back("-"); precedence.push_back(2); associativity.push_back('L');
operators.push_back("/"); precedence.push_back(3); associativity.push_back('L');
operators.push_back("*"); precedence.push_back(3); associativity.push_back('L');
operators.push_back("^"); precedence.push_back(4); associativity.push_back('R');
operators.push_back("$"); precedence.push_back(4); associativity.push_back('R');
// Shunting-Yard logic
while (tokens.size() != 0) {
for (int i = 0; i < tokens.size(); i++) {
if (hasOnlyDigits(tokens[i]))
outputList.push(tokens[i]);
if ( find(operators.begin(), operators.end(), tokens[i]) != operators.end()) {
while (getPrecedence(stack1.top()) > getPrecedence(tokens[i]) || (getPrecedence(stack1.top()) == getPrecedence(tokens[i]) &&
getAssociativity(tokens[i]) == 'L') && stack1.top() != "(") {
outputList.push(stack1.top());
stack1.pop();
stack1.push(tokens[i]);
}
}
if (tokens[i] == "(")
stack1.push(tokens[i]);
if (tokens[i] == ")")
while(!stack1.empty() && stack1.top() != "(") {
outputList.push(stack1.top());
stack1.pop();
}
stack1.pop();
}
if (tokens.size() == 0) {
while(!stack1.empty()) {
outputList.push(stack1.top());
stack1.pop();
}
}
}
// Replaces values with "$" back to "rt"
string str;
while (!outputList.empty()) {
if (outputList.front() == "$") {
str.insert(0,"rt");
outputList.pop();
}
else {
str.insert(0, (outputList.front()));
outputList.pop();
}
}
return str;
}
int main() {
string s1 = "3 + 4";
cout << toRPN(s1);
}
Update:
I have narrowed the issue down to the following while loop:
while (getPrecedence(stack1.top()) > getPrecedence(tokens[i]) || (getPrecedence(stack1.top()) == getPrecedence(tokens[i]) &&
getAssociativity(tokens[i]) == 'L') && stack1.top() != "(") {
outputList.push(stack1.top());
stack1.pop();
stack1.push(tokens[i]);
}
The line getPrecedence(stack1.top() > getPrecedence(tokens[I]) is the issue. In particular, running getPrecedence on the stack1.top(). This function basically takes in a string and compares it to the vector holding all of the operators that are stored. When it finds the index, it returns the precedence at that index (they are set up with all the indices in order). I don't see why I can't call this function in this way. The stack1.top() will just give a string which would be passed through and compared. Any thoughts?
Figured it out. There were a few things going one, but the main one which was haunting the program was that I was popping things off the stack when I shouldn't, resulting in the stack being empty, so it would never get into
while (getPrecedence(stack1.top()) > getPrecedence(tokens[i]) || (getPrecedence(stack1.top()) == getPrecedence(tokens[i]) &&
getAssociativity(tokens[i]) == 'L') && stack1.top() != "(")
So I've tried to solve this, an algorithm which counts and prints the number of vowels which are found between two consonats in a string.
I've made a program but it keeps giving me the wrong answers and I really don't know what could be wrong.
For example, for input: "oasele sunt fragile" it should print 4 but it actually prints 5.
#include <iostream>
#include <cctype>
#include <string.h>
using namespace std;
char s[255];
int isvoc(int i)
{
char c=tolower(s[i]);
if (isspace(c)) return 0;
else
if ((c=='a') || (c=='e') || (c=='i') || (c=='o') || (c=='u')) return 1;
else return 0;
}
int main()
{
cin.get(s,255);
int l=strlen(s),nr=0;
for (int i=1;i<l-1;i++)
if (!(isvoc(i-1)) && (isvoc(i)) && !(isvoc(i+1))) nr++;
cout<<nr;
}
You are counting vowels that appear between non-vowels. So in "a e i" you will get a count of 1, not 0. You would need:
if (iscon(i-1) && isvoc(i) && iscon(i+1))
Where you can implement iscon() any number of ways, such as
bool iscon(int i) { return isalpha(str[i]) && !isvoc(i); }
I am trying to code a program where it takes a program as an input and prints out all the comments written in that program in a separate line.
#include <cmath>
#include <cstdio>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
int main() {
string str;
while(getline(cin,str)) {
int i;
// cout<<str;
for(i=0;str[i]!='/' && str[i+1] !='/';i++);
//cout<<i;
for(i;str[i]!='\n';i++) {
// cout<<i;
cout<<str[i];
}
cout<<endl;
}
return 0;
}
I am getting a segmentation fault in this code and I can't understand why. This is part of a code of a problem in hackerrank https://www.hackerrank.com/challenges/ide-identifying-comments/copy-from/12957153
As commented in your question your code is wrong. First you are treating std::string object, returned by getline, as character array. Secondly your for loops never end if there is no // or \n found in input string. So obviously it will crash. Below is the modified code.
#include <cmath>
#include <cstdio>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
int main() {
string str;
while(getline(cin,str)) {
int i;
// cout<<str;
size_t len = str.length();
const char *cstr = str.c_str();
for(i=0; (cstr[i]!='/' && cstr[i+1] !='/' && i < len); i++)
//cout<<i;
for(; cstr[i]!='\n' && i < len;i++) {
// cout<<i;
cout<<cstr[i];
}
cout<<endl;
}
return 0;
}
int main() {
while(getline(cin,str)) {
int i, len = str.size();
//always make sure that you are not accessing
//contents after your string has ended
for(i=0; i < (len - 1) && !(str[i] == '/' && str[i+1] == '/'); i++);
//note that i here might be the last alphabet
//if there's no comment
if(i < len && str[i] != '/')
i++;
//checking if str[i] != '\n' is not a good idea
//as c++ stl strings are not temrinated by '\n'
if(i < len) {
for(; i < len; i++)
cout << str[i];
cout << endl;
}
}
return 0;
}
Also note that both of the following codes won't terminate at the 4th character, c++ stl strings are not terminated by these characters.
string str = "hahahaha";
str[4] = '\n';
cout << str;
str[4] = '\0';
cout << str;
This is much easier to write and probably much faster than the other solutions to date.
#include <iostream>
int main()
{
std::string str;
while (std::getline(std::cin, str))
{
size_t loc = str.find("//");
if (loc != str.npos)
{
std::cout << str.substr(loc + 2)<< std::endl;
}
}
return 0;
}
It is also wrong.
Here is a nice, clean, and simple state machine version. Also pretty close to worst-case for speed. Thing is it's closest to being right, even though it is also wrong.
#include <iostream>
enum states
{
seeking1,
seeking2,
comment
};
int main()
{
std::string str;
while (std::getline(std::cin, str))
{
states state = seeking1;
for (char ch:str)
{
switch (state)
{
case seeking1:
if (ch == '/')
{
state = seeking2;
}
break;
case seeking2:
if (ch == '/')
{
state = comment;
}
else
{
state = seeking1;
}
break;
case comment:
std::cout << ch;
break;
}
}
if (state == comment)
{
std::cout << std::endl;
}
}
return 0;
}
Why are these approaches all wrong? Consider the line
cout << "Hi there! I am \\Not A Comment!" << endl;`
You can't just look at the \\, you also need the context. This is why the state machine above is the better option. It can be modified to handle, at the very least, states for handling strings and block comments.
My program calculates the length of each word before space and compares it with a fixed number.
The number is chosen from another string (pi).
I don't know why but my variable FLAG is always set to false so I always get the same output.
I don't know where the problem is. Please help out
#include <iostream>
#include <cstdio>
#include <string>
#include <cmath>
#include <algorithm>
#include <iomanip>
using namespace std;
int main() {
int t=0,num;
int i,j,len,space;
bool FLAG;
string pi ="31415926535897932384626433833",song;
cin>>t;
while(t--){
len=0,space=0,i=0,j=0,num=0,FLAG=true;
cin.ignore();
getline(cin,song);
// problem from here
while(1) {
i=0,num=0,FLAG=true;
len=song.length();
space=song.find(' ');
if(space==-1){
if(len==pi[j]){
FLAG=true;
break;
}
else{
FLAG=false;
break;
}
}
else{
while(i<space){
num++;
i++;
}
if(num==pi[j]){
FLAG=true;
j++;
num=0;
i=0;
song.erase(0,space+1);
cout<<song<<endl;
}
else{
FLAG=false;
break;
}
}
}
// to here
if(FLAG==true){
cout<<"It's a pi song."<<"\n";
}
else{
cout<<"It's not a pi song."<<"\n";
}
}
return 0;
}
You are comparing an integer with a character value. i.e. you are comparing 3 with '3'. To get a number from a character digit, subtract '0'.
So you could write
if (len==(pi[j] - '0'))
Also, please learn to use a debugger, you can step through your code to find the line that doesn't work.