Finding digit position - c

I am to write a recursive function int digitpos(int num, int digit) which takes in a positive integer num and digit which returns the position of first appearance of digit in num from the right starting from 1. If not found, 0 will be returned.
For example, digitPos(12234, 2) would yield 3 and digitpos(123, 8) would yield 0
int digitPos(int n, int digit)
{
if (n == 0) return 0;
if (n % 10 == digit) return 1;
return 1 + digitPos(n / 10, digit);
}
The above works if the digit exists in the number. If it doesn't, it will print out how many digits are there(as it goes through all digits).
It don't seems to me to be possible to do so by recursion given only these 2 parameters. Sure, by iteration I can do it. But I wanna know is it possible through recursion?

The function can be written for example the following way
int digitPos( unsigned int n, unsigned int digit )
{
if ( n % 10 == digit ) return 1;
if ( ( n /= 10 ) == 0 ) return 0;
int i = digitPos( n, digit );
return i == 0 ? 0 : i + 1;
}
Here is a demonstrative program
#include <stdio.h>
int digitPos( unsigned int n, unsigned int digit )
{
if ( n % 10 == digit ) return 1;
if ( ( n /= 10 ) == 0 ) return 0;
int i = digitPos( n, digit );
return i == 0 ? 0 : i + 1;
}
int main( void )
{
printf( "%d\n", digitPos( 12345, 2 ) );
return 0;
}
The output is
4
Take into account that 0 is a valid digit.:)

Modify your code as below:
#include <stdio.h>
#include <string.h>
int count=1;
int digitPos(int n, int digit)
{
if(n==0) { count=0; return 0;}
if (n % 10 == digit) return 1;
count++;
digitPos(n/10, digit );
return count;
}
int main(void){
printf("%d",digitPos(12234,8));
return 0;
}
You don't have to divide digit by 10 as it will always give 0, instead divide n by 10.

Related

Calculating sum of certain previously inputted numbers

