I have written a stack based interpreted language in C. The interpreter works with reading a file line by line and executing the line depending on the operation. print(1 + 1) in python would become 1 1 + print.
Here is the function to check what the operation is and push it to the stack or do an operation on it:
if (strncmp(op, "+", 1) == 0 && is_definition == 0)
{
float a = pop(stack);
float b = pop(stack);
push(stack, a + b);
}
else if (strncmp(op, "-", 1) == 0 && is_definition == 0)
{
float a = pop(stack);
float b = pop(stack);
push(stack, b - a);
}
else if (strncmp(op, "*", 1) == 0 && is_definition == 0)
{
float a = pop(stack);
float b = pop(stack);
push(stack, a * b);
}
else if (strncmp(op, "/", 1) == 0 && is_definition == 0)
{
float a = pop(stack);
float b = pop(stack);
push(stack, b / a);
}
else if (strncmp(op, "print", 5) == 0 && is_definition == 0)
{
float a = pop(stack);
if(a == (int)a)
printf("%d\n", (int)a);
else
printf("%f\n", a);
}
else if (strncmp(op, "define", 6) == 0 && is_definition == 0)
{
is_definition = 1;
}
else if (is_definition == 1)
{
}
else if (strncmp(op, "end", 3) == 0 && is_definition == 1)
{
is_definition = 0;
}
else
{
push(stack, atoi(op));
}
This is inside a loop that iterates over every space separated operation in the code.
I want to add a definition system a bit like the one in C.
This is the syntax I would like to have
define TEST 10 end
I would like to use this a bit like a variable system where you can use TEST.
In pseudo code, you should do the following:
Read a line of source
If it is a definition, parse+store it and skip the rest
(it is not a definition) execute, much like the code you posted
About "parse+store" the definitions, you need - for example - a couple of arrays, or an array of structs. You need to store each "name" (the alias, or the name of the definition) and, along with each name, its value.
Then, in the code you posted, you should implement the push() instruction (you only mention pop()). The push() instruction reads an operand and determines if it is an alias (definition) or not:
(push pseudo code)
Get the operand
Determine if it is a definition. Basically, you iterate on all the stored definitions to find a correspondence
Got the final value, put it on the stack
There are several things that could be said... a couple of them, in sparse order:
The pushed operand is a number? In this case you can skip the definition(s) checking, assuming that it is illegal to say "define 10 20"
Would you allow to (re)define operators?
Would you allow a definition to refer to other definitions?
...
Related
How can I simplify below if statements?, I'm trying to achieve the possibly most efficient code.
// doSomething based on x value and y value
void doSomething(x int, y int) {
//x not zero and y not zero
if (x != 0 && y != 0) {
//do a
//do b if x greater or equal y
//else do c
if (x >= y) {
//do b
} else (x < y) {
//do c
}
return;
}
//do b if x not zero and y zero
if (x != 0 && y == 0) {
//do b
return;
}
//do e if both x and y zero
if (x == 0 && y == 0) {
//do e
return;
}
}
What is the most concise and efficient way to simplify?
As it stands, your code is equivalent to:
if (x == 0)
{
if (y == 0)
do e
}
else if (y != 0)
{
if (x < y)
do a,c
else
do a,b
}
In particular:
if x=0 && y!=0 or y=0 && x!=0, then do nothing;
the two branches //do b if x not zero and y zero and //do d if x zero and y not zero are unreachable in your code.
History:
The code in the question was changed several times. This answer is based on the original version of the code. That code is shown below, minimally modified so that it's compilable C code:
void original(int x, int y)
{
if (x == y && x != 0 && y != 0) {
// do a
// do b
return;
}
if (x < y && x != 0 && y != 0) {
// do a
// do c
return;
}
if (x > y && x != 0 && y != 0) {
// do a
// do b
return;
}
if (x != 0 && y == 0) {
// do a
// do b
return;
}
if (x == 0 && y != 0) {
// do a
// do d
return;
}
if (x == 0 && y == 0) {
// do e
return;
}
}
Motivation:
The advantage of the original code is that it clearly covers all possible input combinations.
The first three if statements handle the cases where x and y are non-zero (with x==y, x<y, and x>y handled separately). Then the remaining three if statements handle the cases where one or both are zero. That covers everything.
The disadvantages of the original code are:
Many of the comparisons are repeated several times, e.g. y != 0 is checked four times. Given that branching statements tend to be time consuming in contemporary (year 2021) processors, redundant comparisons are something to be avoided 1.
The code violates the DRY principle. Specifically, do a appears in five locations, and do b appears in three locations. So any refactoring of the code should attempt to eliminate the repetition.
1) The optimizer may be able reduce the number of comparisons. However, that's hard to test without real code.
Refactoring with nested if statements:
If we focus on the DRY principle first, we notice that a appears in 5 of 6 code blocks. Only the case for e doesn't invoke a. So the logical choice is to handle e first. This results in the following code structure:
if (x == 0 && y == 0) {
// do e
} else {
// do a
// everything else (note that either x is not zero, or y is not zero)
}
Within the "everything else", we have do b three times, do c once, and do d once. So the next step is to handle c and d, leaving only b. The refactored code looks like this:
void nestedIf(int x, int y)
{
if (x == 0 && y == 0) {
// do e
} else {
// do a
if (x == 0) {
// do d
} else {
if (y != 0 && x < y) {
// do c
} else {
// do b
}
}
}
}
Refactoring with early return statements:
Some coding standards insist that a function shall only return from one location. The nested if code meets that requirement, but at the cost of being a little messy due to nesting. Using early returns eliminates the nesting, and may allow the code for a thru e to be implemented inline without additional functions (assuming they're only a few lines each). The refactored code looks like this:
void earlyReturn(int x, int y)
{
if (x == 0 && y == 0) {
// do e
return;
}
// do a
if (x == 0) { // x is zero and y is not zero
// do d
return;
}
if (y != 0 && x < y) { // x and y are both not zero, and x < y
// do c
return;
}
// do b
}
assuming a(), b(), and e() have the same type (fxtype)
fxtype *fx[4] = { e, NULL, b, a }; // NULL when x==0, y!=0
fx[2*!!x + !!y](x, y);
Change a to include c() and b()
int a(int x, int y) {
// do previous a()
if (x < y) c(x, y); else b(x, y);
return 0;
}
I have the code below, but I need the code to account for white spaces and double digits, for example if i enter (7-3)/(2+2) it should come out 73-22+/ result: 1. If i enter (7 - 3) / (2 + 2) it should come out 7 3 - 2 2 + / result 1. If I enter (22 - 10)/(2 + 2) it should come out 22 10 - 2 2 + / Result: 3
Here is the code I have:
#include<stdio.h>
char stack[100];
int top = 0;
int eval_top = -1;
int eval_stack[100];
void push(char x) // Push char into stack
{
stack[top++] = x;
}
char pop() // Pop char to top of stack
{
if (top == -1)
return -1;
else
return stack[top--];
}
/* functions for evaluation of postfix expression */
// push function
void eval_push(int x) { // Find push result
eval_stack[++eval_top] = x;
}
// pop function
int eval_pop() { // Find pop result
if (eval_top == -1) {
return -1;
} else {
return eval_stack[eval_top--];
}
}
int priority(char x) // check priority order
{
if (x == '(')
return 0;
if (x == '+' || x == '-')
return 1;
if (x == '*' || x == '/')
return 2;
}
// function to evaluate the postfix expression
void EvalPostfix(char postfix[]) {
int A, B;
int val;
char ch;
int i;
//find postfix
for (i = 0; postfix[i] != ')'; i++) {
ch = postfix[i];
if (isdigit(ch)) {
eval_push(ch - '0');
} else if (ch == '+' || ch == '-' || ch == '*' || ch == '/') {
A = eval_pop();
B = eval_pop();
switch (ch) {
case '*':
val = B * A;
break;
case '/':
val = B / A;
break;
case '+':
val = B + A;
break;
case '-':
val = B - A;
break;
}
eval_push(val); //send value on top of stack
}
}
printf("\n Result: %d \n", eval_pop());
}
main() {
int i = 0;
char * e, x;
char postfix[100]; // store postfix for later evaluation
char exp[100];
printf("Infix expression : ");
scanf("%s", exp); // asking the user to enter the infix expression
printf("Postfix expression: ");
e = exp;
while ( * e != '\0') {
if (isalnum( * e)) { // if character is alphabet or number , it is printed
printf("%c", * e);
postfix[i++] = * e;
} else if ( * e == '(') // if it is open parenthesis, it is pushed into the stack without any priority
push( * e);
else if ( * e == ')') // if it is closed parenthesis , pop the elements in the stack and print them until the we see ( symbol
{
while ((x = pop()) != '(') {
printf("%c", x);
postfix[i++] = x;
}
} else // if character is symbol like +, -, *, / then based on their priority character is pushed if it high priority otherwise high priority symbols are popped and it is pushed
{
while (priority(stack[top]) >= priority( * e)) {
x = pop();
printf("%c", x);
postfix[i++] = x;
}
push( * e);
}
e++;
}
while (top != -1) // printing remaining elements in the stack
{
x = pop();
printf("%c", x);
postfix[i++] = x;
}
postfix[i] = ')'; // this is to add at the end for detecting end by the evaluation function
EvalPostfix(postfix);
}
There are some problems in your code
your pop is not symmetric with your push, push post increment the index so pop must pre decrement the index, and because of that the first invalid index is not -1 but 0 :
char pop() // Pop char to top of stack
{
if (top == 0)
return -1;
else
return stack[--top];
}
priority does not return a value if all the tests are false, but probably the last test is useless
In
while (priority(stack[top]) >= priority( * e))
you missed to check if the stack is empty, must be :
while ((top != 0) && (priority(stack[top]) >= priority( * e))) {
Because the first invalid index for stack is 0 rather than -1
while (top != -1) // printing remaining elements in the stack
must be
while (top != 0) // printing remaining elements in the stack
When you make the postfix expression there is no separation between the numbers, for instance "12+3" becomes "123+" like "1+23", and in EvalPostfix you consider a number has only one digit (eval_push(ch - '0');), so you do not manage the numbers having more than 1 digit. To manage several digits add a separator after all numbers, for instance a space to have "12 3 +" or "1 23 +" and read the number with scanf etc
You do not make the right postfix expression in all the cases, for instance for 1+2*3 you make 12+3* but it must be 123*+
You do not detect the invalid infix expressions
in
while (priority(stack[top]) >= priority( * e))
I missed to say the top element is not stack[top] but stack[top - 1] so it must be replaced by
while ((top != 0) && (priority(stack[top - 1]) >= priority( * e))) {
adding that correction 1+2*3 produces the right postfix expression 123*+
Note it is more clear to introduce the function empty() and tops(), and in case of an invalid access into the stack print a message and exit rather than to return -1 as a char
int empty()
{
return (top == 0);
}
char tops()
{
if (top == 0) {
fputs("top() on the empty stack, abort", stderr);
exit(-1);
}
return stack[top - 1];
}
char pop() // Pop char to top of stack
{
if (top == 0) {
fputs("pop() on the empty stack, abort", stderr);
exit(-1);
}
return stack[--top];
}
also detect a possible overflow of the stack :
void push(char x) // Push char into stack
{
if (top == sizeof(stack)) {
fputs("stack overflow", stderr);
exit(-1);
}
stack[top++] = x;
}
so now you can do
while (!empty() && (priority(tops()) >= priority( * e))) {
Of course this is the same for the other stack
I need the code to account for white spaces and double digits
double digits is too restrictive, just manage any integer, for that you can extract the number using strtol. You cannot also read the full expression using scanf("%s", exp); because is stops on the first space, use fgets.
I'm a first time programmer trying to complete a simple command line program as part of the first assignment for an online course I am taking, but I seem to have hit a roadblock that I can't figure out with GDB or my own research.
After hours of rewrites, and hours of debugging, I finally got the code below to compile. The program is supposed to take a credit card number as an input, and then check whether it's valid per the specifications of the assignment. I used a test number from here: PayPal Test Credit Cards
The odd thing is, when I enter an AMEX card number, it correctly produces the text "AMEX", but when I try a Visa or a Master Card, it prints "INVALID".
In GDB I broke at the Verify function and it seems to incorrectly skip these two if/else if statements without proceeding to the Checksum function even though conditions appear to be met.
if (firstDigit == 4 && totalDigits == (13 | 16) && Checksum(cardNumber, totalDigits) == 0) // checks for a valid Visa.
...
else if (firstDigit == 5 && secondDigit == (1 | 2 | 3 | 4 | 5) && totalDigits == 16 && Checksum(cardNumber, totalDigits) == 0) // checks for a valid Mastercard.
...
The AMEX line of code that correctly executes is:
else if (firstDigit == 3 && secondDigit == (4 | 7) && totalDigits == 15 && Checksum(cardNumber, totalDigits) == 0) // checks for a valid American Express.
The arguments for all three lines seem to be formatted exactly the same. That is far as I could get in GDB though. I would print totalDigits, firstDigit, and secondDigit in GDB right before stepping through the above two non-executing lines and everything looked correct. So I'm stumped, why is the AMEX line executing, but not the others?
Thanks in advance everyone. This is the first program after hello.c that I've tried to write, so I am open to absolutely any criticism or suggestions if it looks like I'm doing something weird/wrong.
Full code:
checker.c
#include <stdio.h>
#include <stdlib.h>
int MAX = 16;
int* DigitSort(unsigned long long x, int* array);
int Verify(int* array);
int main (void)
{
int* output = malloc (sizeof(int) * (MAX + 2)); // creates a blank array for the individual digits of the card number.
unsigned long long userInput = 0;
do
{
printf("Please enter a credit card number:\n");
scanf("%lld", &userInput);
}
while (userInput <= 0); // checks to make sure the user entered a number.
switch(Verify(DigitSort(userInput, output))) // sorts the user's input into individual digits and verifies the card type and validity.
{
case 1 :
printf("VISA\n");
break;
case 2 :
printf("MASTERCARD\n");
break;
case 3 :
printf("AMEX\n");
break;
case 0 :
printf("INVALID\n");
break;
default :
printf("INVALID\n");
}
free(output);
return 0;
}
int Verify(int* array) // verifies whether or not a card number is valid. Must pass the function a sorted array of individual digits.
{
int* cardNumber = array;
int firstDigit = cardNumber[0];
int secondDigit = cardNumber[1];
int totalDigits = 0;
int Checksum(int* cardNumber, int totalDigits);
int i = 0;
while (firstDigit >= 1 && cardNumber[i] >= 0) // this step counts the number of digits in the array.
{
totalDigits = totalDigits + 1;
i++;
}
if (firstDigit == 4 && totalDigits == (13 | 16) && Checksum(cardNumber, totalDigits) == 0) // checks for a valid Visa.
{
return 1;
}
else if (firstDigit == 5 && secondDigit == (1 | 2 | 3 | 4 | 5) && totalDigits == 16 && Checksum(cardNumber, totalDigits) == 0) // checks for a valid Mastercard.
{
return 2;
}
else if (firstDigit == 3 && secondDigit == (4 | 7) && totalDigits == 15 && Checksum(cardNumber, totalDigits) == 0) // checks for a valid American Express.
{
return 3;
}
else // if the card number doesn't match any of the above conditions or fails the checksum, an 'I' for Invalid is returned.
{
return 0;
}
}
int* DigitSort(unsigned long long x, int* array) // takes a long long as input and sorts it into individual digits
{
int* arrayReversed = malloc (sizeof(int) * (MAX + 2)); // creates a new array to hold the reversed order of digits.
int i = 0;
arrayReversed[0] = 0;
if (i < (MAX - 1) && x >= 10)
{
do
{
arrayReversed[i] = x % 10;
x = x / 10;
i++;
}
while (i < (MAX -1) && x >= 10);
}
if (i < MAX && x >= 1 && x <= 9)
{
arrayReversed[i] = (int) x;
x = (x - x);
}
if (x == 0)
{
int j = 0;
do
{
array[j] = arrayReversed[i]; // sorts the digits from the reversed array and places them into the sorted array.
j++;
i--;
}
while (j < MAX && i >= 0);
array[j] = -1;
}
free(arrayReversed);
return array;
}
int Checksum(int* cardNumber, int totalDigits)
{
int sum1 = 0;
int sum2 = 0;
int i = (totalDigits - 2);
int j = (totalDigits - 1);
while (i >= 0)
{
sum1 = ((cardNumber[i] * 2)%10) + ((cardNumber[i] * 2)/10) + sum1;
i -= 2;
}
while (j >= 0)
{
sum2 = (cardNumber[j] + sum2);
j -= 2;
}
if (((sum1 + sum2) % 10) == 0)
{
return 0;
}
else
{
return 1;
}
}
Your first problem is here:
if (firstDigit == 4 && totalDigits == (13 | 16) && ...
You need to write:
if (firstDigit == 4 && (totalDigits == 13 || totalDigits == 16) && ...
Your first check is looking for 0x1D == 29 as the number of digits (because, as paisanco points out in a comment, the | operator is the bitwise OR operator), and no credit card needs 29 digits (yet, and not for a long time to come). Note the extra parentheses for clarity and accuracy. Don't mess around risking removing them — the code won't work properly again. And in general, be explicit if your condition has both && and || operators and use parentheses to group terms explicitly.
You have similar problems elsewhere. As it happens, (4 | 7) is the same value as 7, so the condition works when the second digit is 7 (but not when it is 4). But it doesn't mean what you intended it to mean.
Computer languages don't work the same as human languages. Get used to writing out the condition somewhat more verbosely. Some other languages provide shorthands for these conditions; C is not such a language.
I wanna compare 3 images at 3 different buttons, Xcode is allowing me to compare 2 images at a time but when i write code for 3 it gives a warning
"comparison between pointer and integer"
-(void)compare
{
if (b1.currentImage==b2.currentImage==b3.currentImage)
{
b1.enabled=NO;
b2.enabled=NO;
b3.enabled=NO;
NSLog(#"%#",b1.currentImage);
NSLog(#"%#",b2.currentImage);
}
else
{
UIImage *btnImage = [UIImage imageNamed:#"card.png"];
[b1 setImage:btnImage forState:UIControlStateNormal];
}
}
Generally spoken when you write :
a == b == c
that actually boils down to
(a == b) == c
thus you are comparing the result of the comparision of a and b (which is of type bool regardless of the types of a and b) to c which is of whatever the type of c is.
So in your case you compare b1.currentImage==b2.currentImage (which is of type int) to b3.currentImage which is a pointer type.
If yo want to compare three values for equality you have to write:
(a == b) && (a == c) instead of a == b == c
Try this small program and watch what it prints out:
int main()
{
int a = 2, b = 2 , c = 2 ;
if ((a == b) && (a == c ))
{
printf ("(a == b) && (a == c ) is true") ;
}
if ((a == b == c))
{
printf ("(a == b == c) is true") ;
}
return 0 ;
}
it will print
(a == b) && (a == c ) is true
because (a == b == c) is evaluated like this
1. (a == b) == c
2. (2 == 2) == 2
3. 1 == 2
4. false
Give a AST tree, I want to generate an assembly-like language. I'm trying using Sethi-Ullman algorithm but I have some questions in the algorithm implemetation.
What should I do when I run out of registers?
currently I do the following:
Emit a push REG where REG is the register of right subtree, evaluate left subtree, get one free register assign as register of right subtree and then emit a POP REG operation where REG is the register of right subtree too.
How should I implement the function to get a free register? currently I'm using an implementation like this instead of a stack-based:
enum Reg { Reg_r0, Reg_r1 };
Reg regs[] = { Reg_r0, Reg_r1 };
Reg getreg() {
static int c;
if(c == sizeof(regs) / sizeof(int))
c = 0;
return regs[c++];
}
Here's a pseudo-code (from C-language) how to implement it from what I unsertood(including the label() function)
// K is the number of registers available
int K = 2;
void gen(AST ast) {
if(ast.left != null && ast.right != null) {
int l = ast.left.n;
int r = ast.right.n;
if(l >= K && r >= K) {
gen(ast.right);
ast.n -= 1;
emit_operation(PUSH, ast.right.reg);
gen(ast.left);
ast.reg = getreg();
emit_operation(POP, ast.right.reg);
} else if(l >= r) {
gen(ast.left);
gen(ast.right);
ast.n -= 1;
} else if(l < r) {
gen(ast.right);
gen(ast.left);
ast.n -= 1;
}
ast.reg = getreg();
Reg r1 = ast.left.reg;
Reg r2 = ast.right.reg;
emit_operation(ast.type, r1, r2);
} else if(ast.type == Type_id || ast.type == Type_number) {
ast.n += 1;
ast.reg = getreg();
emit_load(ast);
} else {
print("gen() error");
// error
}
}
// ershov numbers
void label(AST ast) {
if(ast == null)
return;
label(ast.left);
label(ast.right);
if(ast.type == Type_id || ast.type == Type_number)
ast.n = 1;
// ast has two childrens
else if(ast.left not null && ast.right not null) {
int l = ast.left.n;
int r = ast.right.n;
if(l == r)
ast.n = 1 + l;
else
ast.n = max(1, l, r);
}
// ast has one child
else if(ast.left not null && ast.right is null)
ast.n = ast.left.n;
else
print("label() error!");
}
EDIT: Tell me please if more context is needed to understand this.
Sethi-Ullman is really just a scheduling algorithm, not a register allocation algorithm, so it just tells you the order in which to do operations to minimize the number of registers needed; it does not tell you which registers to use where.
So you need to combine it with a register allocation strategy -- usually just a greedy allocator. Then there's the question of what to do if you run out of registers -- do you insert spills inline, or abort and do something else?
In order to do simple greedy allocation inline with your scheduling and instruction generation (what you seem to be doing with your simple gen recursive procedure), you'll need to keep track of which registers are in use at any given time. The easiest way is by adding an extra in_use argument to your gen function:
typedef unsigned RegSet; /* using a simple bitmask for a set -- assuming that
* unsigned is big enough to have a bit per register */
void gen(AST *ast, RegSet in_use) {
if(ast->left != 0 && ast->right != 0) {
if (ast->left->n >= ast->right->n) {
gen(ast->left, in_use);
gen(ast->right, in_use | (1 << ast->left->reg));
} else {
gen(ast->right, in_use);
gen(ast->left, in_use | (1 << ast->right->reg)); }
ast->reg = ast->left->reg
emit_operation(ast->type, ast->left->reg, ast->right->reg);
} else if(ast->type == Type_id || ast->type == Type_number) {
ast->reg = pick_unused_register(in_use);
emit_load(ast);
} else ....
Note that you need a separate recursive pass to calculate n for each node (Sethi-Ullman inherently requires two traversals, with the first traversal computing bottom up the n value for the second traversal to use top-down).
Now the above code doesn't deal with running out of registers at all. To do that, you need to insert some spills. One way is to detect that all registers are in use before making a recursive call and spill then, restoring afterwards:
void gen(AST *ast, RegSet in_use) {
if(ast->left != 0 && ast->right != 0) {
Reg spill = NoRegister; /* no spill yet */
AST *do1st, *do2nd; /* what order to generate children */
if (ast->left->n >= ast->right->n) {
do1st = ast->left;
do2nd = ast->right;
} else {
do1st = ast->right;
do2nd = ast->left; }
gen(do1st, in_use);
in_use |= 1 << do1st->reg;
if (all_used(in_use)) {
spill = pick_register_other_than(do1st->reg);
in_use &= ~(1 << spill);
emit_operation(PUSH, spill); }
gen(do2nd, in_use);
ast->reg = ast->left->reg
emit_operation(ast->type, ast->left->reg, ast->right->reg);
if (spill != NoRegister)
emit_operation(POP, spill);
} else ...
Of course, this turns out to be not terribly efficient -- its usually better to spill sooner and refill later, but only when you know you're going to run out of registers.