Assign and compare in a single statement in C - c

How can I convert the following code to a single line?
int *i;
i = some_func_ret_int_ptr();
if(!i)
{
// Do something
}
// Will use 'i' later
I want to do something like:
if((i=some_func_ret_int_ptr) && !i)
{
// Do something
}
// Will use 'i' later
But I am wasting one comparison here. Is there a better way to do it?
All I want is assignment and comparison in the if and compare only i.

With C, this is as far as you can golf it:
int *i;
if(!(i = some_func_ret_int_ptr()))
{
// do something
}
// Will use i later

In addition to what is suggested in other answers, you can also do it as
if (i = some_func_ret_int_ptr(), !i)
{
// Do something
}
It is a literal implementation of what you had originally, with the statement sequence replaced with an expression sequence separated by the , operator.
It does not make much practical sense, though.

You can do
if(!(i = some_func_ret_int_ptr()))
{
...
}
What happens in this code, in order, is:
The return value of some_func_ret_int_ptr() is assigned to i
The statement !i is checked
If i == 0 what's inside the if gets executed, otherwise it will not

Clean and readable:
int * i = some_func_ret_int_ptr();
if (!i) { /* ... */ }

An option not mentioned yet is:
if ( NULL != (i = some_func()) )
Using the explicit comparison against NULL makes it very easy to read the intent of this code. Especially considering that your function probably won't have ret_int_ptr in its name.

Using the #include <ctype.h> standard library, to get the toupper(char) function, we can write the following function:
void StringToUppercase(char* str)
{
for (int i=0; (str[i] = toupper(str[i])) != 0; i++); // No for-loop body!
// The expression "(str[i] = toupper(str[i]))" executes first and then returns str[i]
}
so that the statement (str[i] = toupper(str[i])) != 0; both assigns a char and checks to see if it is '\0' or not.
The way this works is that part of the C language specifies that assignment expressions have the value of the lefthand expressions after the assignment. For example, with ints, consider the following code snippet:
int x = 5;
int y = x = 8;
// Assignment operators (= += <<=) have right-to-left associativity.
// The expression `(x=8)` returns the value 8, after it has been executed
int z = x != y; // Comparisons have greater (tighter) precedence than assignment
printf("(x, y, z) = (%d, %d, %d)\n", x, y, z); // prints (8, 8, 0)

Same as M.M's answer, but I would go with:
if ((i = some_func_ret_int_ptr()) != NULL)
As it makes the execution order clearer.

Related

How to sort strings without string.h library in C [duplicate]

