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.
Related
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.
I am working on code to reverse an unsigned int whose bits are the same but in reverse order. My code wont stop running while taking user input. What am I doing wrong?
#include <stdio.h>
unsigned int reverse_bits(unsigned int n);
int main(void) {
unsigned int n;
printf("Enter an unsigned integer: ");
scanf("%u",&n);
printf("%u\n",reverse_bits(n));
return 0;
}
unsigned int reverse_bits(unsigned int n) {
unsigned int reverse = 0;
while(n>0) {
reverse <<= 1;
if((n & 1) == 1) {
reverse = reverse^1;
}
}
return reverse;
}
In your program, the while condition is checking whether n is greater than zero. However, inside the loop, there was no operation that modifies the n. So please try using this. It will work.
unsigned int reverse_bits(unsigned int n) {
unsigned int reverse = 0;
while (n>0) {
reverse <<=1;
if((n & 1) == 1) {
reverse = reverse | 1;
}
n=n>>1;
}
return reverse;
}
as #Mark Benningfield said you forget to modify n inside the loop and the
best way to reverse a string is:-
It only runs upto when the leftmost bit is 1.
unsigned int reverse_bits(unsigned int n)
{
unsigned int reverse = 0;
int x = 1;
while ( n > 0 )
{
reverse = reverse << 1;
if ( n & x )
reverese = reverse | 1;
n = n >> 1;
}
return reverse;
I know I could have found the code page on the Internet easily enough for that function, but I want to know why, after passing the 10 digit array, the expected result doesn't act like the previous ones.
#include <stdio.h>
int xstraylen(char *arr) {
int len;
for (len = 0; *(arr + len) != '\0'; len++) {
//printf("%c ", *(arr + len));
}
return len;
}
int str_into_int(char *str) {
int power = 10, len, number;
long int value = 0;
len = xstraylen(str);
printf("\n%d\n", len);
for (int index = 0; index < len; index++) {
number = (int)(*(str + index) - 48);
value += number;
value *= power;
printf("-%d- %d %d ", index, number, value);
}
value /= power;
return value;
}
int main() {
char *str = "1234567890";
int value;
value = str_into_int(str);
printf("\n\n%d", value);
return 0;
}
Output
10
-0- 1 10 -1- 2 120 -2- 3 1230 -3- 4 12340 -4- 5 123450 -5- 6 1234560 -6- 7 12345670 -7- 8 123456780 -8- 9 1234567890 -9- 0 -539222988
-53922298
Your code does not work for 10 digit numbers because you always multiply value by 10 in the loop after adding the digit and divide it at the end. For a 10 digit number, the last multiplication causes an arithmetic overflow on your platform where both int and long probably have 32 bits.
You should multiply value before adding the digit and remove the final division:
int str_into_int(char *str) {
int power = 10, len, number;
long int value = 0;
len = xstraylen(str);
printf("\n%d\n", len);
for (int index = 0; index < len; index++) {
value *= power;
number = (int)(*(str + index) - 48);
value += number;
printf("-%d- %d %ld ", index, number, value);
}
return value;
}
Note that the code can be further simplified and modified to handle larger values and detect overflow:
#include <limits.h>
#include <stdio.h>
unsigned long long int str_into_int(const char *str) {
unsigned long long int value = 0;
for (int i = 0; str[i] >= '0' && str[i] <= '9'; i++) {
unsigned int digit = str[i] - '0';
if (value > ULLONG_MAX / 10 ||
(value == ULLONG_MAX / 10 && digit > ULLONG_MAX % 10)) {
printf("conversion exceeds range of unsigned long long\n");
return ULLONG_MAX;
}
value = value * 10 + digit;
}
return value;
}
void test(const char *str) {
printf("%s -> %llu\n", str, str_into_int(str));
}
int main() {
test("1234567890");
test("12345678901234567890");
test("18446744073709551615");
test("18446744073709551616");
test("123456789012345678901234567890");
return 0;
}
Output:
1234567890 -> 1234567890
12345678901234567890 -> 12345678901234567890
18446744073709551615 -> 18446744073709551615
conversion exceeds range of unsigned long long
18446744073709551616 -> 18446744073709551615
conversion exceeds range of unsigned long long
123456789012345678901234567890 -> 18446744073709551615
Your compiler considers the type long int as having the same range of values as the type int.
In this expression statement
value *= power;
there an overflow occurs when value is equal to 1234567890.
Change the logic of the for loop the following way
for (int index = 0; index < len; index++) {
value *= power;
number = *(str + index) - '0';
value += number;
printf("-%d- %d %ld ", index, number, value);
}
and remove this statement
value /= power;
Bear in mind that your function does not process a sign mark.
Take into account the function xstraylen should be declared the following way
size_t xstraylen( const char *arr ) {
size_t len = 0;
while ( *( arr + len ) ) ++len;
return len;
}
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.
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.