boolean expression in C - c

I found this expression in a C program and I didn't get it :
struct stack_rec *ss;
ss=(struct stack_rec *)EMalloc(sizeof(struct stack_rec));
if (ss) {
int res;
res = (ss->elem = * i , 1); // what does this mean ????
if (res <= 0)
return res;
if (*s == 0) {
ss->next = 0;
} else {
ss->next = *s;
}
*s = ss;
return 2;
}
return 0;
What does res = (ss->elem = * i , 1); mean? Is it a boolean expression? I've tried it with a 0 instead of 1 and it always returns the value of the second parameter! Can anyone explain this expression, please?

Looks broken. It's a use of the comma operator, which simply evaluates to the value of the final expression, i.e. 1.
Therefore, since that code is equivalent to:
ss->elem = *i;
res = 1;
The subsequent testing of res seem pointless, and thus broken.

The comma u see is a not very much used C operator.
Basically, what it does is execute the 2 statements (ss->elem = *i; and 1;). The statement 1; doesn't realy do much.
After that it returns the result from the last statement (in this case 1)

Related

Error: Expected expression before 'String' And too few arguments to function 'strcmp'

I've been trying to finish a part of our program for our groupings but whenever I try to compile there's always an error for this part of the code.
int
Binary_Search(String key, String Name[], int nElements)
{
/* Implement the body of this function. */
int position;
int begin = 0;
int end = String Name - 1; //Error: Expected expression before 'String'
int result = 0;
while(begin <= end)
{
position = (begin + end) / 2;
if(result = strcmp(String Name, nElements) == 0) //Error: Expected expression
//before 'String'
// too few arguments to
// Function 'strcmp'
return position;
else if(result < 0)
begin = position + 1;
else
end = position - 1;
}
}
First of all, end should be set to nElements-1.
Then this line has several problems:
if(result = strcmp(String Name, nElements) == 0)
The most obvious is that it should be strcmp(Name, nElements), assuming String is some horrid typedef for char* (from some bad class like CS-50?).
Also, nElements is an int, not a string, so it can't be compared with a string... supposedly you meant to do something like strcmp(Name[position], key).
Another problem is that result gets assigned the result of the expression strcmp(...) == 0 (which gives 1 or 0) rather than the result of strcmp (<0, or ==0, or >0) as you intended. It is bad practice to use = inside control/loop statements for this very reason, it always leads to bugs. You should change the code to this:
result = strcmp(Name[position], key);
if(result == 0)
return position;
else if(result < 0)
begin = position + 1;
else // if result > 0
end = position - 1;
We don't have string data type in c.
Try using char array to solve your issue. Also strcmp is used to compare char array(i.e. strings) not string with int.

I'm having a hard time using pass by reference

