Powers of 2 above and below input - c

I have the programming reading in middle just fine however using the pointer with below and above is not giving the correct value to be found using middle.
Why is below (most likely above as well) negative when running in the for loop?
Am I calling using pointers in the correct way?
/*
*
*Function pwrTwo has one parameter "middle" it reads the inout from the user
*to find below and above
*
*the function is used to find the highest power of two below middle
*and the lowest power of two above middle
*
*The function then returns the two values and they are printed in the
* the main function displayed as below<middle<above
*
*/
#include <stdio.h>
int pwrTwo(int m, int*above, int*below) {
int i = 0;
*above = 0;
*below = 0;
for (i = 2; *below < m; i += 1) {
*below = pow(2, i);
printf("%d,%d,%d\n", below, m, i); //my check to see if below middle and i are correct
}
for (i += 3; *above > m; i -= 1) {
*above = pow(2, i);
printf("%d,%d,%d\n", below, m, above); // checking again
}
return;
}
int main() {
int middle = 1;
int above = 0;
int below = 0;
while (middle > 0) {
printf("Please input a value:");
scanf("%d", &middle);
pwrTwo(middle, &above, &below);
printf("%d<%d<%d\n", below, middle, above);
}
}

You need to include to use pow function
Since you are getting the values in the parameters, your return type should be void,
and you dont need to use pointers in this case, you want just one value for below, and one for above, so you just use a int..but...
you can work with this:
void pwrTwo(int m, int*above,int*below){
double log2m = log2(m);
*below = pow(2,floor(log2m));
*above = pow(2,ceil(log2m));
}

You are using printf with an int* instead of in an int. I am surprised your compiler did not give you warnings, since my compiler gives me warnings about this.
When you print a pointer as an int, you will get a negative number if the sign bit happens to be set for the address it stores.
Try changing
printf("%d,%d,%d\n",below,m,i)
to
printf("%d,%d,%d\n",*below,m,i)
as well as changing printf("%d,%d,%d\n",below,m,above) to printf("%d,%d,%d\n",*below,m,*above).

#3 is the main issue.
1) Missing #include <math.h>
2) Mis-matched return. Change from
int pwrTwo(int m, int*above, int*below) {
...
return;
}
to
void pwrTwo(int m, int*above, int*below) {
...
// return;
}
3) Wrong types in printf()
// printf("%d,%d,%d\n", below, m, i);
printf("%d,%d,%d\n", *below, m, i);
...
// printf("%d,%d,%d\n", below, m, above);
printf("%d,%d,%d\n", *below, m, *above);
...
4) Good idea to check return value from scanf()
// scanf("%d", &middle);
if (scanf("%d", &middle) != 1) Handle_Error();
5) Code may simplify. Watch out for range errors.
// some_int = pow(2, i);
some_int = 1 << i;

Related

recursive Function, to find even or odd digits inside given number

