So i have a homework, but i can't wrap my head around why this code doesn't work.
Problem sounds something like this:
Make a code that checks all possible variations of 4 digit number, but there are no 3 same digits in a number. ( i hope that makes sense)
My code:
#include<stdio.h>
int main ()
{
int i;
char a,b,c,d;
for (i=0; i<9999; i++)
{
a = i/1000;
b = i/100%10;
c = i/10%10;
d = i%10;
if (a==b==c) {i++;}
else if (b==c==d) {i++;}
else if (c==d==a) {i++;}
else if (d==a==b) {i++;}
else if (a==b==c==d) {i++;}
else
{
printf("%d,%d,%d,%d\n", a,b,c,d);
}
}
}
I want it to print out something like this:
0,0,1,1
0,0,1,2
0,0,1,3
...
0,1,0,9
0,1,1,0
0,1,1,2
...
9,9,8,8
Instead it prints:
0,1,2,2
0,1,3,3
0,1,4,4
0,1,5,5
0,1,6,6
...
0,8,6,6
0,8,7,7
0,8,8,8
0,8,9,9
0,9,2,2
...
9,9,9,8
There's a problem with these comparisons:
if (a==b==c)
This doesn't find out if a, b and c are all the same. The result of == is 0 or 1, and then that is compared to the third number. So per example if all three numbers are 9, then 9==9==9 turns into 1==9, which is 0, so the if is not taken. What's more, you have false positives for things like 9==9==1.
What you instead need here is
if ((a==b) && (a==c))
Now you check if a is equal to b, and when it is, you check it with c, and the if is taken if they're all the same.
Likewise of course for the other comparisons, so instead of else if (a==b==c==d) you want else if ((a==b) && (a==c) && (a==d))
As other answers have noted, you can't chain comparison operators in C and get the expected results. Use logical operators to combine comparisons. It would probably be more clear to use || to avoid all of the else statements.
There is another significant problem with the posted code: i is incremented whenever a failing number is found. But then i is incremented again by the for loop. This causes the number after a failing number to be skipped, so some desired numbers will not be found. For example, 3222 should fail, and the subsequent number 3223 should pass, but this number is skipped by the posted code (after the comparison corrections), with the next number to be checked 3224. Instead, just use continue:
if ((a == b && a == c) ||
(b == c && b == d) ||
(c == d && c == a) ||
(d == a && d == b) ||
(a == b && a == c && a == d)) {
continue;
} else {
printf("%d,%d,%d,%d\n", a,b,c,d);
}
You can't use multiple equalities like this. You have to do them separately with and conditions (e.g. a==b && b==c).
Related
me again ... Sorry for asking maybe a little bit stupid questions but i am a starter and i really want to learn coding .. So i got a problem to realize why those are always true ? Its something with the operators or again C behavior is undefined. ?
int x;
int b;
b = 1 < x < 10;
printf("%d%d",b);
char c = 'z';
(c==' ') || (c='\t') || (c=='\n');
printf("%c",c);
Why those are always true ? Its because of ASCII code or what ?
Result of comparison of constant 10 with boolean expression is always true
You can see here a table for the C Operator Precedences
it could be read like this:
b = ((1 < x) < 10);
being that in languages such as C, relational operators return the integers 0 or 1, where 0 stands for false and any non-zero value stands for true.
so the value stored in b is 1 (true)
Also:
you're not initializing x, it should have trash info (probably != false)
and in your second code, you're allocating instead of comparing, (c='\t') is this on purpose? That's the reason it's printing a 'tab'.
In your first block of code, there are several problems:
x is uninitialized (you did not give it a value)
1 < x < 10 is not valid C
your printf statement expects 2 integer values to accompany the "%d%d", but you are only passing 1
I think this is what you want:
int x = <some valid value>;
int b;
b = ((1 < x) && (x < 10)); // expression is true if x is between [2..9]
printf("%d",b);
This line
(c==' ') || (c='\t') || (c=='\n');
Should be
(c==' ') || (c=='\t') || (c=='\n');
Note the double equals when comparing to \t (the tab character). Otherwise, you wind up assigning a tab char to c.
This question already has answers here:
Chaining multiple greater than/less than operators
(6 answers)
Two '==' equality operators in same 'if' condition are not working as intended
(4 answers)
Math-like chaining of the comparison operator - as in, "if ( (5<j<=1) )" [duplicate]
(4 answers)
Closed 3 years ago.
I'm learning C and I've came around a strange problem. I think I understand the difference between multiple ifs and else-if statement, but I simply can not understand the difference in behavior this time. If I delete the else keyword it works as intended, but with else on it does not.
The code is about counting of occurrences of each letter without differentiating lower case or upper case (so 'a' and 'A' both counts as 1 occurrence for letter 'a').
I've tried omitting braces where I could but nothings changed so I've left them in to avoid caveats.
while ((c = getchar()) != EOF)
{
if ('A' < c < 'Z')
{
++array[c - 'A'];
}
else if ('a' < c < 'z')
{
++array[c - 'a'];
}
}
When I type in 'a' then the array is not being incremented, but if I delete the else statement thus switching to a multiple if situation, it works as intended. Letter 'A' updates the array nicely in both cases.
Could you please help me understand the difference in behavior in this case?
What we need to know:
The result of < comparison is an int with value 1 for true and 0 for false. It's like the result of 1 + 3 is int with value 4, the same way the result of 1 < 3 is an int with value 1.
Operator < has associativity Left to Right. That means that in 1 < 2 < 3 it will be parsed as (1 < 2) < 3 - ie. first will be 1 < 2 calculated, then the result will be < 3 compared with 3.
So:
'A' < c < 'Z'
is interpreted as
('A' < c) < 'Z'
The result of 'A' < c is either 1 or 0. When 'A' is lower then c, then it becomes:
1 < 'Z'
otherwise it becomes:
0 < 'Z'
Both cases are true, so the comparison is always true.
If you want to check if a number is a letter between A and Z including the letters A and Z, you can:
if ('A' <= c && c <= 'Z') {
or #include <ctype.h> and use isupper function:
if (isupper(c)) {
try
while ((c = getchar()) != EOF)
{
if ('A' <= c && c <= 'Z')
{
++array[c - 'A'];
}
else if ('a' <= c && c <= 'z')
{
++array[c - 'a'];
}
}
'a'<c<'z' is computed not like a mathmatical expression, first 'a' < c is evaluated to True or False then that value (converted to 0 or 1 probably) is compared to 'z', so it is not doing what you are expecting it to.
The relational operators like < take two operands and returns 1 if the first operand is smaller than the second, otherwise 0.
Thus 'A' < c gives a result of 1 or 0, and then (since < operators associate left-to-right) you compare the value 1 or 0 with the ASCII value of 'Z', which is nonsense.
Correct code for checking if a variable is inside an interval is
if ( (c >= 'A') && (c <= 'Z') )
Also make sure c is int and not char, because getchar actually returns int, and to compare against EOF you will need to use int.
If I have two integer values I can test for equality simply:
if (a == b)
if I have three integer values then I could do something like:
if ((a == b) && (a == c) && (b == c))
I've got a situation where I've got 6 values to test for equality, this approach is going to get verbose
Is their a better, and more C idiomatic (c-onic?) means to achieve this?
actually, just having written this I can see that:
if ((a == b) && (b == c) && (c == d)... )
is logically ok, i.e. you don't need all the combinations as a == b and b == c implies a == c
But in terms of clarity of expression how close can I get to:
if (a == b == c) ?
You're not going to get very close to a == b == c.
To cause experienced C programmers the least surprise, I think this is best is
if(a == b && b == c && c == d && d == e && e == f)
i.e. basically like what you have already, with less parentheses. I'm not always opposed to adding parentheses that make no difference to the compiler to help humans who don't know all the precedence rules, but I think comparisons separated by && (with no || mixed in) are a simple enough case that the parentheses are more clutter than they're worth.
If the variable names are long, putting it all on one line isn't going to be pretty, so maybe
if(a == b &&
b == c &&
c == d &&
d == e &&
e == f)
or this might be better since the duplication of the the a in every line will be immediately noticeable:
if(a == b &&
a == c &&
a == d &&
a == e &&
a == f)
If you really want it to be compact, the p99 preprocessor library offers this:
#include "p99_for.h"
if(P99_ARE_EQ(a,b,c,d,e,f))
which looks like John Zwinck's answer but doesn't require a helper function.
I can show you how to do it in a variadic macro, so we can write this:
if(EQI(a, b, c, d, e, f))
Here's the code:
#include <stdarg.h>
#include <stddef.h>
#define NUMARGS(...) (sizeof((int[]){__VA_ARGS__}) / sizeof(int))
#define EQI(...) ( \
alleqi(NUMARGS(__VA_ARGS__), __VA_ARGS__))
/* takes count number of int arguments */
int alleqi(size_t count, ...)
{
va_list va;
va_start(va, count);
int v0 = va_arg(va, int);
for (; count > 1; count--) {
if (v0 != va_arg(va, int)) {
break;
}
}
va_end(va);
return count == 1;
}
Please be advised the above only works for int arguments (and probably other types whose size is the same as int, though I am bracing for someone to accuse me of promoting undefined behavior if I advertise that!).
Thanks to this prior post for figuring out how to count arguments in a variadic macro: https://stackoverflow.com/a/2124433/4323
If you want to check six values, one approach would be to store them in an array
int a[6];
equals = 1;
for (int i=0; i<5; i++)
{
if (a[i] != a[i+1])
{
equals = 0;
break;
}
}
Approaches using arrays require you to change your data structure into an array.
Approaches using a variadic macro requires an additional function and function call (overhead).
Except for these two approaches, the only other way I see is to write them out. I feel the best way, or the more clear way, is to take the first variable and compare it to all other variables. By implication then either all variabes are equal, or at least two variables are unequal:
if ((a == b) && (a == c) && (a == d)
&& (a == e) && (a == f) && (a == g) ...)
The first if statement is not working and code is running without considering the constraint.
#include <stdio.h>
int main(void)
{
int with;
int inacbal;
float acleft;
scanf("%d",&with);
scanf("%d",&inacbal);
if(0<=with<=2000&&0<=inacbal<=2000) //this statement not working
{
if((with%5)==0)
{
if(inacbal>with)
{
acleft=(float)inacbal-(float)with-0.50;
printf("%.2f",acleft);
}
else
printf("%d",inacbal);
}
else
printf("%d",inacbal);
}
return 0;
}
Even on inputting value greater than the constraint relation the loop is running.
While mathematicians sometimes use the shorthand a < b < c, the C language is a bit more strict.
You must rewrite:
if(0<=with<=2000&&0<=inacbal<=2000)
to be something like:
if((0 <= with) && (with <= 2000) && (0 <= inacbal) && (inacbal <= 2000))
What you have actually is valid C but it does not do what you would normally expect. The expression 1 < 2 < 3 actually means: calculate 1 < 2 (giving the integral truth value 0 or 1 for false and true respectively) then comparing that against 3.
If you want to use a shorter form, you can use something like:
#define between(a,b,c) (((a) <= (b)) && ((b) <= (c)))
:
if (between (0, with, 2000) && between (0, inacbal, 2000))
though you need to watch out for duplicated side effects if you use terms such as a++ when using it. A safer approach may be replacing the macro with something along the lines of:
int between (int a, int b, int c) {
return (a <= b) && (b <= c);
}
You cannot compare avariable to two other values like that. You should separate the conditions:
if ((0<=with) && (with<=2000) && ( 0<=inacbal) && (inacbal<=2000))
The statement
if(0<=with<=2000&&0<=inacbal<=2000)
is not checking variables between the given range. These comparisons doesn't have mathematical meaning in C.
Compiler should raise a warning
[Warning] comparisons like 'X<=Y<=Z' do not have their mathematical meaning [-Wparentheses]
To check whether a value is between a given range or not you need to use && operator. You need to rewrite it as
if(0 <= with && with <=2000 && 0 <= inacbal && inacbal <=2000)
My program compares the 2 strings entirely and does not stop once n number of characters are reached? Why does this happen?
int strncompare (const char* mystring1,const char* mystring2, int number)
{
int z;
z = number - 1;
while ((*mystring1==*mystring2) && (*mystring1 != '\0') && (*mystring2 != '\0'))
{
*mystring1++;
*mystring2++;
if ((*mystring1 == mystring1[z]) && (*mystring2 == mystring2[z]))
{
break;
}
}
return (mystring1++ - mystring2++);
}
Because you don't stop when you've compared number characters.
There are several ways to do this, but I would recommend changing your loop condition to
while (*mystring1 && *mystring2 && *mystring1 == *mystring2 && number-- > 0)
Also remove
if ((*mystring1 == mystring1[z]) && (*mystring2 == mystring2[z]))
{
break;
}
Because, although it seems like that was your attempt at making it stop, it's coded wrong; you don't care if the characters are the same, you only care if you've compared number characters. Also you use && which makes the condition even more restrictive than it already was.
Also change
*mystring1++;
*mystring2++;
To
mystring1++; // or better, ++mystring1
mystring2++; // or better, ++mystring2
The * dereferences the pointer but you're not doing anything with it so it's pointless (pun intended).
You also can remove the ++ from these:
return (mystring1++ - mystring2++);
So it would be
return mystring1 - mystring2;
However, that is undefined behaviour when the two pointers point to different arrays (which they probably always will). You need to be doing something else. What? I don't know because I don't know what your function should return.
You have no condition in your function that examines number, or z that you derive from it. What would make it stop?
Why don't you simply decrement number and break when it reaches 0 assuming the loop hasn't broken by that point
You should update z on each iteration and then check if it reaches zero, try adding this to your code:
if (z == 0)
break;
else
z -= 1;
Also, that check you have there is really faulty, if it worked it could stop at an unwanted time, for example on the strings "abcdec" and "xxcddc", where number = 6, it would stop at 3, because the characters at those indexes are the same as those on index 6.
Re-read your code very thoroughly and make sure you really understand it before taking any of these answers into account.
This will walk until it finds a difference, or the end of the string.
while(n > 0) {
if(*str1 != *str2 || *str1 == '\0'){
return *str1 - *str2;; //they're different, or we've reached the end.
}
++str1; //until you understand how ++ works it's a good idea to leave them on their own line.
++str2;
--n;
}
return 0;// I originally had *str1 - *str2 here, but what if n came in as zero..
the problem with the z compare is it's a moving target.
think of [] as a + sign.. mystring1[z] could be represented like this *(mystring1 + z)
That means the line above ++mystring1; (as it should be) is moving the pointer and thus moving where z is looking..
It might help to think of pointers as address on a street.. when you ++ you move up a house..
Say z = 1.. and the house that mystring1 points at is yours, and z is your neighbor. add one to the house you're looking at, and mystring1 is now pointing at your neighbor, and z is pointing at his neighbor because z is still saying what your pointing at + 1.
Thanks all...I fixed the error...added another condition to the while loop.
int i;
i=0;
z = number - 1;
while((*mystring1==*mystring2) && (*mystring1 !='\0') && (*mystring2 !='\0') && (i<z))
and then incrementing i till it comes out of this loop.