I don't know why I keep on getting errors in my code when I'm trying to do pass-by-reference, for finding the largest number of an integer using recursion.
My code works when it's pass-by-value, but I fail to do it correctly in pass-by-reference.
My main:
#include <stdio.h>
#include <math.h>
void largest_digit(int* digit);
int main() {
int num;
printf("\nPlease enter a number ");
scanf("%d", &num);
largest_digit(&num);
printf("The largest digit = %d\n", num);
return 0;
}
My function:
void largest_digit(int* digit) {
int hold, hold1;
if(*digit == 0 || *digit < 0) {
*digit = 0;
*digit;
return;
}
// If-statement with Recursion.
if(*digit > 0){
hold = *digit % 10;
hold1 = largest_digit(*digit/10);
if(hold > hold1) {
hold = *digit;
*digit;
return;
} else {
hold1 = *digit;
*digit;
return;
}
}
}
As someone said before, the largest_digit function is void, so it can't be assinged to a variable when is called. What you can do instead, is modifying *digit before the call, and then assign the value of *digit to what you want, in this case hold1.
Other thing is that you need to save the value into *digit before returning, for example, instead of doing hold = *digit, you should do *digit = hold.
Here are the suggested modifications:
void largest_digit(int* digit) {
int hold, hold1;
if(*digit == 0 || *digit < 0) {
*digit = 0;
return;
}
// If-statement with Recursion.
if(*digit > 0){
hold = (*digit) % 10;
(*digit) /= 10;
largest_digit(digit);
hold1 = *digit;
if(hold > hold1) {
*digit = hold;
return;
} else {
*digit = hold1;
return;
}
}
}
With this main,
int main() {
int a=123, b=652, c=3274;
largest_digit(&a);
largest_digit(&b);
largest_digit(&c);
printf("%d\n",a);
printf("%d\n",b);
printf("%d\n",c);
return 0;
}
the output is
3
6
7
You said you were passing it by reference, but you just tried to pass it by value here
hold1 = largest_digit(*digit/10);
Create a new int with *digit/10 and pass the address to largest_digit
int hold1Temp = *digit/10;
hold1 = largest_digit(&hold1Temp);
EDIT: Your function should be something like this:
void largest_digit (int* digit)
{
if (*digit <= 0) return; // if there's no more digit to compare, stop
int currentDigit = *digit % 10; // if you receive 982, it gets the 2
int nextDigit = *digit/10; // if you receive 982, it turns into 98
largest_digit(&nextDigit); // does the same thing again
*digit = currentDigit > nextDigit ? currentDigit : nextDigit; // chooses the biggest digit
}
A couple of things first:
The unary indirection operator (*) used on a pointer means "look at what is this pointing to". Therefore, the statement *digit; alone is not useful to anything. You can very well remove it from your code (I see you use it multiple times), perhaps you meant to do an assignment? The statement *digit = X; is an assignment and modifies the data pointed by the pointer.
"Passing by reference" does not exist in C. You can only pass by value. That value though can be a pointer to another value, that is how you "simulate" passing something by reference.
A function declared as void f(...) does not return any value. Therefore, assigning the "return value" of such a function to a variable does not make sense.
Now, considered the above:
Your call largest_digit(*digit/10) is not passing a pointer, but dereferencing the pointer digit, dividing the value by 10, and then passing that as parameter. As you already figured, this is wrong. To correctly pass by reference in your case, you would need to either modify the original value pointed to by digit, or create a new one and pass its address.
In any case, passing a pointer around (instead of the value directly) for this kind of recursive function does not make much sense and is only a complicated twist that does not accomplish much other than making your life harder. Use a plain value as argument.
int largest_digit(int num) {
if (num < 0)
return largest_digit(-num);
if (num == 0)
return 0;
int cur = num % 10;
int next = largest_digit(num / 10);
if (cur > next)
return cur;
return next;
}
int main(void) {
printf("%d\n", largest_digit(1923)); // 9
printf("%d\n", largest_digit(4478)); // 8
printf("%d\n", largest_digit(-123)); // 3
}
NOTE: for simplicity, the above function also handles negative numbers by calling largest_digit(-num) if the number is negative, therefore it only supports negative digits down to INT_MIN+1 (that is, it does not correctly handle INT_MIN).
Your trouble is that other than the case where *digit is negative, you never actually set *digit. Each time you do this:
*digit;
The above only dereferences the pointer and looks up the value, but it doesn't actually change it. What you need to do on each of your return routes is to actually set the value to something:
*digit = ...something...;
Without setting this value anywhere, the value of num in your main() function is never actually going to change.
In addition, you are treating largest_digit as if it has a return value, which it does not:
hold1 = largest_digit(*digit/10); // <- assigning the return value does not make sense

Tokenize negative numbers. Convert an infix expression to postfix with negative values using RPN

So I'm trying to make a working calculator using RPN (reverse polish notation), however, it works perfectly fine using positive numbers and doing a simple substract like (3*4-2+5)/3*2 which postfix expression is 34*2-5+3/2* and 10 as result. The thing is I'm not sure how to implement negative numbers, such as (-4+2*2), in this case the postfix expression should be ??? (4-22*) ??? (I'm not sure about this one) but the result should be 0
I've already made a tokenizer which prints the type of each token and its value. I.e:
Input: (2*3+4-5)
Output:
(Infix expression) | (Postfix Expression)
Parenthesis [(] Number[2]
Number [2] Number[3]
Operator [*] Operator[*]
Number [3] Number[4]
Operator [+] Operator[+]
Number[4] Number[5]
Operator [-] Operator[-]
Number [5]
Parenthesis [)]
Result: 5.0
However, when I try to use a negative number expression like the one above (-4+2*2) I get an error "Stack Underflow" because when I try to convert it I get:
(Infix Expression) | (Postfix Expression)
Parenthesis [(] Number[4]
Operator [-] Operator[-]
Number [4] Number[2]
Operator [+] Number[2]
Number [2] Operator[*]
Operator [*] Operator[+]
Number [2]
Parenthesis [)] ^^^^ Therefore, when I use my InfixToPostfix function,
It cannot find a number before the first [4] to do the [-]
operation, hence, in the "pop" function it prints the "Stack Underflow" error.
How can I fix this? I'm trying to fix it in the Tokenizer function which is the follow one:
Token.c:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "token.h"
/* Works using enum within the "token.h" and the TToken struct, defined as follows:
extern char strToken[][11];
typedef enum {variable, parentesis,operador, numero} tipoToken;
typedef struct{
tipoToken tipo; //Type of the token
char token[20]; //Content of that token
} TToken;
/*
char strToken[][11] = {"Variable", "Parentesis","Operador", "Numero"}; //Variable, Parenthesis, Operator, Number
int esOperador(char c) //isOperator function, which evaluates the valid nonalpha&&nondigit characters
{
int k;
static char operadores[] = "+-*/^";
int l = strlen(operadores);
for (k=0; k<l; k++)
if (c == operadores[k])
return 1;
return 0;
}
int esParentesis(char c) // IsParenthesis function
{
if (c=='(' || c==')')
return 1;
return 0;
}
TToken *token(char *s)
{
static char cadena[1000]; // The aux variable that will store 's' (original string)
static char *actual; // Keeps a track where the string is
int k;
char res[1000];
TToken *unToken=NULL;
if (s != NULL) {
strcpy(cadena,s);
actual = cadena;
}
while ((*actual == ' ') || (*actual =='\n') || (*actual=='\t')) //Only reads the valid characters of the string
actual++;
if (*actual == '\0')
return NULL;
if ( (esOperador(*actual) == 1) ) { // If is an operator, then...
res[0] = *actual;
res[1] = '\0';
unToken=malloc(sizeof(TToken));
unToken->tipo=operador;
strcpy(unToken->token,res);
actual = actual + 1;
return unToken;
} else if ( (esParentesis(*actual) == 1) ) { //If is a parenthesis, then...
res[0] = *actual;
res[1] = '\0';
unToken=malloc(sizeof(TToken));
unToken->tipo=parentesis;
strcpy(unToken->token,res);
actual = actual + 1;
return unToken;
} else if (isdigit(*actual) || (*actual=='.')) { // Read float numbers
k = 0;
while ( (*actual != '\0') && (isdigit(*actual) || *actual == '.' ) ) {
res[k] = *actual;
actual = actual + 1;
k = k+1;
}
res[k] = '\0';
unToken=malloc(sizeof(TToken));
unToken->tipo=numero;
strcpy(unToken->token,res);
return unToken;
} else if (isalpha(*actual)) { //**I might use this one also to evaluate also variables (Idk how, yet)**
k = 0;
while ( (*actual != '\0') && isalpha(*actual)) {
res[k] = *actual;
actual = actual + 1;
k = k+1;
}
res[k] = '\0';
unToken=malloc(sizeof(TToken));
unToken->tipo=variable;
strcpy(unToken->token,res);
return unToken;
}
printf("Error: Incorrect expression\n");
exit(0);
}
After that call to the token function, I call the InfixToPostfix expression, but in my opinion, the "correct" tokenized expression should be sent to InfixToPostfix and therefore, I should change the "token" function to allow negative numbers (unary minus).
If you do have any question do not hesitate asking (Such as another used functions in my code)

