difference between "cnt += num % 2;",and, "if (num % 2) ++cnt;" - c

the difference between "cnt += num % 2;",and, "if (num % 2) ++cnt;"
I succeeded in counting the number of '1' in binary number.
but one line which seems to do the same thing makes different result.
global variable "cnt=0" is declared top of the code
#include<stdio.h>
int cnt=0;
//and the recursive function which counts '1' is here
int one( int num ) {
if (num < 2)
{
cnt += num;
return cnt ; //here, escape and return cnt to main.
}
else
{
one(num / 2);
cnt += num % 2; //according to the remainders cnt++ AND THIS IS THE THE QUESTION CORE
}
}
void main() {
int num;
scanf("%d", &num);
cnt=one(num); //call recursive function
printf("%d", cnt); //and here, i want to watch the [RESULT]
}//main
[RESULT]
when I use " cnt += num % 2; " prints correct answer
but another code which seems same "if (num % 2) ++cnt;" prints wrong answer.
num%2 must be 0 or 1. so it adds '1' to cnt. but second code doesn't work.
which point did i miss?

Other than lack of return in else branch, you use global var cnt in a .. not an appropriate way (those are what you missed). The following code works well:
int one(int num) {
if (num < 2) {
return num;
} else {
return (num % 2) + one(num / 2);
}
}
Hope that helps.

Related

Skipping digits of a number and adding the non-skipped ones in C

I'm trying to get every other digit from a user-inputted number. And then find their sum. For example, 123456. I want to get 5,3, and 1. Then find their sum. This is my function for that:
int getSum(long userInput) // user input being passed as an argument.
{
long userInput1 = userInput;
long sumOfNum = 0 ;
while(userInput1 != 0)
{
userInput1 = userInput1 / 10;
sumOfNum += userInput1 % 10;
}
printf("%ld\n",sumOfNum);
}
This doesn't work for all of the numbers, for example; with 12345, I am expecting 6. But the output is 10.
Where did I go wrong?
[Edit- How I did it? (based on the answer from Fe2O3)
I need another division. So:
while(userInput1 != 0)
{
userInput1 = userInput1 / 10;
sumOfNum += (userInput1 % 10);
userInput1 = userInput1 / 10; // this one
}
printf("%ld\n",sumOfNum);
return sumOfNum;
}
To get every other digit...
int getSum( long val ) {
int sum = 0;
for( val /= 10; val; val /= 100 )
sum += val % 10;
printf( "%d\n", sum );
return sum; // missed this in previous version
}
EDIT:
After it was pointed out that 'sum' went out of scope after the for() terminated, the code has been adapted to have fewer division operations.

Recursive positive digits sum program

