Below is the code I am having issues with. I understand constants and believe I understand the sizeof function but must be missing something. Here is what I have tried to do to solve on my own:
- printf statement with TOTAL_ELEMENTS as the %d - it returns 7
- printf statement of TOTAL_ELEMENTS - 2 - it returns 5 (as expected)
- substitute 5 in the for loop - loop runs correctly
- initialize a global int variable of any name and set it equal to (sizeof(array) / sizeof(array[0])). Then used the variable in the for loop where TOTAL_ELEMENTS would go - again the loop runs correctly.
So (at least in my head), it has to be something involving both the constant and the sizeof function - I'm positive the array/array[0] also plays a part but through testing and substitution I can't figure out what the issue is. I have read up on the sizeof function as well as constants to no avail. I have tried searching but have gotten no where as I'm not fully certain what I'm searching for. I don't necessarily need answers but if someone could point me in the right direction it would be much appreciated. Thank you in advance.
#include <stdio.h>
#define TOTAL_ELEMENTS (sizeof(array) / sizeof(array[0]))
int array[] = {23,34,12,17,204,99,16};
int main()
{
int d;
for(d=-1;d <= (TOTAL_ELEMENTS-2);d++)
printf("%d\n",array[d+1]);
return 0;
}
This issue is not related to sizeof. this is because of the comparing signed with unsigned value. In your code , (TOTAL_ELEMENTS-2) has an unsigned value , but d is a signed variable. therefore , for condition will compare 5 with 0xFFFFFFFF and 5 is less than 0xFFFFFFFF then it is false always!
For example :
int main()
{
int d;
unsigned int e = 5;
for (d = -1; d <= e; d++)
printf("%d\n", array[d + 1]);
return 0;
}
It do not print any things! , same as your code.
Related
I was trying out a problem, and my code failed one of its test cases. I traced back the error, and it can be summarized by the following code:
#include <stdio.h>
int main(void)
{
int a = 90000;
int b = 80000;
if (a * b <= a + b)
{
printf("YES\n");
}
else
{
printf("NO\n");
}
}
I would expect the output to be a "NO" (since 90000 * 80000 > 90000 + 80000). But turns out, when compiled and run, the above program outputs "YES".
I suspect this has something to do with the range of an int in C. The range of an int on a 64-bit OS (the one I have) is 4 bytes, thus all the integers from -2,147,483,648 to 2,147,483,647 can be represented by an int. But a * b in the above code is 7200000000, which is well beyond the bounds of an int. So I tried casting the value of a * b to a long long int as follows
#include <stdio.h>
int main(void)
{
int a = 90000;
int b = 80000;
if ((long long int) a * b <= a + b)
{
printf("YES\n");
}
else
{
printf("NO\n");
}
}
But still the output stays the same, "YES". I can't seem to figure out how I can make the program return the correct output. How can I do it? This has been solved. The above code works perfectly fine.
Like MathewHD pointer out in the comments that declaring a and b as longs rather than ints solves the issue. Then why does casting not work? Casting works (refer the above code). Also, where is this temporary variable having the value of a * b stored, and how can I change the data type of that temporary variable?
Turns out I was using a slightly different code when the error was generated. Using the above code (the one which includes casting to a long), does give the expected output, however adding parentheses around the left hand side of the condition, makes the program return the wrong output i.e. "YES". The code follows
#include <stdio.h>
int main(void)
{
int a = 90000;
int b = 80000;
if ((long long int) (a * b) <= a + b)
{
printf("YES\n");
}
else
{
printf("NO\n");
}
}
The main reason why I initially thought of adding the parentheses around the left hand side of the inequation, was to ensure that the compiler does not misinterpret the casting to be for only one of the involved integers rather than their product. So I just wanted their product to be casted. I would love an explanation as to why adding the parentheses does more harm than good, i.e. why doe it make the program return wrong outputs?
One of my previous question also remains: Where is this temporary variable having the value of a * b stored, and how can I change the data type of that temporary variable?
This doesn't work:
if ((long long int) (a * b) <= a + b)
Because you're casting the result of the multiplication, after any overflow occurs. Since both a and b have type int, the result also has type int and overflows so the cast doesn't matter.
This works:
if ((long long int) a * b <= a + b)
Because it converts one of the operands of the * operator to a larger type, resulting in the other operand getting converted to match, so the result has type long long int.
Here is a code snippet:
unsigned int m,n,a;
long long int c,p=0,q=0;
scanf("%u%u%u",&m,&n,&a);
while(m>0){
m-=a;
p++;
}
while(n>0){
n-=a;
q++;
}
c=p*q;
printf("%lld",c);
The above code does not work for any input. That is, it seems like it has crashed,though I could not understand where I'm mistaken. I guess the part with %lld in the printf has problems. But Ido not know how to fix it. I'm using code blocks.
Some expected outputs for corresponding inputs are as follows:
Input: 6 6 4
Output: 4
Input: 1000000000 1000000000 1
Output: 1000000000000000000(10^18).
APPEND:
So, I'm giving the link of the main problem below. The logic of my code seemed correct to me.
https://codeforces.com/contest/1/problem/A
As it's been pointed out in comments/answers the problem is that m and n is unsigned so your loops can only stop if m and n are a multiple of a.
If you look at the input 6 6 4 (i.e. m=6 and a=4), you can see that m first will change like m = 6 - 4 which leads to m being 2. So in the next loop m will change like m = 2 - 4 which should be -2 but since m is unsigned it will wrap to a very high positive number (i.e. UINT_MAX-1) and the loop will continue. That's not what you want.
To fix it I'll suggest you drop the while loops and simply do:
unsigned int m,n,a;
long long unsigned int c,p=0,q=0;
scanf("%u%u%u",&m,&n,&a);
p = (m + a - 1)/a; // Replaces first while
q = (n + a - 1)/a; // Replaces second while
c=p*q;
printf("%lld",c);
One problem with this solution is that the sum (m + a - 1) may overflow (i.e. be greater than UINT_MAX) and therefore give wrong results. You can fix that by adding an overflow check before doing the sum.
Another way to protect against overflow could be:
p = 1; // Start with p=1 to handle m <= a
if (m > a)
{
m -= a; // Compensate for the p = 1 and at the same time
// ensure that overflow won't happen in the next line
p += (m + a - 1)/a;
}
This code can then be reduced to:
p = 1;
if (m > a)
{
p += (m - 1)/a;
}
while(m>0){
m-=a;
p++;
}
will run until m is equal to 0, since it cannot be negative because it is unsigned. So if m is 4 and a is 6, then m will underflow and get the maximum value that m can hold minus 2. You should change the input variables to signed.
4386427 shows how you can use math to remove the loops completely, but for the more general case, you can do like this:
while(m > a) {
m-=a;
p++;
}
// The above loop will run one iteration less
m-=a;
p++;
Of course, you need to do the same thing for the second loop.
Another thing, check return value of scanf:
if(scanf("%u%u%u",&m,&n,&a) != 3) {
/* Handle error */
}
Using an unsigned type isn't always the best choice to represent positive values, expecially when its modular behavior is not needed (and maybe forgotten, which leads to "unexpected" bugs). OP's use case requires an integral type capable of store a value of maximum 109, which is inside the range of a 32-bit signed integer (a long int to be sure).
As 4386427's answer shows, the while loops in OP's code may (and should) be avoided anyways, unless a "brute force" solution is somehow required (which is unlikely the case, given the origin of the question).
I'd use a function, though:
#include <stdio.h>
// Given 1 <= x, a <= 10^9
long long int min_n_of_tiles_to_pave_an_edge(long int x, long int a)
{
if ( x > a ) {
// Note that the calculation is performed with 'long' values and only after
// the result is casted to 'long long', when it is returned
return 1L + (x - 1L) / a;
}
else {
return 1LL;
}
}
int main(void)
{
// Given a maximum value of 10^9, a 32-bit int would be enough.
// A 'long int' (or 'long') is guaranteed to be capable of containing at
// least the [−2,147,483,647, +2,147,483,647] range.
long int m, n, a;
while ( scanf("%ld%ld%ld", &m, &n, &a) == 3 )
{
// The product of two long ints may be too big to fit inside a long.
// To be sure, performe the multiplication using a 'long long' type.
// Note that the factors are stored in the bigger type, not only the
// result.
long long int c = min_n_of_tiles_to_pave_an_edge(m, a)
* min_n_of_tiles_to_pave_an_edge(n, a);
printf("%lld\n",c);
}
}
can anyone explain me the output
I have code like
#define TOTAL_ELEMENTS (sizeof(array) / sizeof(array[0]))
int array[] = {23,34,12,17,204,99,16};
for(d=-1;d <= (TOTAL_ELEMENTS);d++)
{
printf("%d\n",array[d+1]);
}
It shows no output why it is so ?
But when i change the value of d in for loop like d=1 it shows the output why?
if i remove macro TOTAL_ELEMENT wit d<=4 ; i get the desired output why ?
As other stated in their answers, with d = -1 it does not print anything as in:
d <= TOTAL_ELEMENTS
d is converted to an unsigned integer type (TOTAL_ELEMENTS is of type size_t because of sizeof). After conversion d value becomes a huge unsigned integer and the comparison with TOTAL_ELEMENTS value fails.
Then:
printf("%d\n",array[d+1]);
will overflow your array as the last element of your array is at index TOTAL_ELEMENTS - 1 and you access your array up to TOTAL_ELEMENTS + 1.
To display your array elements just use the regular form starting from index 0:
int i;
for (i = 0; i < TOTAL_ELEMENTS; i++)
{
printf("%d\n", array[i]);
}
You need to understand "Conversion rules for comparision between signed and unsigned types". In the example, for(d=-1;d <= (TOTAL_ELEMENTS);d++), here d is signed int, and TOTAL_ELEMENTS is unsigned, and d <= TOTAL_ELEMENTS converts d to unsigned. Unsigned -1 is huge number which is not < TOTAL_ELEMENTS, so the loop never gets executed. Typecast as shown below. It will work.
for(d=-1;d <= (int)(TOTAL_ELEMENTS);d++)
try casting TOTAL_ELEMENTS to int
for(d=-1;d <= (int)(TOTAL_ELEMENTS);d++)
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
signed to unsigned conversions
A riddle (in C)
I am trying to understand why this program is not working
#include<stdio.h>
#define TOTAL_ELEMENTS (sizeof(array) / sizeof(array[0]))
int array[] = {23,34,12,17,204,99,16};
int main()
{
int d;
for(d=-1;d <= (TOTAL_ELEMENTS-2);d++)
printf("%d\n",array[d+1]);
return 0;
}
I came across this program when I was going through automatic type conversions in C.But I don't understand how conversions happen between signed and unsigned data types.Please explain.
Thank you,
Harish
sizeof() is of type unsigned, wile d is signed.
you check if d is smaller then an unsigned integer. Thus, the signed d is converted to unsinged.
But the bits representaion of the signed -1 when read as unsigned is greater then 2^31, and obviously greater then TOTAL_ELEMENTS-2, thus the condition is never met and you do not enter the for loop even once.
Look at this code snap, it might clear up things for you:
#include <stdio.h>
#include <stdlib.h>
int main() {
unsigned int x = 50;
int y = -1;
printf("x < y is actually %u < %u which yields %u\n", y,x,y < x);
return 0;
}
The above code prints:
x < y is actually 4294967295 < 50 which yields 0
what is wrong with this code ? can anyone explain ?
#include <stdio.h>
#include <malloc.h>
#define TOTAL_ELEMENTS (sizeof(array) / sizeof(array[0]))
int array[] = {23,34,12,17,204,99,16};
int main()
{
int num;
int d;
int size = TOTAL_ELEMENTS -2;
printf("%d\n",(TOTAL_ELEMENTS-2));
for(d=-1;d <= (TOTAL_ELEMENTS-2);d++)
printf("%d\n",array[d+1]);
return 0;
}
when i print it gives 5, but inside for loop what is happening ?
The sizeof operator returns a value of type size_t, which is an unsigned value. In your for loop condition test:
d <= (TOTAL_ELEMENTS-2)
you are comparing a signed value (d) with an unsigned value (TOTAL_ELEMENTS-2). This is usually a warning condition, and you should turn up the warning level on your compiler so you'll properly get a warning message.
The compiler can only generate code for either a signed or an unsigned comparison, and in this case the comparison is unsigned. The integer value in d is converted to an unsigned value, which on a 2's complement architecture ends up being 0xFFFFFFFF or similar. This is not less than your TOTAL_ELEMENTS-2 value, so the comparison is false.
You're starting the loop by setting d = -1, it should be d = 0. So for the first element you're reading random bits of memory.
If you fix that, then you can change your printf to be
printf("%d\n",array[d]);
As you've also marked this as homework, I'd advise also take a look at your loop terminating condition.