I am trying to figure out why I get segmentation fault, and my guess is that it is in my recursive function, which simplifies a prefix notation operation.
For example:
"m + 4 4" Returns: "+ m 8"
During testing I get a segmentation fault signal:
Exited with signal 11 (SIGSEGV)
I believe though that the problem lies in my recusive function "Operate"
string Operate(stack<string> &S, queue<string> &Q)
{
S.push(Q.front());
Q.pop();
std::string::size_type sz;
string result = "";
if (IsOperator(S.top()) == true)
{
S.push(Operate(S, Q));
}
if (Q.empty() == false)
{
S.push(Q.front());
Q.pop();
if (IsOperator(S.top()) == true)
{
S.push(Operate(S, Q));
}
if (S.size() < 3)
return "wrong input";
string arg1 = S.top();
S.pop();
string arg2 = S.top();
S.pop();
string oper = S.top();
S.pop();
if (StringIsDigit(arg1) && StringIsDigit(arg2))
{
int a = stoi(arg1, &sz);
int b = stoi(arg2, &sz);
char o = oper.at(0);
int c = 0;
if (o == '+')
c = b + a;
else if (o == '-')
c = b - a;
else if (o == '*')
c = b * a;
else
return "e";
result = to_string(c);
}
else
result = oper + " " + arg2 + " " + arg1;
}
else
{
result = S.top();
S.pop();
}
return result;
}
or in the function StringIsDigit:
bool StringIsDigit(string arg)
{
bool result = true;
for (int i = 0; i < arg.size() && result == true; i++)
{
if ((arg.size() != 1) && (arg.at(0) == '-') && (arg.at(i + 1) != ' '))
i++;
else
result = isdigit(arg.at(i));
}
return result;
}
Link to the whole program code:
https://pastebin.com/04pfE55N
The answer was quite simple, my error: SEGFAULT was as many pointed out for me error in reading from memory, segmentation fault, wiki.
When did the segfault occur?
It was when my function StringIsDigit() tried to figure out if negative values over 2 characters was an integer. In the "if statement, when checking if the string was indeed an integer, say -100", I continued to read the string until I reached the end of the arg string, but with arg.at(i + 1). Leading to the code trying to access memory outside the string array.Thanks Struthersneil for finding this flaw!
Please look at my old StringIsDigit() to find out the of by one value error I made:
bool StringIsDigit(string arg)
{
bool result = true;
for (int i = 0; i < arg.size() && result == true; i++)
{
if ((arg.size() != 1) && (arg.at(0) == '-') && (arg.at(i + 1) != ' '))
i++;
else
result = isdigit(arg.at(i));
}
return result;
}
The solution
The solution I want to make sure that the string was an integer since my algorithm supports expressions, such as x+3. This means that I need to iterate through the string is call isdigit() on every character in the string array. Though '-' is not an integer, '-' is needed obviously to express a negative integer, so I made a flawed check as you can see in my old StringIsDigit(). Instead of using that conditional if statement, I checked if the first character '-' and the second is not a whitespace ' ', and then I just let the isdigit() function do the rest of the work.
bool StringIsDigit(string arg)
{
bool result = true;
//I only need to check if the first is a '-' char and
//the next char is not ' '.
for (int i = 0; i < arg.size() && result == true; i++)
{
if ((arg.size() != 1) && (arg.at(0) == '-') && (arg.at(1) != ' '))
i++;
else
result = isdigit(arg.at(i));
}
return result;
}
Related
I wanted to simplify algebraic expressions in c++. I started with something simple: removing brackets from a algebraic expression containing + and - operators. For example, a-(b-c) should be simplified to a-b+c. This link gives the answer to this question. Here is the source code:
#include <iostream>
#include <string.h>
#include <stack>
using namespace std;
// Function to simplify the string
char* simplify(string str)
{
int len = str.length();
// resultant string of max length equal
// to length of input string
char* res = new char(len);
int index = 0, i = 0;
// create empty stack
stack<int> s;
s.push(0);
while (i < len) {
if (str[i] == '+') {
// If top is 1, flip the operator
if (s.top() == 1)
res[index++] = '-';
// If top is 0, append the same operator
if (s.top() == 0)
res[index++] = '+';
} else if (str[i] == '-') {
if (s.top() == 1)
res[index++] = '+';
else if (s.top() == 0)
res[index++] = '-';
} else if (str[i] == '(' && i > 0) {
if (str[i - 1] == '-') {
// x is opposite to the top of stack
int x = (s.top() == 1) ? 0 : 1;
s.push(x);
}
// push value equal to top of the stack
else if (str[i - 1] == '+')
s.push(s.top());
}
// If closing parentheses pop the stack once
else if (str[i] == ')')
s.pop();
// copy the character to the result
else
res[index++] = str[i];
i++;
}
return res;
}
I tested the function on a-(b-c-(d+e))-f and it gave the result a-b+c+d+e-fÿï┌. Why is it producing weird characters?
I have a assingment were I need to code and decode txt files, for example: hello how are you? has to be coded as hel2o how are you? and aaaaaaaaaajkle as a10jkle.
while ( ! invoer.eof ( ) ) {
if (kar >= '0' && kar <= '9') {
counter = kar-48;
while (counter > 1){
uitvoer.put(vorigeKar);
counter--;
}
}else if (kar == '/'){
kar = invoer.get();
uitvoer.put(kar);
}else{
uitvoer.put(kar);
}
vorigeKar = kar;
kar = invoer.get ( );
}
but the problem I have is if need to decode a12bhr, the answer is aaaaaaaaaaaabhr but I can't seem to get the 12 as number without problems, I also can't use any strings.
try to put a repeated character when next is not numeric or end of string.
For prepare this, it needs to make number by parsing string.
about this, I recommend you to find how to convert string to integer in real time at C++.
bool isNumeric(char ch) {
return '0' <= ch && ch <= '9';
}
string decode(const string& s) {
int counter = 0;
string result;
char prevCh;
for (int i = 0; i < s.length(); i++) {
if (isNumeric(s[i])) { // update counter
counter = counter * 10 + (s[i] - '0');
if (isNumeric(s[i + 1]) == false || i + 1 == s.length()) {
// now, put previous character stacked
while (counter-- > 1) {
result.push_back(prevCh);
}
counter = 0;
}
}
else {
result.push_back(s[i]);
prevCh = s[i];
}
}
return result;
}
now, decode("a12bhr3") returns aaaaaaaaaaaabhrrr. it works well.
I am to implement a recursive program given the grammar. I understand the concept of recursion, but implementing it can be overwhelming.
I'm having trouble with strings with parenthesis.
Inputing "(b-c)" should result in it being a valid expression, but the output says invalid.
I've been tracing the program where it deals with the parenthesis, but i can seem to figure out where I am wrong.
Also, the program may not be perfect, but i'd like to address this issue. Thanks for any help.
Main prompts user for input. I only provided what I believe is necessary.
Main
if(i.findExpression(str)){
cout << str << " is legal infix expression.\n";
}
else{
cout << str << " is not a legal infix expression.\n";
}
The grammar to follow is:
expression = term | term + term | term - term
term = factor | factor * factor | factor / factor
factor = letter | (expression)
letter = a|b|...|z
Find Expression
bool infix::findExpression(string strExp){
int i;
int n = (int)strExp.length();
bool found = true;
for (i = 0; i < n; i++){
if((strExp.at(i) == '(') and (n != i)){ //
while((strExp.at(i)!=')') and (n != i)){ //
i++;
}
found = false;
}
else if((strExp.at(i) == '+' or strExp.at(i) == '-') and
(n != i))
{
found = true;
break;
}
else
found = false;
}// added
if(found){
return(findTerm(strExp.substr(0,i))&&findTerm(strExp.substr(i+1, n-(i+1))));
}
else{
return findTerm(strExp.substr(0,n));
}
}
Find Term
bool infix::findTerm(string strExp){
int n = (int)strExp.length();
bool found = true;
int i;
for(i = 0; i < n; i++){
if((strExp.at(i) == '(')and (n != i)){
while((strExp.at(i)!=')')and (n != i)){
i++;
}
found = false;
}
else if((strExp.at(i)=='*' or strExp.at(i)=='/')and (n != i)){
found = true;
break;
}
else
found = false;
}
if(found){
return(findFactor(strExp.substr(0,i)) && findFactor(strExp.substr(i+1, n-(i+1))));
}
else{
return findFactor(strExp.substr(0,n));
}
}
Find Factor
bool infix::findFactor(string strExp)
int i;
char ch;
int n = (int)strExp.length();
bool found = true;
ch = strExp.at(0);
if((n==1)&&islower(ch)){
return true;
}
else if(ch == '('){
for(i = n; i > 0; i--){
if((n-1 != i) and (strExp.at(i-1) == ')')){
found = true;
break;
}
else{
found = false;
}
}
if(found){
return findExpression(strExp.substr(1, i-1));
}
else{return false;}
}
else{return false;}
}
Recursive descent parsers typically have methods exactly reflecting the rules. The rules consume the corresponding input. Typically this is done by operating on some kind of stateful token stream.
If you want to use simple strings, one way to handle how much is consumed by a recursive call is to let the recursion return the new position (although I'd really recommend operating on a token stream instead, as you normally would use the return value to return the corresponding subtree).
In this case, for your example, the method for handling expressions would look similar to this:
// expression = term | term + term | term - term
// Returns the position in strExp after parsing, or -1 for errors.
int infix::parseExpression(string strExp) {
int pos = parseTerm(strExp);
if (pos == -1) { // Error signal
return -1;
}
if (pos >= strExp.length()) {
return pos; // done
}
if (strExp.at(pos) != '-' && strExp.at(pos) != '+') {
return -1; // error
}
return parseTerm(strExpr.substr(pos + 1));
}
// term = factor | factor * factor | factor / factor
int infix::parseTerm(string strExp) {
...
Comparing the result to the string length should provide whether the expression is valid. You can encapsulate this check in another method for convenience.
I am looking for better ways to optimize this function for better performance, speed its targeted towards embedded device. i welcome any pointers, suggestion thanks
function converts string BCD to Decimal
int ConvertBCDToDecimal(const std::string& str, int splitLength)
{
int NumSubstrings = str.length() / splitLength;
std::vector<std::string> ret;
int newvalue;
for (auto i = 0; i < NumSubstrings; i++)
{
ret.push_back(str.substr(i * splitLength, splitLength));
}
// If there are leftover characters, create a shorter item at the end.
if (str.length() % splitLength != 0)
{
ret.push_back(str.substr(splitLength * NumSubstrings));
}
string temp;
for (int i=0; i<(int)ret.size(); i++)
{
temp +=ReverseBCDFormat(ret[i]);
}
return newvalue =std::stoi(temp);
}
string ReverseBCDFormat(string num)
{
if( num == "0000")
{
return "0";
}
else if( num == "0001")
{
return "1";
}
else if( num == "0010")
{
return "2";
}
else if( num == "0011")
{
return "3";
}
else if( num == "0100")
{
return "4";
}
else if( num == "0101")
{
return "5";
}
else if( num == "0110")
{
return "6";
}
else if( num == "0111")
{
return "7";
}
else if( num == "1000")
{
return "8";
}
else if( num == "1001")
{
return "9";
}
else
{
return "0";
}
}
Update
this is what i plan to get, for a BCD Value::0010000000000000 Decimal Result 2000
BCD is a method of encoding decimal numbers, two to a byte.
For instance 0x12345678 is the BCD representation of the decimal number 12345678. But, that doesn't seem to be what you're processing. So, I'm not sure you mean BCD when you say BCD.
As for the code, you could speed it up quite a bit by iterating over each substring and directly calculating the value. At a minimum, change ReverseBCDFormat to return an integer instead of a string and calculate the string on the fly:
temp = temp * 10 + ReverseBCDFormat(...)
Something like that.
What you call BCD is not actually BCD.
With that out of the way, you can do this:
int ConvertBCDToDecimal(const std::string& str, int splitLength)
{
int ret = 0;
for (unsigned i = 0, n = unsigned(str.size()); i < n; )
{
int v = 0;
for (unsigned j = 0; j < splitLength && i < n; ++j, ++i)
v = 2*v + ('1' == str[i] ? 1 : 0); // or 2*v + (str[i]-'0')
ret = 10*ret + v;
}
return ret;
}
Get rid of all the useless vector making and string copying. You don't need any of those.
Also, I think your code has a bug when processing strings with lengths that aren't a multiple of splitLength. I think your code always considers them to be zero. In fact, now that I think about it, your code won't work with any splitLength other than 4.
BTW, if you provide some sample inputs along with their expected outputs, I would be able to actually verify my code against yours (given that your definition of BCD differs from that of most people, what your code does is not exactly clear.)
as soon as you're optimizing function, here is different variant:
int ConvertBCDToDecimal(const std::string& str) {
unsigned int result = 0;
const std::string::size_type l = str.length();
for (std::string::size_type i = 0; i < l; i += 4)
result = result * 10 + ((str[i] - '0') << 3) + ((str[i + 1] - '0') << 2) + ((str[i + 2] - '0') << 1) + (str[i + 3] - '0');
return result;
}
note: you don't need splitLength argument, as you know that every digit is 4 symbols
I'm writing a program that converts an expression from infix to postfix. I have the conversion part down but when it comes to evaluating the postfix expression, I run into problems with converting from char to int using the stack.
I keep getting the error: "Exception in thread "main" java.lang.ClassCastException: java.lang.Character cannot be cast to java.lang.Integer"
It might be in this part of the code below where the problem is but I'm not sure:
Integer x1 = (Integer)stack2.pop();
Integer x2 = (Integer)stack2.pop();
Thank you!
public class Calc {
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
System.out.println("Please enter your infix expression: ");
Scanner scanner = new Scanner(System.in);
String input = scanner.nextLine();
String postfix = "";
Stack<Character> stack = new Stack<Character>();
for(int i = 0; i < input.length(); i++){
char subject = input.charAt(i);
if (subject == '*'||subject == '+'||subject == '-'||subject == '/'){
while ((stack.empty() == false) && (order(stack.peek()) >= order(subject)))
postfix += stack.pop() + " ";
stack.push(subject);
}
else if(subject == '(')
{
stack.push(subject);
}
else if(subject == ')')
{
while(stack.peek().equals('(') == false){
postfix += stack.pop() + " ";
}
stack.pop();
}
else{
if((Character.isDigit(subject) == true) && ((i + 1) < input.length()) && (Character.isDigit(input.charAt(i+1)) == true))
{
postfix += subject;
}
else if(Character.isDigit(subject))
{
postfix += subject + " ";
}
else
{
postfix += subject;
}
}
}
postfix += stack.pop();
System.out.println("Your post-fix expression is: " + postfix);
char subject2;
int yeah;
Stack stack2 = new Stack();
for (int j = 0; j < postfix.length(); j++){
subject2 = postfix.charAt(j);
if(Character.isDigit(subject2) == true){
stack2.push(subject2);
}
if(subject2 == ' '){
continue;
}
else{
Integer x1 = (Integer)stack2.pop();
Integer x2 = (Integer)stack2.pop();
if (subject2 == '+'){
yeah = x1 + x2;
}
if (subject2 == '-'){
yeah = x1 - x2;
}
if (subject2 == '*'){
yeah = x1 * x2;
}
if (subject2 == '/'){
yeah = x1 / x2;
}
else {
yeah = 0;
}
}
}
yeah = (int) stack2.pop();
System.out.println("The result is:" + yeah);
}
static int order(char operator)
{
if(operator == '+' || operator =='-')
return 1;
else if(operator == '*' || operator == '/')
return 2;
else
return 0;
}
}
You can solve this by casting to int. Note that int and Integer are not the same:
Integer x1 = (int) stack2.pop();
Integer x2 = (int) stack2.pop();
no casting is necessary by using type-information
Stack<Integer> stack2 = new Stack<Integer>();
…
if(Character.isDigit(subject2) == true){
stack2.push( Character.getNumericValue( subject2 ) );
}
…
to prevent an empty stack exception I'd prefer poll over pop
so it is easier to check an error condition
eg. if( x1 == null ) System.err.println( "Your error message" );
Deque<Integer> stack2 = new ArrayDeque<Integer>();
…
Integer x1 = stack2.poll();
Integer x2 = stack2.poll();
…
btw: the program is syntactically wrong, because it puts only one value on the stack