I'm facing an issue, the program almost works correctly except it gives +1 in output result. For example num input is 123 = 1+2+3=6, instead it gives 7 as output.
I can simply fix this problem by adding -1 in the printf statement, but I want to know why this is happening.
#include<stdio.h>
int Sumdigits(int num);
int Sumdigits(int num){
if(num<1){
return 1;
}
else return (num%10+Sumdigits(num/10));
}
int main(){
int num;
printf("Enter Number: ");
scanf("%d",&num);
printf("%d",Sumdigits(num));
}
The problem is that Sumdigits( 0 ) will return 1 instead of 0, which does not make sense. To fix this, change
if(num<1){
return 1;
}
to:
if(num<1){
return 0;
}
It is also worth noting that your code will not work with negative numbers. Therefore, you may want to change the function Sumdigits to the following:
int Sumdigits( int num )
{
if( num == 0 )
return 0;
if ( num < 0 )
num = -num;
return num % 10 + Sumdigits(num/10);
}
You are adding 1 in this if statement
if(num<1){
return 1;
The function should be declared and defined like
unsigned int Sumdigits( unsigned int num )
{
return num == 0 ? 0 : num % 10 + Sumdigits( num / 10 );
}
If the user is allowed to deal with negative integer values then the function can be defined the following way
unsigned int Sumdigits( int num )
{
unsigned int digit = num < 0 ? -( num % 10 ) : num % 10;
return num == 0 ? 0 : digit + Sumdigits( num / 10 );
}
if (num < 1) is only handled when the digit is zero, but then you return 1, instead, so adding one to the result. This happens always, as this is the cut'n go back case that is executed always at the deepest recursion level.
It should read:
if (num < 1)
return 0;
(if you check, the only possibility for a valid number is to be zero, as it is an integer going down from a large number until you have no more digits, when you exhaust the number, it is actually zero, so it can be more readably written:
if (num == 0)
return 0;
meaning if we are at the end, then just add zero.

Print an integer digit by digit

I have a function print_number.
The function checks if in front of the number there exists '-', then it reverse the number and takes every digit and prints it. The algorithm works pretty good but if i give -2.147.483.648 ( which should be the bottom limit of an integer ) it pritns -0 and i don't know why.
#include<stdio.h>
void print_char(char character)
{
printf("%c",character);
}
void print_number(int nr)
{
int reverse=0;
if (nr < 0)
{
print_char('-');
nr *= -1;
}
while(nr > 9)
{
reverse = reverse * 10 + nr % 10;
nr = nr / 10;
}
print_char(nr + '0');
while(reverse)
{
print_char(reverse % 10 + '0');
reverse = reverse / 10;
}
}
When you are doing
if (nr < 0)
{
print_char('-');
nr *= -1;
}
It inverses negative number to the positive one.
If you will run it for -2.147.483.648, you will receive
nr = 2.147.483.648 // == binary 1 0000000000000000000000000000000
As INT is 32 BIT variable in your architecture (and at least 16 BIT variable by the spec), so '1' overflows it and so on
nr = 0 // For gcc-like C realisation
And accepting the ISO9899 spec, this behaviour of signed int overflow is realisation-specified thing and may not be predicted in common.
Use long long value if you're needing to use your program for larger values.
Something like:
#include<stdio.h>
void print_char(char character)
{
printf("%c",character);
}
void print_number(long long nr)
{
int reverse=0;
if (nr < 0)
{
print_char('-');
nr *= -1;
}
while(nr > 9)
{
reverse = reverse * 10 + nr % 10;
nr = nr / 10;
}
print_char(nr + '0');
while(reverse)
{
print_char(reverse % 10 + '0');
reverse = reverse / 10;
}
}
void main(void){
print_number(-2147483648LL);
}
And test:
> gcc test.c
> ./a.out
-2147483648
Firstly, the MAX and MIN range for an INT are -2,147,483,648 and 2,147,483,647 respectively.
Negating -2,147,483,648 means a positive value 2,147,483,648 would result in an overflow by 1 as it is out of bounds for the MAX range.
This operation will result in the same value of -2,147,483,648.
Secondly, you might encounter an overflow during the integer reversing process.
Example, reversing 2147483647 causes an overflow after the intermediate result of 746384741.
Therefore, you should handle that by throwing an exception or returning 0.
Thirdly, your loop for reversing the number is inaccurate. It should loop till while(nr != 0)
Here's the complete code.
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
int main()
{
void reverseNumber(int);
reverseNumber(124249732);
return 0;
}
void reverseNumber(int nr)
{
printf("nr = %d\n", nr);
int reverse = 0;
bool neg = false;
if (nr < 0) {
neg = true;
nr *= -1;
}
while (nr != 0) {
int digit = nr % 10;
int result = reverse * 10 + digit;
if ((result - digit) / 10 != reverse) {
printf("ERROR\n");
exit(0);
}
reverse = result;
nr = nr / 10;
}
if(neg) {
printf("%c", '-');
}
printf("%d\n", reverse);
}
nr *= -1; is a problme when nr == INT_MIN as that is signed integer overflow. The result is undefined behavior (UB). Best to avoid.
Wider integers are not always available.
Using OP's general, approach, do not change the sign of nr until it is reduced.
void print_number(int nr) {
int reverse = 0;
if (nr < 0) {
print_char('-');
//nr *= -1;
}
while (nr/10) { // new test
reverse = reverse * 10 + nr % 10;
nr = nr / 10;
}
reverse = abs(reverse); // reverse = |reverse|
nr = abs(nr); // nr = |nr|
print_char(nr + '0');
while (reverse) {
print_char(reverse % 10 + '0');
reverse = reverse / 10;
}
}

C: Recursive function for inverting an int

I had this problem on an exam yesterday. I couldn't resolve it so you can imagine the result...
Make a recursive function: int invertint( int num) that will receive an integer and return it but inverted, example: 321 would return as 123
I wrote this:
int invertint( int num ) {
int rest = num % 10;
int div = num / 10;
if( div == 0 ) {
return( rest );
}
return( rest * 10 + invert( div ) )
}
Worked for 2 digits numbers but not for 3 digits or more. Since 321 would return 1 * 10 + 23 in the last stage.
Thanks a lot!
PS: Is there a way to understand these kind of recursion problems in a faster manner or it's up to imagination of one self?
int invertint( int num ) {
int i ;
for(i=10;num/i;i*=10);
i/=10;
if(i == 1) return num;
return( (num % 10) * i + invertint( num / 10 ) );
}
Your mistake is that in the last statement you are multiplying rest by 10. Why only 10? You need to shift the rest digit by as many digits as there are left in the remaining part of the number. You are shifting by only 1. No wonder it works only for 2-digit numbers.
The last part should be done along the lines of
int tail = invert( div );
int deg = /* number of digits in `tail` */;
return rest * (int) pow(10, deg) + div;
The problem is with return(rest * 10 + invert(div)). You can't do the multiplication yourself. The factor depends on the number of times the function is recursed, thus you have to provide the carry as a second argument to your function (carry is initialized with 0)
If you do it the other way, you won't need a counter.
int invertint(int num)
{
if (0 == num || 0 == num % 10) {
return num / 10;
}
int digits = floor(log10(num)) + 1;
int modulus = pow(10, digits - 1);
return invertint(num % modulus) * 10 + num / modulus;
}
Note that this isn't as simple as I originally thought - I had to use math.
int reverse(int no,int rev)
{
if(no!=0)
return reverse(no/10,rev*10+no%10);
else
return rev;
}
call this method as reverse(numberToReverse,0)
Just as an alternative, this could be done without recursion.
int invertint(int num)
{
int res = 0;
while (num != 0)
{
res = res * 10 + (num % 10);
num /= 10;
}
return res;
}
But since recursion was the assignment, given the int(int) signature, easiest would be with a pow(log10)) variation (provided that you're allowed to include math.h ? )
int invertint(int num)
{
if (num == 0) return 0;
return invertint(num / 10) + (int)pow(10, (int)log10(num)) * (num % 10);
}
This is the simplest approach.
int sum=0;
int reverse(int n)
{
if(n>0)
{
sum=(sum*10)+(n%10);
reverse(n/10);
}
return sum;
}

Extracting individual digits from a long in C

I'm doing a homework assignment for my course in C (first programming course).
Part of the assignment is to write code so that a user inputs a number up to 9 digits long, and the program needs to determine whether this number is "increasing"/"truly increasing"/"decreasing"/"truly decreasing"/"increasing and decreasing"/"truly decreasing and truly increasing"/"not decreasing and not increasing". (7 options in total)
Since this is our first assignment we're not allowed to use anything besides what was taught in class:
do-while, for, while loops, else-if, if,
break,continue
scanf, printf ,modulo, and the basic operators
(We can't use any library besides for stdio.h)
That's it. I can't use arrays or getchar or any of that stuff. The only function I can use to receive input from the user is scanf.
So far I've already written the algorithm with a flowchart and everything, but I need to separate the user's input into it's distinct digits.
For example, if the user inputs "1234..." i want to save 1 in a, 2 in b, and so on, and then make comparisons between all the digits to determine for example whether they are all equal (increasing and decreasing) or whether a > b >c ... (decreasing) and so on.
I know how to separate each digit by using the % and / operator, but I can't figure out how to "save" these values in a variable that I can later use for the comparisons.
This is what I have so far:
printf("Enter a positive number : ");
do {
scanf ("%ld", &number);
if (number < 0) {
printf ("invalid input...enter a positive integer: ");
continue;
}
else break;
} while (1);
while (number < 0) {
a = number % 10;
number = number - a;
number = number / 10;
b = a;
}
Why not scan them as characters (string)? Then you can access them via an array offset, by subtracting the offset of 48 from the ASCII character code. You can verify that the character is a digit using isdigit from ctype.h.
EDIT
Because of the incredibly absent-minded limitations that your professor put in place:
#include <stdio.h>
int main()
{
int number;
printf("Enter a positive number: ");
do
{
scanf ("%ld", &number);
if (number < 0)
{
printf ("invalid input...enter a positive integer: ");
continue;
}
else break;
} while (1);
int a = -1;
int b = -1;
int c = -1;
int d = -1;
int e = -1;
int f = -1;
int g = -1;
int h = -1;
int i = -1;
while (number > 0)
{
if (a < 0) a = number % 10;
else if (b < 0) b = number % 10;
else if (c < 0) c = number % 10;
else if (d < 0) d = number % 10;
else if (e < 0) e = number % 10;
else if (f < 0) f = number % 10;
else if (g < 0) g = number % 10;
else if (h < 0) h = number % 10;
else if (i < 0) i = number % 10;
number /= 10;
}
/* Printing for verification. */
printf("%i", a);
printf("%i", b);
printf("%i", c);
printf("%i", d);
printf("%i", e);
printf("%i", f);
printf("%i", g);
printf("%i", h);
printf("%i", i);
return 0;
}
The valid numbers at the end will be positive, so those are the ones you validate to meet your different conditions.
Since you only need to compare consecutive digits, there is an elegant way to do this without arrays:
int decreasing = 2;
int increasing = 2;
while(number > 9)
{
int a = number % 10;
int b = (number / 10) % 10;
if(a == b)
{
decreasing = min(1, decreasing);
increasing = min(1, increasing);
}
else if(a > b)
decreasing = 0;
else if(a < b)
increasing = 0;
number /= 10;
}
Here, we walk through the number (by dividing by 10) until only one digit remains. We store info about the number up to this point in decreasing and increasing - a 2 means truly increasing/decreasing, a 1 means increasing/decreasing, and a 0 means not increasing/decreasing.
At each step, a is the ones digit and b is the tens. Then, we change increasing and decreasing based on a comparison between a and b.
At the end, it should be easy to turn the values of increasing and decreasing into the final answer you want.
Note: The function min returns the smaller of its 2 arguments. You should be able to write your own, or replace those lines with if statements or conditionals.
It's stupid to ask you to do loops without arrays --- but that's your teacher's fault, not yours.
That being said, I would do something like this:
char c;
while (1) {
scanf("%c", &c);
if (c == '\n') /* encountered newline (end of input) */
break;
if (c < '0' || c > '9')
break; /* do something to handle bad characters? */
c -= '0';
/*
* At this point you've got 0 <= c < 9. This is
* where you do your homework :)
*/
}
The trick here is that when you type numbers into a program, you send the buffer all at once, not one character at a time. That means the first scanf will block until the entire string (i.e. "123823" or whatever) arrives all at once, along with the newline character ( '\n' ). Then this loop parses that string at its leisure.
Edit For testing the increasing/decreasing-ness of the digits, you may think you need to store the entire string, but that's not true. Just define some additional variables to remember the important information, such as:
int largest_digit_ive_seen, smallest_digit_ive_seen, strict_increasing_thus_far;
etc. etc.
Let us suppose you have this number 23654
23654 % 10000 = 2 and 3654
3654 % 1000 = 3 and 654
654 % 100 = 6 and 54
54 % 10 = 5 and 4
4
This way you can get all the digits. Of course, you have to know if the number is greater than 10000, 1000, 100 or 10, in order to know the first divisor.
Play with sizeof to get the size of the integer, in order to avoid a huge if...else statement
EDIT:
Let us see
if (number>0) {
// Well, whe have the first and only digit
} else if (number>10) {
int first_digit = number/10;
int second_digit = number % 10;
} else if (number>100) {
int first_digit = number/100;
int second_digit = (number % 100)/10;
int third_digit = (number % 100) % 10;
} ...
and so on, I suppose
// u_i is the user input, My homework asked me to extract a long long, however, this should also be effective for a long.
int digits = 0;
long long d_base = 1;
int d_arr[20];
while (u_i / d_base > 0)
{
d_arr[digits] = (u_i - u_i / (d_base * 10) * (d_base * 10)) / d_base;
u_i -= d_arr[digits] * d_base;
d_base *= 10;
digits++;
}
EDIT: the extracted individual digit now lives in the int array d_arr. I'm not good at C, so I think the array declaration can be optimized.
Here's a working example in plain C :
#include <stdio.h>
unsigned long alePow (unsigned long int x, unsigned long int y);
int main( int argc, const char* argv[] )
{
int enter_num, temp_num, sum = 0;
int divisor, digit, count = 0;
printf("Please enter number\n");
scanf("%d", &enter_num);
temp_num = enter_num;
// Counting the number of digits in the entered integer
while (temp_num != 0)
{
temp_num = temp_num/10;
count++;
}
temp_num = enter_num;
// Extracting the digits
printf("Individual digits in the entered number are ");
do
{
divisor = (int)(alePow(10.0, --count));
digit = temp_num / divisor;
temp_num = temp_num % divisor;
printf(" %d",digit);
sum = sum + digit;
}
while(count != 0);
printf("\nSum of the digits is = %d\n",sum);
return 0;
}
unsigned long alePow(unsigned long int x, unsigned long int y) {
if (x==0) { return 0; }
if (y==0||x==1) { return 1; }
if (y==1) { return x; }
return alePow(x*x, y/2) * ((y%2==0) ? 1 : x);
}
I would suggest loop-unrolling.
int a=-1, b=-1, c=-1, d=-1, e=1, f=-1, g=-1, h=-1, i=-1; // for holding 9 digits
int count = 0; //for number of digits in the given number
if(number>0) {
i=number%10;
number/=10;
count++;
}
if(number>0) {
h=number%10;
number/=10;
count++;
}
if(number>0) {
g=number%10;
number/=10;
count++;
}
....
....
/* All the way down to the storing variable a */
Now, you know the number of digits (variable count) and they are stored in which of the variables. Now you have all digits and you can check their "decreasing", "increasing" etc with lots of if's !
I can't really think of a better soltion given all your conditions.

Resources