Basically, its printing only one instance when it happens, and i don't understand why, maybe has something to do with the code reseting every time and starting the variable at 0 again, and i got another question if someone can help me with, i have to return both values when its odd and even, like how many digits are even and odd at the same time, i'm having a little trouble figuring out how to do it
#include <stdio.h>
int digits(int n)
// function that checks if the given value is odd or even, and then add
// + 1 if it's even, or odd, it's supposed to return the value of the quantity
// of digits of the number given by the main function
{
int r;
int odd = 0;
int even = 0;
r = n % 10;
if (r % 2 == 0) // check if given number is even
{
even = even + 1;
}
if (r % 2 != 0) // check if its odd
{
odd = odd + 1;
}
if (n != 0) {
digits(n / 10); // supposed to reset function if n!=0 dividing
// it by 10
}
if (n == 0) { return odd; }
}
int
main() // main function that sends a number to the recursive function
{
int n;
printf("type number in:\n ");
scanf("%d", &n);
printf("%d\n", digits(n));
}
odd and even variables are local in your code, so they are initialized by zero every time.
I think they should be declared at caller of the recursive function, or be declared as global variables.
#include <stdio.h>
void digits(int n, int *even, int *odd)//function
{
int r;
r = n % 10;
if (r % 2 == 0)//check if given number is even
{
*even = *even + 1;
}
else //otherwise, its odd
{
*odd = *odd + 1;
}
n /= 10;
if (n != 0)
{
digits(n, even, odd);//supposed to reset function if n!=0 dividing it by 10
}
}
int main()
{
int n, even = 0, odd = 0;
printf("type number in:\n ");
scanf("%d", &n);
digits(n, &even, &odd);
printf("even: %d\n", even);
printf("odd: %d\n", odd);
return 0;
}
Maybe I found the problem you are facing. You you initialized you odd and even variable as zero. every time you call the function it redeclares their value to zero again. You can use pointer caller or use those as your global variable so that every time they don't repeat their initial values again.
Implementing a function that counts the number of odd and even digits in a number, is not to be done using recursive. That is simply a wrong design choice.
But I assume that it's part of your assignment to use recursion so ... okay.
You want a function that can return two values. Well, in C you can't!! C only allows one return value. So you need another approach. The typical solution is to pass pointers to variables where the result is to be stored.
Here is the code:
void count_odd_even(const int n, int *even, int *odd)
{
if (n == 0) return;
if (((n % 10) % 2) == 1)
{
*odd += 1;
}
else
{
*even += 1;
}
count_odd_even(n/10, even, odd);
}
And call it like
int odd = 0;
int even = 0;
count_odd_even(1234567, &even, &odd);

Need to generate 4 random numbers without repetition in C programming. 1 to 4

I want to generate numbers 1 to 4 in a random fashion using C programming.
I have made provision to print a[0] directly in a while loop and for any further element the program checks whether the new number from a[1] to a[3] is same as any of the previous elements. A function has been created for the same. int checkarray(int *x, int y).
The function checks current element with previous elements one by one by reducing the passed address. If it matches the value it exits the loop by assigning value zero to the condition variable (int apply).
return apply;
In the main program it matches with the int check if check==1, the number is printed or else the loop is repeated.
Problem faced: The number of random numbers generated is varying between 2 and 4.
e.g
2 4
2 4 3
1 3 3 4
etc
Also repetition is there sometimes.
#include <stdio.h>
#include <conio.h>
int checkarray(int *x, int y);
void main() {
int a[4], i = 0, check;
srand(time(0));
while (i < 4) {
a[i] = rand() % 4 + 1;
if (i == 0) {
printf("%d ", a[i]);
i++;
continue;
} else {
check = checkarray(&a[i], i);
}
if (check == 1) {
printf("\n%d ", a[i]);
} else {
continue;
}
i++;
}
getch();
}
int checkarray(int *x, int y) {
int arrcnt = y, apply = 1, r = 1;
while (arrcnt > 0) {
if (*x == *(x - 2 * r)) {
apply = 0;
exit(0);
} else {
arrcnt--;
r++;
continue;
}
}
return apply;
}
Let's look at the checkarray function, which is supposed to check if a number is already present in the array.
It is called this way:
check = checkarray(&a[i], i);
Where a is an array of 4 integers and i is the actual index, so it tries to scan the array backwards looking for any occurrences of a[i]
int checkarray(int *x,int y)
{
int arrcnt=y,apply=1,r=1;
while(arrcnt>0)
{
if(*x==*(x-2*r))
// ^^^ Why? This will cause an out of bounds access.
{
apply = 0;
exit(0); // <-- This ends the program. It should be a 'break;'
}
else
{
arrcnt--;
r++;
continue;
}
}
return apply;
}
Without changing the interface (which is error prone, in my opinion) it could be rewritten as
int check_array(int *x, int y)
{
while ( y )
{
if ( *x == *(x - y) )
return 0;
--y;
}
return 1;
}
Testable here.
There are many other issues which should be addressed, though, so please, take a look to these Q&A too.
Does "n * (rand() / RAND_MAX)" make a skewed random number distribution?
Why do people say there is modulo bias when using a random number generator?
Fisher Yates shuffling algorithm in C
int main() vs void main() in C
Why can't I find <conio.h> on Linux?
Your approach is tedious but can be made to work:
there is no need to special case the first number, just make checkarray() return not found for an empty array.
you should pass different arguments to checkarray(): a pointer to the array, the number of entries to check and the value to search.
you should not use exit(0) to return 0 from checkarray(): it causes the program to terminate immediately.
Here is a modified version:
#include <stdio.h>
#include <conio.h>
int checkarray(int *array, int len, int value) {
int i;
for (i = 0; i < len; i++) {
if (array[i] == value)
return 0;
}
return 1;
}
int main() {
int a[4], i = 0, value;
srand(time(0));
while (i < 4) {
value = rand() % 4 + 1;
if (checkarray(a, i, value)) {
printf("%d ", value);
a[i++] = value;
}
}
printf("\n");
getch();
return 0;
}

