I am looking at the following piece of code:
void printd(int n)
{
if (n < 0) {
putchar('-');
n = -n;
}
if (n / 10)
printd(n / 10);
putchar(n % 10 + '0');
}
I understand the first if statement fine, but the second one has me confused on a couple of points.
By itself, since "n" is an integer, I understand that n/10 will shift the decimal point to the left once - effectively removing the last digit of the number; however, I am having a little trouble understanding how this can be a condition by itself without the result being equal to something. Why isn't the condition if ((n/10) >= 0) or something?
Also, why is the '0' passed into the putchar() call?
Can someone tell me how it would read if you were to read it aloud in English?
Thanks!
The n / 10 will evaluate to false if the result is 0, true otherwise. Essentially it's checking if n > 10 && n < -10 (the -10 doesn't come into play here due to the n = -n code)
The + '0' is for character offset, as characters '0'-'9' are not represented by numbers 0-9, but rather at an offset (48-57 with ascii).
Can someone tell me how it would read if you were to read it aloud in English?
If you're talking about the conditional, then I would say "if integer n divided by 10 is not zero"
n/10 will not shift the decimal number since n is an integer. The division will produce the result like this: if n = 25, then n/10 would be 2 (without any decimal points), similarly if n = 9, then n/10 would be 0 in which case if condition would not be satisfied.
Regarding the +'0', since n%10 produces an integer result and in putchar you are printing a char , you need to convert the integer to a char. This is done by adding the ascii value of 0 to the integer.
In C, there is no separate boolean type; an expression like a > b evaluates to zero if false, non-zero if true. Sometimes you can take advantage of this when testing for zero or non-zero in an int.
As for the '0', that just performs character arithmetic so that the right character is printed. The zero character has an ASCII encoding value which isn't zero, so the n value is used as an offset from that encoding to get the right numeric digit printed out.
Related
I came across this program to convert decimals numbers into their binary equivalent in C. I do not understand how the printf statement works in this program.
int main()
{
int N;
scanf("%d", &N); // Enter decimal equivalent here
for( int j = floor(log2(N)); j >= 0; j-- ){
printf("%d", (N >> j) & 1);
}
}
Let's take an example to get through this problem. Suppose you enter N=65. Its binary representation is - 1000001. When your given code goes through it, j will start at floor(log2(65)), which is 6. So, the given loop will run 7 times, which means 7 numbers will be printed out (which fits the fact that 65's binary representation has 7 digits).
Inside the loop - The number is shifted by j bits each time to the right. When 1000001 is shifted to the right by 6 bits, it becomes 0000001. If shifted by 5, it is 0000010, and so on. It goes down to a shift by 0 bits which is the original number. When each of these shifted numbers are &ed with 1, only the least significant bit (the right most bit) remains. And this digit can either be a 0 or a 1.
If you would have noticed each right shift divides the number by 2. So when 1000001 is shifted by 1 to make 0100000, it is the binary representation of 32, which indeed is 65/2 in C. After all, this is the way someone manually calculates the binary representation of a number. Each division by 2 gives you a digit (starting from the end) of the representation, and that digit is either a 0 or a 1. The & helps in getting the 0 or 1.
In the end, 65 becomes 1000001.
What it is doing is:
Finding the largest number j such that 2^j <= N
Starting at the jth bit (counting from the right) and moving to the right ...
chopping off all of the bits to the right of the current chosen bit
chopping off all of the bits to the left of current chosen bit
printing the value of the single remaining bit
The code actually has undefined behavior because you did not include <stdio.h>, nor <math.h>. Without a proper declaration of floor() and log2(), the compiler infers the prototype from the calling context and gets int log2(int) and int floor(int), which is incompatible with the actual definition in the C library.
With the proper includes, log2(N) gives the logarithm of N in base 2. Its integral part is the power of 2 <= N, hence 1 less than the number of bits in N.
Note however that this method does not work for negative values of N and only works by coincidence for 0 as the conversion of NaN to int gives 0, hence a single binary digit.
The output of below c program is,
output : 1,2,3,4 ........ 126,127,-128,-127 .... -2,-1 ?
#include <stdio.h>
#include <string.h>
int main()
{
char i=0;
for(i<=5 && i>=-1 ; ++i;i>0)
printf("%d\n",i);
printf("\n");
return 0;
}
please explain why is so ?
Here is a breakdown of your code, it's fairly sneaky:
for( i <= 5 && i >= -1 ; ++i; i > 0)
Typically a for-loop is, ( initial statement, expression, second statement ). Looking at your code before the first null statement: what you have done is an expression (in place of a statement), which does not matter at all however it's entirely useless. So removing that line (which has no effect on the result of this expression) gives us:
for( ; ++i; i > 0)
... now if you noticed you initialized i to be 0 before the for loop. What you are doing next is incrementing i and then returning its value (see here), and hence it will go from 1 ... -1 (overflowing at 127). This is because in C any non-zero value is true and 0 is false. Hence, once i becomes 0 it will stop running the loop. i can only become zero by overflowing.
Your third statement does not matter, it's irrelevant.
It is called overflow. Type "char" uses 1 byte of your RAM's capacity, so it can store only 256 values. These are [-128, 127]. When you try to get over 127, it will get back the the lowest value.
Other than that, your for loop is a little messed up. Try
for ( i = 0 ; i <= 5 ; ++i ) // This will print 0,1,2,3,4,5
printf( "%d\n" , i );
I'm guessing you're using the for loop incorrectly.
for(i<=5 && i>=-1 ; ++i;i>0)
The above code means:
Before anything, evaluate i<=5 && i>=-1 (which doesn't have any side effects so nothing happens)
On every iteration, increment i then check if it is zero. If it is non-zero, run another iteration.
At the end of every iteration, evaluate i>0 (which again, does nothing).
Therefore, your loop simplifies down to and is essentially
while (++i)
To explain your result, the system you're using is likely using implements a char as a signed two's complement integer which 'wraps' to a negative number when it is higher than 127 (since 128 in a 8 bit two's complement integer is a -128)
First of all, char occupies 1 byte and it is signed.
With the help of 8 bits (1 byte) the range of numbers that you can represent is
**-(2^(8-1)) to +((2^(8-1)) -1) [ie from -128 to +127].**
In your code you are incrementing i and also printing the same.
once i reaches 127 (in binary 0111 1111 = 127) and you again increment it becomes (1000 0000) which is -128.
And while printing you are using %d. so out will be in integer format.
That is why it is printing 1,2,3 ... -128, -127...
If you didn't understand how 1000 0000 is -128, read
What is 2's Complement Number?
Because this:
for(i<=5 && i>=-1 ; ++i;i>0)
works out as
1) Initialisation:
i<=5 && i>=-1
does nothing
2) Termination condition:
++i
increments i and will terminate when i gets to zero
3) statement executed each time round loop (normally an increment / decrement):
i > 0
does nothing.
So your code loops from i = 0 back till it's zero again
I got a set of characters as input using scanf which is actually like this "1854?156X".
(using scanf("%c",&input[i]) , input is an array of 10 characters);
In further processing of code I want to multiply the (first digit *10) & (second digit *9) and so on.
So, while multiplying it is taking the ASCII value of 1 which is actually (49 *10), instead of (1*10).
input[i]*counter;
where counter is
int counter=10;
How can I convert the char array to integer array where the exact digit should be multiplied instead of ascii value of that character?
If you know ahead of time that you value is ascii then simply subtract the value of '0' from it. E.g. '9' - '0' = 9'
Definitely use atoi(). It spares you a lot of manual character checking.
int input_val = atoi(input);
int temp = input_val;
while(temp)
{
int digit = temp % 10;
temp /= 10;
}
This gives you each digit from right to left in "digit". You can construct your number using addition and multiplying by powers of 10.
Take the ascii value and subtract 48.
That is input[i] - '0'
...or rather use atoi(). It returns zero if it fails on conversion, so you don't need to bother with '?' and such characters in your array while you traverse it.
Use strtol to convert these character strings into integral types.
It's superior to atoi because the failure modes are not ambiguous.
I have a homework. The question is:
Write a function that takes as parameter a single integer, int input, and returns an unsigned character
such that:
a- if input is negative or larger than 11,111,111 or contains a digit that is not 0 or 1; then the function will
print an error message (such as “invalid input”) and return 0,
b- otherwise; the function will assume that the base-10 value of input represents a bit sequence and return the magnitude-only bit model correspondent of this sequence.
For Example: If input is 1011, return value is 11 and If input is 1110, return value is 14
This is my work for a, and I am stuck on b. How can I get bit sequence for given integer input?
int main()
{
int input = 0;
printf("Please type an integer number less than 11,111,111.\n");
scanf("%d",&input);
if(input < 0 || input > 11111111)
{
printf("Invalid Input\n");
system("PAUSE");
return 0;
}
for (int i = 0; i < 8; i++)
{
int writtenInput = input;
int single_digit = writtenInput%10;
if(single_digit == 0 || single_digit == 1)
{
writtenInput /= 10;
}
else
{
printf("Your digit contains a number that does not 0 or 1. it is invalid input\n");
system("PAUSE");
return 0;
}
}
printf("Written integer is %d\n",input);
system("PAUSE");
return 0;
}
The bit that you are missing is the base conversion. To interpret a number in base B, what you need to do is multiply digit N times B^N (assuming that you start counting digits from the least significative). For example, in base 16, A108 = (10)*16^3 + 1*16^2 + 0*16^1 + 8*16^0. Where in your base is 2 (binary).
Alternatively, you can avoid the exponentiation if you rewrite the expression as:
hex A008 = ((((10*16) + 1)*16 +0)*16 + 8
Which would be simpler if your input was stated in terms of an array of possibly unknown length as it is easily convertible into a loop of only additions and multiplications.
In the particular case of binary, you can use another direct solution, for each digit that is non-zero, set the corresponding bit in an integer type large enough (in your case, unsigned char suffices), and the value of the variable at the end of the loop will be the result of the conversion.
First off, the existing part of your code needs work. It doesn't report non-binary digits correctly. The question is "Are there any digits that are neither 0 nor 1". To answer this question in the negative, you need to check every single digit. Your code can terminate early. I also suggest renaming the function to something that clearly tells you what it does. For example haveNonBinaryDigit. The term check doesn't tell you what you should expect on the return value.
As for the second part, read up on the binary representation. It is fairly similar to decimal, except that instead of each digit being weighted by 1, 10, 100, .., 10^x, they are weighted by 1, 2, 4, ..., 2^n. Also the digits can only have values 0 and 1.
Your current code has a problem: it will terminate as soon as it finds one single binary bit (at the end) and call the entire integer correct.
I would take a different approach to this problem. What you want to do is get your hands on every single digit from the integer seperately. You made a good start in doing so by using modulo. Say you had this code:
for (int i = 0; i < 8; i++)
{
char single_digit = input%10;
input /= 10;
}
This makes it easy to start working with the digits. You would be checking 8 bits because that seems to be the maximum allowed (11,111,111). Check if each digit is either 0 or 1. Then you can start pushing it in to an unsigned character using bitwise operations. Shift every digit to the left by i, then use a bitwise OR.
For instance n = 8135267 => 16
Here is a solution but I don't understand it.
int sumOddDigits(int n) {
if(n == 0)
return 0;
if(n%2 == 1) //if n is odd
//returns last digit of n + sumOddDigits(n/10) => n/10 removes the last digit of n
return n % 10 + sumOddDigits(n/10)
else
return sumOddDigits(n/10);
}
Integer divison by ten "cuts off" the last digit: I.e. 1234/10 results in 123.
Modulo 10 returns the last digit: i.e. 1234%10 results in 4.
Thus, the above code considers always the last digit. If the last digit is odd (hence the %2==1 stuff) it will be counted, otherwise not. So, if it should count the digit, it takes the last digit (the % 10-stuff) and continues computing with the remaining digits (the recursion with the /10-stuff) and adding them to the digit. If the current digit shall not be counted, it continues just with the remaining digits (thus the recursion and the /10-stuff) without adding it to the current digit.
If the argument is 0, this means that the whole number is traversed, thus the function terminates with returning 0.
% is the modulo operator. It basically finds the remainder of dividing by a number.
n %2 n is only 1 if it's odd. % 10 gets the remainder of the dividing the number by 10, this gets you the currently last digit. Integer division by 10 gets you the next digit as the current last digit (1567/10 = 156)
Think about it this way: Starting with your known answer of 8135267 => 16, if I asked you for the sum of the odd digits in *3*8135267, what would you do? What if I asked for *4*8135267? How do your manual steps related to that function?
Think of it this way. If you get an even digit your function returns it + function value of the number without that digit. Otherwise it returns the function value of the number without the last digit. On your example:
813526(7) -> 0 + sumEvenDigits(813526)
6 + sumEvenDigits(81352)
2 + sumEvenDigits(8135)
....
8 + sumEvenDigits(0)
0 = 16
Hope this helps.
int sum_odd_digits(int n)
{
int s=0,r=0;
if(n==0)
return 0;
r = n%10;
if(r%2==1)
s = s+r;
n=n/10;
return s+ sum_odd_digits(n);
}