This question already has answers here:
How to sort array of strings in ascending order in C
(6 answers)
Closed 2 months ago.
#include <stdio.h>
int main()
{
char * str[ ]={"C program", "Basic", "Foxbase+", "Fortran", "Pascal"};
int i,j;
char * temp;
int k;
for(i=0;i<4;i++)
{
k=i;
for(j=i+1;j<5;j++)
if(str[i] < str[j]) k=j;
temp=str[i]; str[i] = str[k]; str[k] = temp;
}
for(i=0;i<5;i++)
printf("%s\n",str[i]);
return 0;
}
I wanna sort the strings given above by the order of letter(ASCII), but I just couldn't do it, I already know that the wrong part of this code is the
if(str[i] < str[j]) k=j;
And I tried to fix it many times, just doesn't work out.
I already tried:
*str[i] < *str[j] (didn't work, which I think is reasonable?)
Btw, using string.h is not allowed, how can I make everything right here?
EDIT: sorry I posted this question that is silly, I didn't know that even if I couldn't use string.h, I can also use stdlib.h to use strcmp function, I was confused at that time but now everything is clear. Thanks for you guys spending time here, I appreciate it, and sorry again for asking this silly question.
As arising from the comments to the question you are not allowed to use any library functions – thus you need to compare those strings manually (note that you cannot just compare the pointers, these might be arbitrary addresses, you need to compare what the strings point to!) – and as you even don't seem to be allowed to write a separate function you need to inline this code as well.
In general string comparison might look as follows (here still as a function):
int cmp(char const* x, char const* y)
{
for(; *x && *y; ++x, ++y)
{
if(*x != *y)
// first position where the strings differ:
// x < y lexicographically if *x < *y, thus *x - *y < 0
// x > y analogously, so:
return *x - *y;
// this gives you the equivalence: x # y <=> cmp(x, y) # 0
// with # being any comparison operator
}
#if 0
if(*x)
return 1; // x is longer, thus x > y
if(*y)
return -1; // y is longer, thus x < y
return 0; // both equal
#else
// actually, as the null terminator is smaller than any other character
// anyway, we still can simply:
return *x - *y;
#endif
}
Edit: An even simpler solution (thanks #Lundin for the hint) just iterates as long as the strings yet can be equal:
while(*x && *x == *y) // covers *y being 0, too!
{
++x; ++y;
}
return *x - *y;
Side note: There's an issue with the comparison if your strings include values in the upper half of the character range (from 128 up to 255 inclusive; not an issue with your example): It is unspecified if raw char is signed or unsigned – which makes a difference on comparing characters not residing in the same half of the range of char (200 - 100 = 100 > 0 <-> -56 - 100 = -156 < 0). You can achieve more consistent behaviour over different platforms if you cast to unsigned char at any difference or comparison (above and below):
return static_cast<unsigned char>(*x) - static_cast<unsigned char>(*y);
Using such a function is, in general, the solution to prefer. Maybe you ask once more if you are allowed to write a new function after all!
Otherwise in your case you could reduce the code for testing on being smaller only, so:
char const* cur = str[j];
char const* min = str[k];
while(*cur && *cur == *min)
{
++cur; ++min;
}
if(*cur < *min)
{
// cur is lexicographically smaller or shorter than min!
// -> found a new minimum
k = j;
}
Rather than compare pointers with
if(str[i] < str[j]) // Compare pointers
code need to compare the strings refenced by those pointers.
if (strcmp(str[i], str[j])) // Compare strings
As OP is obliged to not use strcmp(), make your own by comparing the strings, one character at a time (as unsigned char) for equality (and not a null character). Report zero when the same or a negative or positive corresponding to the sign of the difference.
// Use const to allow for pointers to const strings.
int my_strcmp(const char *x, const char *y) {
// Convert to unsigned char * as `strcmp()` compares "as if"
// the characters were all unsigned.
const unsigned char *ux = (const unsigned char*) x;
const unsigned char *uy = (const unsigned char*) y;
// Test for equality and null character.
// I like to place the more likely to fail one first.
while ((*ux == *uy) && *ux) {
ux++;
uy++;
}
// On rare machines, using `return *ux - *uy` may overflow.
// To avoid overflow, use 2 tests.
// Good compilers see this idiom and emit efferent code.
return (*ux > *uy) - (*ux < *uy);
}

Expressions and for loops in C

Is this correct way of assigning an expression to a variable?
int a == ( i<3 );
And I want to use a for loop like this
for(i=0;a; i++)
The assignment operator is =. So the correct way to assign an expression to a variable is
int a = i < 3;
More accurately, this assigns the value of the expression to a variable. It does not assign the expression itself to the variable. This means that the expression is evaluated immediately. When you do
for(i=0;a; i++)
The value of a will never change even though i does.
The idiomatic way of writing for loops is to write the boolean expression inline:
for(i=0;i<3; i++)
If you have some more complicated calculation to determine when a loop should end, then you can write a function for the calculation. For example:
int condition(int i) {
return i < 3;
}
Now you can write the for loop as
for (i = 0; condition(i); i++)
You can use macros like following
#include <stdio.h>
#define a(i) i < 3
int main(void) {
for(int i =0; a(i); i++) {
printf("%d\n",i);
}
return 0;
}
Output
0
1
2
EDIT
As others said macro is not a good idea when the condition is large. In that case you can make a separate function for the complex logic and use that in your for loop condition part. Like following:
int a(i) {
return i < 3; // Your condition. It may be even more complex as per your requirement.
}
Then you can use that function in your for loop in the following way:
for(int i =0; a(i); i++ ){...}
You cannot do that, why would you even want to? Can you give me an example, where this would be useful? Just curious, maybe we find better solution :)
Also, you can read more about loops at http://en.cppreference.com/w/cpp/language/for

C: Why Bitwise AND works for special character

I'm trying to write simple program using c to compute the intersection between two strings using Bitwise AND operator Like :
char x[]="abcdefghijklmnopqrstuvwxyz";
char y[]="abcdefghijklmnopqrstuvwxyz";
int i,sum=0;
const int size = 26;
for(i=0;i<size;i++)
{
if(x[i]&y[i]==y[i]){
printf("%c",y[i]);
sum++;
}
}
printf("\n%d\n",sum);
After executing code i found the result :
acegikmoqsuw
13
what's the problem with my code or what's the reason for that ?
You should take care of operand precedence in the if:
char x[]="abcdefghijklmnopqrstuvwxyz";
char y[]="abcdefghijklmnopqrstuvwxyz";
int i,sum=0;
const int size = 26;
for(i=0;i<size;i++)
{
if((x[i] & y[i]) == y[i])
{
printf("%c",y[i]);
sum++;
}
}
printf("\n%d\n",sum);
Your code isn't strictly correct; if every x[i] were 0xff then it'd think that every character matched. All you're going to detect is anywhere that the relevant x has a 0 that the relevant y does not.
If the requirement is to use &, for whatever academic purpose, then run the test in both directions:
if( (x[i]&y[i])==y[i] && (x[i]&y[i])==x[i] )
i.e. if there are no bits set in y that are not also set in x and there are no bits set in x that are not also set in y then the two must have the same bit pattern.
Though, obviously:
if( x[i]==y[i] )
... is the intended means of testing for equality in C.
Your problem lies in the evaluation of the if statement
if(x[i]&y[i]==y[i])
the == operator has greater precedence than the & operator.
https://en.wikipedia.org/wiki/Operators_in_C_and_C%2B%2B#Operator_precedence
Try replacing it with this:
if( (x[i] & y[1]) == y[1] )

What is the utility of a bool variable in C?

What is the advantage of using bool variable in the code below instead of an int to set the value 1 or 0? What difference does it make?
#include<stdio.h>
int main(void)
{
int p,d;
_Bool isPrime;
for ( p = 2; p <= 50; p++){
isPrime = 1;
for (d = 2; d < p; d++)
if (p %d == 0)
isPrime = 0;
if (isPrime != 0)
printf("%i ",p);
}
printf("\n");
return 0;
}
It's useful for making your intent clear. When you declare a variable as Bool_, it's obvious it's never supposed to have a value other than true and false.
A more conventional way to write your example code would be:
#include
int main(void)
{
for (int p = 2; p <= 50; p++) {
bool isPrime = true;
for (int d = 2; d < p; d++) {
if (p % d == 0) isPrime = false;
}
if (!isPrime) printf("%i ", p);
}
printf("\n");
return 0;
}
I just use plain ints as my boolean type without any typedefs or special defines or enums for true/false values. If you follow my suggestion below on never comparing against boolean constants, then you only need to use 0/1 to initialize the flags anyway. However, such an approach may be deemed too reactionary in these modern times. In that case, one should definitely use since it at least has the benefit of being standardized.
Whatever the boolean constants are called, use them only for initialization. Never ever write something like
if (ready == TRUE) ...
while (empty == FALSE) ...
These can always be replaced by the clearer
if (ready) ...
while (!empty) ...
Note that these can actually reasonably and understandably be read out loud.
Give your boolean variables positive names, ie full instead of notfull. The latter leads to code that is difficult to read easily. Compare
if (full) ...
if (!full) ...
with
if (!notfull) ...
if (notfull) ...
Both of the former pair read naturally, while !notfull is awkward to read even as it is, and becomes much worse in more complex boolean expressions.
Boolean arguments should generally be avoided. Consider a function defined like this
void foo(bool option) { ... }
Within in the body of the function, it is very clear what the argument means since it has a convenient, and hopefully meaningful, name. But, the call sites look like
foo(TRUE);
foo(FALSE):
Here, it's essentially impossible to tell what the parameter mean without always looking at the function definition or declaration, and it gets much worse as soon if you add even more boolean parameters.. I suggest either
typedef enum { OPT_ON, OPT_OFF } foo_option;
void foo(foo_option option);
or
#define OPT_ON true
#define OPT_OFF false
void foo(bool option) { ... }
In either case, the call site now looks like
foo(OPT_ON);
foo(OPT_OFF);
which the reader has at least a chance of understanding without dredging up the definition of foo.

Is ++ the same as += 1 for pointers?

I'd like to refactor some old C code of mine, and I was curious if I can replace all ptr++ with ptr += 1 where ptris some pointer, without changing any behavior. Here's an example of what I mean, from K&R Section 5.3:
/* strlen: return length of string s*/
int strlen(char *s)
{
int n;
for (n = 0; *s != '\0'; s++)
n++;
return n;
}
When I replace the s++ with s += 1, I get the same results, but I'm wondering if this will be the case for all types. I also did a test for ints:
int size = 10;
int *int_array = (int*)calloc(size, sizeof(int));
for (int i = 0; i < size; i++)
int_array[i] = i;
for (int i = 0; i < size; i++) {
printf("*int_array = %d\n", i, *int_array);
int_array++;
}
If I replace the line int_array++; with int_array += 1;, I get the same result.
After thinking about this some more, I realize there could be a problem if the value is used in an expression. Would it be safer I just moved the increment onto another line like so:
int a = 5;
int b = a++;
would become:
int a = 5;
int b = a;
a += 1;
Conclusion
What I thought could be a problem, incrementing pointers of different types, is not a problem. See #bdonlan's response for the reason why.
This doesn't mean that you can replace all x++ with x += 1 and expect the same behavior. You can, however, replace ++x with (x += 1) safely, since they are equivalent.
a += 1 is equivalent to ++a (C99 §6.5.3.1/2). In a line like int b = a++; this means it is not equivalent to a++; a++ would return the old value of a, while a += 1 returns the new value.
Note that if you don't use the result of a++ (ie, you have a statement containing just a++;), then they are effectively identical.
Also, note that _all pointer arithmetic is done in increments of the pointed-to type's size (§6.5.6/8). This means that:
ptr = ptr + x;
is equivalent to:
ptr = (ptr_type *)( (char *)ptr + x * sizeof(*ptr) );
This is the same whether you use +, ++, +=, or [] (p[x] is exactly equivalent to *(p + x); you can even do things like 4["Hello"] because of this).
++ and -- is defined in terms of arithmetic for built-in types. The behavior will be the same, other than postfix returning the old value.
It's a good question. The answer is yes, you can do that -- no matter how you do it, incrementing a pointer adds sizeof(the type that the pointer points to) to the pointer. As other answers indicate, you do need to be careful that you don't depend on when the increment happens, i.e. a++ and ++a have different effect, but a eventually ends up with the same value.
A question is: why do you want to change all your code from a++ to a+=1? Using the post-increment operator with pointers is something that should be easily understood by any C programmer, so it's hard to understand why you'd make that change.

Resources