Weird pattern when I try to generate a 4-digit integer for which every digit is distinct

When I try to write a small program in C language that is intended to generate a 4-digit integer for which every digit is distinct and nonzero, the returned value is always in pattern like 1abc: the first digit seems to always be 1, and sometimes the returned value will be more than 4-digit like 56127254. Could anyone help me look into this? Thank you very much in advance.
So basically the program includes two functions, int isvalid(int n) and int choose_N(void).
isValid return 1 if the integer consists of exactly 4 decimal digits, and all these digits are nonzero and distinct, and 0 otherwise.
And int choose_N(void) generates an integer that is 4-digit and all the digits are distinct and nonzero.
Here is my code:
#define N_DIGITS 4
....
....//the main function
int isvalid(int n){
int i, x; int check[N_DIGITS]={0};
for(i=1;i<=N_DIGITS;i++){ //check whether all digits are nonzero
if((check[i-1]=n%10)==0){
return 0;
}
n /= 10;
}
for(i=0;i<N_DIGITS-1;i++){ // check whether all digits are distinct
for(x=i+1;x<N_DIGITS;x++){
if(check[i]==check[x])
return 0;
}
}
return 1;
}
int choose_N(void){
int i; int number=0;
while(!isvalid(number)){
for(i=0;i<N_DIGITS;i++){
srand(time(0));
number += ((10^i)*(rand()%10));
}
}
return number;
}
For srand(time(0));, I have tried various alternatives like srand(time(0)+i); or put this statement out of while loop, but those attempts seemingly did not work and still the returned value of choose_Nstill showed the werid pattern that I described.
your choose_N method has several issues:
First, if the number isn't valid, you're not resetting it to 0, so it just grows and grows.
Second, srand(time(0)) is not necessary within the loop (and could yield the same result for several iterations), just do it at program start (srand() — why call it only once?)
Third and biggest mistake: 10 ^ i is 10 xor i, not 10**i. You can use an aux value and multiply by 10 in your loop. Since number of digits is low, no risk of overflow
minor remark: you want to pass in the loop at least once, so use a do/while construct instead, so you don't have to force the first while test.
I'm trying to fix your code:
int choose_N(void){
int i, number;
do
{
number = 0;
int p = 1;
for(i=0;i<N_DIGITS;i++)
{
number += p*(rand()%10);
p *= 10;
}
} while(!isvalid(number));
return number;
}
While #Jean-François-Fabre answer is the right one, it is not optimal algorithm. Optimal algorithm in such case would be using FIsher-Yates-Knuth shuffle and Durstenfeld's implementation.
Shuffling right array will produce numbers which are automatically valid, basically no need for isvalid(n) anymore.
Code
// Swap selected by index digit and last one. Return last one
int
swap_array(int digits[], int idx, int last) {
if (idx != last) { // do actual swap
int tmp = digits[last];
digits[last] = digits[idx];
digits[idx] = tmp;
}
return digits[last];
}
int
choose_N_Fisher_Yates_Knuth() {
int digits[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
int r = 0;
for (int k = 0; k != N_DIGITS; ++k) {
int idx = rand() % (9 - k);
int n = swap_array(digits, idx, (9 - k) - 1);
r = r * 10 + n;
}
return r;
}
int
main() {
srand(12345);
int r, v;
r = choose_N_Fisher_Yates_Knuth();
v = isvalid(r);
printf("%d %d\n", r, v);
r = choose_N_Fisher_Yates_Knuth();
v = isvalid(r);
printf("%d %d\n", r, v);
r = choose_N_Fisher_Yates_Knuth();
v = isvalid(r);
printf("%d %d\n", r, v);
r = choose_N_Fisher_Yates_Knuth();
v = isvalid(r);
printf("%d %d\n", r, v);
return 0;
}
Output
7514 1
6932 1
3518 1
5917 1

Reverse two numbers and obtain the reverse of the sum

I am coming to SO as a last resort. Been trying to debug this code for the past 2 hours. If the question is suited to some other SE site, please do tell me before downvoting.
Here it goes:
#include <stdio.h>
#include<math.h>
int reverse(int n) {
int count = 0, r, i;
int k = (int)log(n * 1.0);
for(i = k; i >= 0; i--)
{
r = (n % 10);
n = (n / 10);
count = count + (r * pow(10, k));
}
return count;
}
int main(void) {
int t;
scanf("%d", &t);
while(t--)
{
int m, n, res;
scanf("%d %d", &m, &n);
res = reverse(m) + reverse(n);
printf("%d", reverse(res));
}
return 0;
}
My objective is to get 2 numbers as input, reverse them, add the reversed numbers and then reverse the resultant as well.I have to do this for 't' test cases.
The problem: http://www.spoj.com/problems/ADDREV/
Any questions, if the code is unclear, please ask me in the comments.
Thank you.
EDIT:
The program gets compiled successfully.
I am getting a vague output everytime.
suppose the 2 numbers as input are 24 and 1, I get an output of 699998.
If I try 21 and 1, I get 399998.
Okay, if you had properly debugged your code you would have notices strange values of k. This is because you use log which
Computes the natural (base e) logarithm of arg.
(took from linked reference, emphasis mine).
So as you are trying to obtain the 'length' of the number you should use log10 or a convertion (look at wiki about change of base for logarithms) like this: log(x)/log(10) which equal to log10(x)
And now let's look here: pow(10, k) <-- you always compute 10^k but you need 10^i, so it should be pow(10, i) instead.
Edit 1: Thanks to #DavidBowling for pointing out a bug with negative numbers.
I don't know how exactly you have to deal with negative numbers but here's one of possible solutions:
before computing k:
bool isNegative = n < 0;
n = abs(n);
Now your n is positive due to abs() returning absolute value. Go on with the same way.
After for loop let's see if n was negative and change count accordingly:
if (isNegative)
{
count = -count;
}
return count;
Note: Using this solution we reverse the number itself and leave the sign as it is.
It looks like Yuri already found your problem, but might I suggest a shorter version of your program? It avoids using stuff like log which might be desirable.
#include <stdio.h>
int rev (int n) {
int r = 0;
do {
r *= 10;
r += n % 10;
} while (n /= 10);
return r;
}
int main (void) {
int i,a,b;
scanf("%d",&i);
while (i--) {
scanf("%d %d",&a,&b);
printf("%d\n",rev(rev(a) + rev(b)));
}
return 0;
}
Hopefully you can find something useful to borrow! It seems to work okay for negative numbers too.
Under the hood you get char string, reverse it to numeric, than reverse it to char. Since is more comfortable work with chars than let's char:
char * reverse (char *s,size_t len) //carefull it does it in place
{
if (!len) return s;
char swp, *end=s+len-1;
while(s<end)
{
swp =*s;
*s++=*end;
*end--=swp;
}
return s;
}
void get_num(char *curs)
{
char c;
while((c=getchar())!='\n')
*curs++=c;
*curs=0;
}
int main()
{
double a,b,res;
char sa[20],sb[20],sres[20],*curs;
get_num( sa);
get_num(sb);
reverse(sa,strlen(sa));
reverse(sb,strlen(sb));
sscanf(sa,"%f",&a);
sscanf(sb,"%f",&b);
res=a+b;
sprintf(sres,"%f",res);
reverse(sres);
printf(sres);
}

Trying to write a function to shuffle a deck in C

So all I'm trying to do is take an input from the user of how many cards to use and then randomly assign each card to a different index in an array. I'm having extensive issues getting the rand function to work properly. I've done enough reading to find multiple different ways of shuffling elements in an array to find this one to be the easiest in regards to avoiding duplicates. I'm using GCC and after I input the amount of cards I never get the values from the array back and if I do they're all obscenely large numbers. Any help would be appreciated.
#include <time.h>
#include <stdlib.h>
#include <stdio.h>
void main(){
srand(time(NULL));
int d, c, i, z, l, r;
printf("Enter the deck length: ");
scanf("%d\n ", &c);
int deck[c];
int swap[c];
z = c;
for(l=0; l<c; l++){
swap[l] = l;
}
for(i=z; i=0; i--){
r = rand() / i
deck[i] = swap[r];
for(r; r=(c-1); r++){
swap[r] = swap[(r+1)];
}
}
for(d = 0; d < c; d++){
printf("%d ", deck[d]);
}
return;
}
I can spot one major problem here:
for(i=z; i=0; i--)
^^^
This loop will never execute since you are using assignment(=) and setting i to 0 therefore the condition will always be false, although using equality(==) will still be false in this case, you probably want:
for(i=z; i!=0; i--)
This means you will be using deck unitialized which is undefined behavior. Once you fix that you have a similar problems here:
for(r; r=(c-1); r++){
main has to return int and your return at the end needs to provide a value.
Turning on warning should have allowed you to find most of these issues, for example using -Wall with gcc gives me the following warning for both for loops:
warning: suggest parentheses around assignment used as truth value [-Wparentheses]
Note, see How can I get random integers in a certain range? for guidelines on how to use rand properly.
You basically need to be able to generate 52 numbers pseudo-randomly, without repeating. Here is a way to do that...
First, loop a random number generator 52 times, with a method to ensure none of the random numbers repeat. Two functions in addition to the main() will help to do this:
#include <ansi_c.h>
int NotUsedRecently (int number);
int randomGenerator(int min, int max);
int main(void)
{
int i;
for(i=0;i<52;i++)
{
printf("Card %d :%d\n",i+1, randomGenerator(1, 52));
}
getchar();
return 0;
}
int randomGenerator(int min, int max)
{
int random=0, trying=0;
trying = 1;
while(trying)
{
srand(clock());
random = (rand()/32767.0)*(max+1);
((random >= min)&&(NotUsedRecently(random))) ? (trying = 0) : (trying = 1);
}
return random;
}
int NotUsedRecently (int number)
{
static int recent[1000];//make sure this index is at least > the number of values in array you are trying to fill
int i,j;
int notUsed = 1;
for(i=0;i<(sizeof(recent)/sizeof(recent[0]));i++) (number != recent[i]) ? (notUsed==notUsed) : (notUsed=0, i=(sizeof(recent)/sizeof(recent[0])));
if(notUsed)
{
for(j=(sizeof(recent)/sizeof(recent[0]));j>1;j--)
{
recent[j-1] = recent[j-2];
}
recent[j-1] = number;
}
return notUsed;
}

Resources