This program should calculate the sum of all numbers whose digits are in descending order. It stops you from inputting if the number isn't a whole number. I think that the problem might be because of the sum variable, but I don't know how to fix it.
Edit: Per #user3386109 request, here is the output I get:
4321
75
56
4,79
0
The sum should be 4396, as sum of 4321 and 75. Not 0.
Sorry for the unclear question I am quite new to this.
int n, last, secondlast, sum, c = 0;
int temp;
while (scanf("%d", &n) == 1) {
sum = 0;
while (temp > 0) {
last = temp % 10;
secondlast = (temp / 10) % 10;
if (secondlast > last) {
c++;
sum = sum + temp;
}
temp = temp / 10;
}
}
if (c == 0) {
printf("There are no numbers that meet the requirements\n");
}
else {
printf("%d\n", sum);
}
As #Support Ukraine commented, this code gets the job done.
#include <stdio.h>
int descendingDigits(int n)
{
int current = n % 10;
n = n / 10;
while(n)
{
int this = n % 10;
if (this <= current) return 0;
current = this;
n = n / 10;
}
return 1;
}
int main(void) {
int sum = 0;
int c = 0;
int n = 0;
while (scanf("%d", &n) == 1) {
if (descendingDigits(n))
{
sum = sum + n;
c = 1;
}
}
if (c == 0) {
printf("There are no numbers that meet the requirements\n");
}
else
{
printf("%d\n", sum);
}
return 0;
}
%10 operations are really not the best way to determine if the digits are descending. It works, but it seems like overkill to use scanf to convert the input to an integer at all, since it's much easier to know if the digits are in order if you leave them as a string. It's tempting to check if the digits of the string are descending and only convert to an integer value if they are, but it seems like a bad idea to parse the string twice. In other words; read the input as a string and do not convert, then compute the integer value while you are looking at the digits to see if they are descending. This is aesthetically appealing, since you minimize computations. (eg, if the input string is "47901", you shouldn't waste cpu cycles converting that to the integer 47901; after you see that 7 is not less than 4, you can abort).
eg:
#include <ctype.h>
#include <stdio.h>
/* If the string s represents an integer
* with (strictly) descending digits, return
* its integer representation (base 10). Else
* return 0.
*/
unsigned
is_descending(const char *s)
{
unsigned rv = 0;
int last = '9' + 1;
while( *s ){
if( isdigit(*s) && *s < last ){
rv = 10 * rv + *s - '0';
} else {
return 0;
}
last = *s++;
}
return rv;
}
int
main(int argc, char **argv)
{
char buf[64];
unsigned sum = 0;
while( scanf("%63s", buf) == 1 ){
sum += is_descending(buf);
}
printf("sum: %u\n", sum);
return 0;
}
Note that this does not handle negative numbers well, but it's not clear how you want to deal with that. Left as an exercise for the reader.

Find the position of a max on a number

I have C program that needs to find the position of a number. It goes like this:
From standard input we enter unknown number of number that are positive. The numbers have maximum of 5 digits, we read new numbers till the user enters a value that is not a number. I need to find the positions of the max digit of a number from right to left. Use the right-most position if there are more than one instance of the max digit.
The program needs to output the position and the number of times the max digit of a number was found at that position.
For example:
input:
97654 48654 12345 12343 1263 12443 12643 12777 #
output:
0: 2
1: 3
2: 1
3: 1
4: 1
because
Position: 4 3 0 1 1 1 2 0
v v v v v v v v
97654 48654 12345 12343 1263 12443 12643 12777 #
THE PROGRAM WORKS FOR THIS SPECIFIC TEST CASE
More test cases under the code.
Here is my code:
#include <stdio.h>
int main(){
int n;
int max;
int num,digit,pos,br0=0,br1=0,br2=0,br3=0,br4=0;
while (scanf("%d",&n)) {
max =0;
num = n;
pos=0;
while (num>0) {
digit = num%10;
if(digit > max){
max=digit;
pos++;
}
num/=10;
}
printf("%d\n",pos);
switch (pos) {
case 1: br0++; break;
case 2: br1++; break;
case 3: br2++; break;
case 4: br3++; break;
case 5: br4++; break;
}
}
printf("0: %d\n1: %d\n2: %d\n3: %d\n4: %d\n",br0,br1,br2,br3,br4);
return 0;
}
This program work for some test cases, such as
97654 48654 12345 12343 1263 12443 12643 12777 #
123 456 789 987 654 321 #
But not for:
542 8965 7452 1111 12 8 6532 98745 15926 #
75386 86142 94285 15926 35724 #
The problem with your program is that within this loop
while (num>0) {
digit = num%10;
if(digit > max){
max=digit;
pos++;
}
num/=10;
}
the variable pos is incremented only when a digit that is greater than previous digits is found. For example If you have a number like this
51234
then the first largest digit is 4 and the variable pos is set to 1. After that when the next largest digit is found that is the digit 5 the variable pos is incremented and becomes equal to 2 while actually the largest digit 5 is at the position 5.
You need to introduce one more variable as for example
max =0;
num = n;
pos=1;
int i = 1;
do
{
digit = num%10;
if(digit > max){
max=digit;
pos = i;
}
} while ( ( num /=10 ) && ( i++ != 5 ) );
I would write the program the following way
#include <stdio.h>
int main(void)
{
enum { N = 5 };
const unsigned int Base = 10;
size_t total[N] = { 0 };
unsigned int n;
while ( scanf( "%u", &n ) == 1 )
{
unsigned int pos = 0;
unsigned int max_digit = 0;
unsigned int i = 0;
do
{
unsigned int current_digit = n % Base;
if ( max_digit < current_digit )
{
pos = i;
max_digit = current_digit;
}
} while ( ( n /= Base ) && ( ++i != N ) );
++total[pos];
}
for ( unsigned int i = 0; i < N; i++ )
{
printf( "%u: %zu\n", i, total[i] );
}
return 0;
}
For the input
542 8965 7452 1111 12 8 6532 98745 15926 #
the program output is
0: 3
1: 0
2: 3
3: 2
4: 1
It may be fewer steps to do the work using fgets(), and keeping the input in string format. (verifying that it contains numeric characters.)
Plus, an array of values will be easier to keep tract of value to index relationships.
Here is an alternate way of getting the information you describe:
int main(void) {
char inBuf[20] = {0};
int index = 0;
int loops = 0;
int maxPos = 0;
int maxVal = 0;
printf("Enter a number : ");
while (fgets(inBuf, sizeof inBuf, stdin) && loops < 6) {
inBuf[strcspn(inBuf, "\r\n")] = 0;//remove unwanted white space
if(strstr(inBuf, "#")) return 0;//exit if "#"
if(digits_only(inBuf))
{
index = 0;
maxVal = inBuf[index];
while(inBuf[index])
{
if(inBuf[index] >= maxVal)
{
maxVal = inBuf[index];
maxPos = index;
}
index++;
}
printf("%d:%d \n", loops, maxPos);
loops++;
inBuf[0]=0;
}
else
{
printf("\n%s contains non-numeric characters, it cannot be converted.\n\nctrl-c to exit\n...Or enter a number : \n", inBuf);
}
};
return 0;
}
scanf is the wrong tool for this. (scanf is (almost) always the wrong tool). For this particular problem, you really want to treat the input as a string. As long as you don't want to accept inputs that look like "1e3" (which is a perfectly valid representation of an integer), you could just do something like:
#include <stdio.h>
#include <assert.h>
#include <ctype.h>
#include <string.h>
int
main(void){
int max = -1;
int br[5] = {0};
int maxpos = -1;
int len = 0;
int c;
while( (c = getchar()) != EOF ){
if( c && strchr("0123456789", c) ){
if( ++len > 5 ){
fputs("invalid input\n", stderr);
return 1;
}
assert( len > 0 && len < 6 );
if( c > max + '0' ){
maxpos = len;
max = c - '0';
}
} else if( isspace(c) ){
if( max > -1 ){
br[len - maxpos] += 1;
}
maxpos = -1;
len = 0;
max = '0' - 1;
} else {
fputs("invalid input\n", stderr);
return 1;
}
}
for( int i = 0; i < 5; i++ ){
printf("%d: %d\n", i, br[i]);
}
return 0;
}

can anyone simplify this code for me in c?

The sum of all odd digits of n.(eg. n is 32677, the sum would be 3+7+7=17)
Here is the code.
For this question, any of loop or function is acceptable, but not longer than this answer.
#include <stdio.h>
int main()
{
char n[20];
int m=0,i;
printf("Enter integers for the variable n: ");
for (i=0;i<20;i++)
{
scanf("%c",&n[i]);
if(n[i]=='\n')
{
break;
}
}
for (i=0;i<20;i++)// this is the part I would like to simplified
{
if (n[i]%2!=0)
{
if(n[i]==49)
m++;
if(n[i]==51)
m+=3;
if(n[i]==53)
m+=5;
if(n[i]==55)
m+=7;
else if(n[i]==57)
m+=9;
}
}
printf("The sum of odd digits of n is %d.",m);
}
Here are some tools/ideas you can use:
In ctype.h is a function isdigit() which tells you whether or not a character represents a digit.
Assuming the characters for the digits 0..9 are in sequence, the value represented by a character digit c is c-'0'
Here you are
#include <stdio.h>
int main( void )
{
enum { N = 20 };
char value[N];
printf( "Enter an unsigned integer: " );
size_t n = 0;
for ( char digit; n < N && scanf( "%c", &digit ) == 1 && digit != '\n'; ++n )
{
value[n] = digit;
}
unsigned int sum = 0;
for ( size_t i = 0; i < n; i++ )
{
if ( value[i] % 2 != 0 ) sum += value[i] - '0';
}
printf( "The sum of odd digits of the value is %u.\n", sum );
}
The program output might look like
Enter an unsigned integer: 0123456789
The sum of odd digits of the value is 25
Or you can add a check that an entered character is a digit. For example
#include <stdio.h>
#include <ctype.h>
int main( void )
{
enum { N = 20 };
char value[N];
printf( "Enter an unsigned integer: " );
size_t n = 0;
for ( char digit;
n < N && scanf( "%c", &digit ) == 1 && isdigit( ( unsigned char )digit );
++n )
{
value[n] = digit;
}
unsigned int sum = 0;
for ( size_t i = 0; i < n; i++ )
{
if ( value[i] % 2 != 0 ) sum += value[i] - '0';
}
printf( "The sum of odd digits of the value is %u\n", sum );
}
As for your code then in this loop
for (i=0;i<20;i++)
{
scanf("%c",&n[i]);
if(n[i]=='\n')
{
break;
}
}
you have to count how many digits were entered. And the new line character shall not be stored in the array. Otherwise this loop
for (i=0;i<20;i++)
can result in undefined behavior.
And you should not use magic numbers like for example 49.

Count zeroes with Recursion keep crashing

My code is supposed to count the number of zeroes using recursion.
However my program keeps crashing.
Expected output:
Input: 10500
Result: 3
Code:
void rCountZeros2(int num, int *result) {
if (num > 0) {
if ((num % 10) == 0) {
rCountZeros2((num / 10) + 1, *result);
}
rCountZeros2(num / 10, *result);
} else if (num == 0) {
*result = 1;
}
*result = num;
}
How do I make it work?
Here's the solution with and without using pointers
Hope this helps
#include <stdio.h> // For C++ #include<iostream>
// Without using pointer
int count_zeros_recursive2(int num) {
if (num % 10 == 0) {
if (num > 19 || num < -19) {
return 1 + count_zeros_recursive2(num / 10);
}
return 1;
}
if (num > 19 || num < -19) {
return count_zeros_recursive2(num / 10);
}
return 0;
}
// Using pointer
void count_zeros_recursive(int num, int *result) {
if (num % 10 == 0)
*result = *result + 1;
if (num > 19 || num < -19)
count_zeros_recursive(num / 10, result);
}
int count_zeros(int num) {
int result = 0;
count_zeros_recursive(num, &result);
//result = count_zeros_recursive2(num);
return result;
}
int main() {
int n;
while (1) {
scanf("%d", &n); // For C++ std::cin >> n;
printf("%d\n", count_zeros(n));// For C++ std::cout << n << "\n";
}
return 0;
}
eg Input: 1010
Output: 2
Input: 0
Output: 1
Input: 10204012410
Output: 4
Input: -101
Output: 1
I prefer returning the result instead of passing the pointer to the result.
Stop condition is when the number is a single digit, then if 0 you have 1 zero, otherwise none.
If the number is not a single digit, calculate the number of zeros in the number without the lowest digit (num/10) and add 1 to the returned value if the lowest digit was 0.
#include <stdio.h>
int count_zeros_recursive(int num)
{
int res = 0;
int num_without_lowest_digit = num/10;
if(num_without_lowest_digit == 0)
{
res = (num == 0);
}
else
{
res = count_zeros_recursive(num_without_lowest_digit);
if (num % 10 == 0)
{
res++;
}
}
return res;
}
int main(void) {
int nums[] = { 202, 7, 100, 10500, 10234, 10000};
int i;
for (i=0; i < sizeof(nums)/sizeof(nums[0]); ++i)
{
printf("Number %d has %d zeros\n", nums[i], count_zeros_recursive(nums[i]));
}
return 0;
}
Tested here
Number 202 has 1 zeros
Number 7 has 0 zeros
Number 100 has 2 zeros
Number 10500 has 3 zeros
Number 10234 has 1 zeros
Number 10000 has 4 zeros
Let's say you really want to use a pointer for some reason. Here's a full solution:
#include <stdio.h>
void rCountZeros2(int num, int *result)
{
if(num>0)
{
if( (num % 10) == 0)
{
*result = *result + 1;
}
rCountZeros2(num/10, result);
}
}
int main() {
int i = 0;
int n;
n = scanf("%d", &n);
int *result = &i;
rCountZeros2(n, result);
printf("%d\n", *result);
}
So what will happen is that you're effectively just updating the value at the location which result is pointing to, which means that you're really just storing the count in the variable i.
There is no need to pass a pointer if you can use a functional approach. Just return the value.
long recursiveZeroesCount(long num) {
if(num == 0) return 1;
if(num < 10) return 0;
if(num % 10 == 0) return 1 + recursiveZeroesCount(num / 10);
else return recursiveZeroesCount(num / 10);
}
Your program has undefined behavior because you pass the value of the *result instead of the pointer to the result variable to recursive calls. Furthermore, your algorithm is flawed as you cannot use this API recursively because the recursive calls update the result as well as the current call, a very impractical situation.
Here is a corrected version without recursion:
void rCountZeros2(int num, int *result) {
int count = 0;
for (;;) {
if (num % 10 == 0)
count++;
num /= 10;
if (num == 0)
break;
}
*result = count;
}
And here is a recursive implementation with a simpler API:
int rCountZeros2(int num) {
if (num % 10 == 0) {
if (num == 0)
return 1;
else
return 1 + rCountZeros2(num / 10);
} else {
if (num < 10)
return 0;
else
return rCountZeros2(num / 10);
}
}
The above function can be simplified as a single statement:
int rCountZeros2(int num) {
return !(num % 10) + ((num < 10) ? 0 : rCountZeros2(num / 10));
}

Returning a value with pointer ( C program)

I'm a beginner in C and below is a program to find the position of a given digit. My first function works but i can't say the same for the 2nd one(digitPos2) that returns the value from a pointer. I'm not sure what is wrong and why.
#include <stdio.h>
int digitPos1(int num, int digit);
void digitPos2(int num, int digit, int *result);
int main()
{
int number, digit, result=0;
printf("Enter the number: \n");
scanf("%d", &number);
printf("Enter the digit: \n");
scanf("%d", &digit);
printf("digitPos1(): %d\n", digitPos1(number, digit));
digitPos2(number, digit, &result);
printf("digitPos2(): %d\n", result);
main();//return 0;
}
int digitPos1(int num, int digit)
{
int pos=0;
while(num)
{
if(num%10 == digit)
{
return pos = pos + 1;
}
else
{
pos++;
num = num/10;
}
}
}
void digitPos2(int num, int digit, int *result)
{
int pos=0;
while(num)
{
if(num%10 == digit)
{
pos = pos + 1;
*result = pos;
}
else
{
pos++;
num = num/10;
}
}
*result = 0;
}
Output
The both functions are invalid.
For starters it is better to set the parameters num and digit as having the type unsigned int. Otherwise the functions will be more complicated. That is you will need to check whether one of the parameters or both are negative.
Secondly the function digitPos1 has undefined behavior because it returns nothing in case when the digit is not present in the number.
Moreover instead of the while loop you should use a do-while loop because num can be set by the user to 0 and 0 is a valid number.
This statement in the function digitPos2
*result = 0;
does not make sense.
And you have to exut the function if the digit is found
while(num)
{
if(num%10 == digit)
{
pos = pos + 1;
*result = pos;
// exit the function
}
//...
Also it is unclear how the user can determine whether the digit is not present in the number.
You can use an approach that returns for example -1 in case the digit is not present in the number.
Pay attention to that according to the C Standard the function main without parameters shall be declared like
int main( void )
Here is a demonstrative program
#include <stdio.h>
int digitPos1( unsigned int num, unsigned int digit);
void digitPos2( unsigned int num, unsigned int digit, int *result);
int main( void )
{
unsigned int number, digit;
int result;
printf( "Enter the number: " );
scanf( "%d", &number );
printf( "Enter the digit: " );
scanf( "%d", &digit );
printf("digitPos1(): %d\n", digitPos1( number, digit ) );
digitPos2(number, digit, &result);
printf( "digitPos2(): %d\n", result );
return 0;
}
int digitPos1( unsigned int num, unsigned int digit )
{
const unsigned int Base = 10;
int pos = -1;
int n = 0;
do
{
if ( num % Base == digit )
{
pos = n;
}
else
{
++n;
}
} while ( ( num /= Base ) && ( pos == -1 ) );
return pos;
}
void digitPos2( unsigned int num, unsigned int digit, int *result )
{
const unsigned int Base = 10;
int n = 0;
*result = -1;
do
{
if ( num % Base == digit )
{
*result = n;
}
else
{
++n;
}
} while ( ( num /= Base ) && ( *result == -1 ) );
}
The program output might look for example like
Enter the number: 123456
Enter the digit: 2
digitPos1(): 4
digitPos2(): 4
The position startrs from 0.
First of all,
In case the digit is not present at all you should return a index that is not possible in a real number, e.g. you can return a negative number in that case, may be -1. (In c/c++ indexing starts from 0 so 0 is always a valid index)
so for digitPos1(int num, int digit) the ending should look like
while(num){
//your code
//return pos + 1 in case digit found
//more code
}
return -1;
similarly for digitPos2(int num, int digit, int *result) you should initialize *result with -1
int pos=0;
*result = -1;
and the biggest mistake is to set *result=0 at the end. To understand this you should understand that while dealing with pointers, every change you make to the pointers value is reflected in the callee function also, so if you set *result=0 then all the previous computation is just wasted and the position is returned blindly as 0. So you MUST remove this line for your computations to reflect back in the main function.
Secondly,
I don't think you have considered the cases of duplicates, e.g.
num : 1232323
digit : 3
Here, ideally you should break or return after you have found the match in case of digitPos2
*result = pos;
return; //return type is void
This changes should give expected behaviour according to me.

Resources