Convert value to string using #define

My task is to convert a float or integer value to string in C. I can't use sprintf since I am working in embedded platform. So I thought to use something like this.
#define CURRENT(STRING,S_NO,VALUE) (str = "S"#S_NO#VALUE"A")
and invoking it like this
int a=10,b=20;
CURRENT(str,a,b);
So str should be S1020A. But I am getting SabA.
What am I doing wrong here?
Macros are evaluated before compilation so CURRENT(str,a,b); is expanded using the variable names a and b rather than their values which may only be available at runtime.
To convert an int to a char array at runtime without use of sprintf etc. use itoa if available or you could write a function like the following (untested!)
#define MAX_INT_STRING_BYTES (11)
void IntToString(int val, char* str)
{
char reversed[MAX_INT_STRING_BYTES]
int index, i = 0;
bool negative = false;
if (val == 0) {
*str++ = '0';
*str = '\0';
return;
}
if (val < 0) {
negative = true;
}
while(val != 0) {
reversed[index++] = (char)('0' + abs(val % 10));
val /= 10;
}
if (negative) {
*str++ = '-';
}
for (i = index; i > 0; i--) {
*str++ = reversed[i - 1]);
}
*str = '\0';
}
It only knows what the value of a and b is at runtime, and preprocessor directives are resolved at compile time. Thus what you're trying to do won't work.
You can however do something like:
#define CURRENT(STRING,S_NO,VALUE) sprintf(STRING, "S%i%iA", S_NO, VALUE)
Or just make it a function.
Or just call the sprintf directly instead of CURRENT.

Put a condition check and variable assignment in one 'if' statement

I am looking at some legacy C code and got confused. It is something like:
UINT A, B = 1;
if((A = B) == 1) {
return(TRUE);
} else {
return(FALSE);
}
We all know there will be a compiler warning if we do if(A = B), but here it looks like the 'if' is checking A against 1. Am I correct?
First, it assigns the value of B to A (A = B), then it checks if the result of this assignment, which is A and evaluates to 1, is equal to 1.
So technically you are correct: On the way it checks A against 1.
To make things easier to read, the code is equivalent to:
UINT A, B = 1;
A = B;
if(A == 1){
return(TRUE);
} else {
return(FALSE);
}
Rather, your code is always assigning B to A, and it is moreover checking whether the value of B (and thus also A) is equal to 1.
There's nothing "legacy" about this, this is generally a pretty handy idiom if you need the result of an operation but also want to check for errors:
int result;
if ((result = foo()) != -1)
{
printf("The result is: %i\n", result);
}
else
{
// panic
}
If you want to keep it on 1 line:
if ((A = B), A == 1)
does the same thing.
We are trying to avoid if statements to make code more readable.
UINT A, B = 1;
bool fResult = false;
fResult = (A == B);
return(fResult);
And if there must be an condition to act on (not) equality, see this example.
UINT A, B = 1;
bool fResult = false;
fResult = (A == B);
if(fResult)
{
doThis();
}
else
{
doThat();
}
return(fResult);
Correct. The value A has after the assignment will be compared to 1.
This code sample is equivalent to just:
return (TRUE);

Resources