Memory Allocation in C and passing multiple numbers - c

I'm having a difficult time figuring out how'd I'd accomplish a task and am looking for help.
So, I need to use a function that'll find a pair of numbers (to be allocated dynamically) that meets a condition and returns a pointer to it.
Here's what I have:
int* f_cubes_sum(int n)
{
//Declaring array
int *numSet;
numSet = (int *)malloc(2); // Only two because I'm looking for a pair
//Declaring variables
int sum = 0;
int a = 0;
int b = 0;
bool results = false;
while (b < n && results == false)
{
while (a < n)
{
sum = a^3 + b^3;
if (sum == n)
{
results = true;
}
else
{
a = a + 1;
}
sum = 0;
}
if (results = false)
{
a = 0;
b = b + 1;
}
}
if (results = false)
{
a = NULL;
b = NULL;
}
numSet[0] = a;
numSet[1] = b;
free(numSet);
return numSet;
}
And in my main function, how would I access both numbers?
Thank you for your time

You are looking for a function that determines whether a number can be written a the sum of two cubes and if so, it should yield the two numbers whose cubes are summed. Basically you need:
an information on whether n can be written as a³ + b³ and
if so, the values of a and b.
You can use your approach of allocating an array of two integers and return that on success and NULL on failure. If you do so, you should allocate the array only if you have a result:
int *f_cubes_sum(int n)
{
int a, b;
// logic to work out whether a³ + b³ == n
if (a*a*a + b*b*b == sum) {
int *res = malloc(2 * sizeof(*res));
res[0] = a;
res[1] = b;
return res;
}
// no solution found
return NULL;
}
The drawback here is that the calling code has to free the returned pointer:
int *res = f_cubes_sum(2778);
if (res) {
printf("%d, %d\n", res[0], res[1]);
free(res);
}
Another approach is to pass in an array that your code has to fill and indicate success or failure with a boolean return value:
bool f_cubes_sum(int n, int res[2])
{
int a, b;
// logic to work out whether a³ + b³ == n
if (a*a*a + b*b*b == sum) {
res[0] = a;
res[1] = b;
return true;
}
// no solution found
return false;
}
Now the calling code has to provide the space for the result:
int res[2];
if (f_cubes_sum(2778, res)) {
printf("%d, %d\n", res[0], res[1]);
}
Of course, because you are always dealing with two possible result values, you could also pass pointers to these values instead of passing an array. Here's a variant of your function that does this:
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
bool f_cubes_sum(int n, int *pa, int *pb)
{
int a = 0;
while (1)
{
int a3 = a*a*a;
if (a3 > n) break;
int b = cbrt(n - a3) + 0.5;
int b3 = b*b*b;
if (a3 + b3 == n) {
*pa = a;
*pb = b;
return true;
}
a++;
}
return false;
}
int main(void)
{
int a, b;
int n = 35001;
if (f_cubes_sum(n, &a, &b)) {
printf("%d^3 + %d^3 == %d\n", a, b, n);
} else {
printf("Nothing found for %d.\n", n);
}
return 0;
}
Also note what commenters have alreadey pointed out:
In C, = assigns, == compares. Unfortunately, an assignment inside an iF condition is valid C: It will assign the value and then test it, entering the clause if it isn't 0 or false. Therefore if (x = false) never enters the if clause. Switch on warnings to carch such mistakes.
The ^ operator isn't the power operator, it is the bitwise xor operator. Raising a number a to the power of b is done with the floating-point function pow(a, b). If the exponent is a known small integer, it is usually better to write the multiplication explicitly. Thus, pow(a, 3) is rendered better as a*a*a.
When allocating memory, be sure the make enough room for the desired type. Also don't use freed pointers; the memory they point to is invalid.

Related

How do I process the return value inf

I working through a book on C on my own. This isn't homework to be turned in. I am writing a C program to determine the largest Fibonacci number my machine can produce. And instructed to use a nonrecursive method.
My Code:
#include<stdio.h>
double fibo(int n);
int main(void)
{
int n = 0; // The number input by the user
double value; // Value of the series for the number input
while (n >= 0)
{
// Call fibo function
value = fibo(n);
// Output the value
printf("For %d the value of the fibonacci series = %.0f\n", n,
value);
n++;
}
return 0;
}
double fibo(int n)
{
int i; // For loop control variable
double one = 0; // First term
double two = 1; // Second term
double sum = 0; // placeholder
if (n == 0)
return 0;
else if (n == 1)
return 1;
else
{
for (i = 2; i <= n; i++)
{
sum = one + two;
one = two;
two = sum;
}
}
return sum;
Code works fine but I want to to break when the output gives me the fist instance of :
For 17127 the value of the fibonacci series = inf
Is there way to us an if statement like:
if (value == inf)
break;
The simplest is to use INFINITY or isinf().
Just did a little search and found this nice trick:
...
double value, temp; // Value of the series for the number input
while (n >= 0)
{
// Call fibo function
temp = fibo(n);
if (temp - temp != 0)
break;
else
value=temp;
...
well it turns out that whats happening is when temp hits Inf the if condition temp - temp produces Nan which equals nothing and the rest is just executing break; to exit the process.
I want to to break when the output gives me the first instance of : inf
Simply test against INFINITY from <math.h>. The output will not be an exact Fibonacci number.
#include <math.h>
#include <stdio.h>
int main(void) {
double a;
double b = 0;
double c = 1;
do {
a = b;
b = c;
c = a + b;
} while (c < INFINITY);
printf("%e\n", b);
return 0;
}
Output
1.306989e+308
long double
Use the widest floating point type and look for an inexact addition.
#include <fenv.h>
#include <stdio.h>
int main(void) {
long double a;
long double b = 0;
long double c = 1;
do {
a = b;
b = c;
c = a + b;
} while (fetestexcept(FE_INEXACT) == 0);
printf("%.0Lf\n", b);
return 0;
}
Output
12200160415121876738
Integers
Use the widest type available. This is akin to #Syed.Waris unsigned long long approach. Although common that unsigned long long and uintmax_t have the same range, using uintmax_t insures the widest.
uintmax_t: The following type designates an unsigned integer type capable of representing any value of any unsigned integer type:
#include <stdint.h>
#include <stdio.h>
uintmax_t a;
uintmax_t b = 0;
uintmax_t c = 1;
do {
a = b;
b = c;
c = a + b;
} while(c >= b);
printf("%ju\n", b);
Output
12200160415121876738
String
An alternative to double or some int type, is to create a simple string add function str_add(), then quite easy to form large Fibonacci numbers.
int main(void) {
char fib[3][4000];
strcpy(fib[0], "0");
strcpy(fib[1], "1");
int i;
for (i = 2; i <= 17127 && strlen(fib[1]) < sizeof fib[1] - 1; i++) {
printf("Fib(%3d) %s.\n", i, str_add(fib[2], fib[1], fib[0]));
strcpy(fib[0], fib[1]);
strcpy(fib[1], fib[2]);
}
printf("%zu\n", strlen(fib[2]));
return 0;
}
Output
Fib(1476) 13069...(299 digits)....71632. // Exact max `double`
Fib(17127) 95902...(3569 digits)...90818.
largest Fibonacci number my machine can produce
This question is not concerned with any data type but it is concerned with machine.
The basic rule of fibonacci is this:
n = (n-1) + (n-2)
You can take a big sized unsigned long long variable and you can keep on adding. But what if that datatype is overflowed? You are not concerned with data type. Your machine may produce a number even bigger than the long long. What would that number be ? Entire bits on RAM? Hard Disk ?
Since you are required to use an iterative method and not recursive method, your teacher/book/instructor might be testing you on loops (and not any standard API). Below is sample code using unsigned long long:
#include <stdio.h>
int main ()
{
unsigned long long a = 0;
unsigned long long b = 1;
unsigned long long c = a + b;
while(c >= b)
{
a = c;
c = b + c;
b = a;
}
printf("\n%llu\n", b);
return 0;
}
Output:
12200160415121876738

Segmentation fault during memory allocation [duplicate]

Somewhere in my code I am doing something very bad. I'm getting undefined behavior in my extrema variable when it does run but most of the time it doesn't even run. Any help would be really great.
#include <stdio.h>
void get_extrema(int quadrant, int **extrema)
{
if (quadrant == 1)
{
*(extrema)[0] = 0;
*(extrema)[1] = 90;
}
else if (quadrant == 2)
{
*(extrema)[0] = -90;
*(extrema)[1] = 0;
}
}
void print(int* arr)
{
printf("%i",arr[0]);
printf(",");
printf("%i\n",arr[1]);
}
int main(void)
{
int *extrema = (int*)malloc(2*sizeof(int));
get_extrema(1,&extrema);
print(extrema);
get_extrema(2,&extrema);
print(extrema);
}
I also tried editing the extrema array using pointer arithmetic like the following:
**(extrema) = 0;
**(extrema+1) = 90;
But that did not work either. I really have no clue where this is going wrong and I could really use some help.
The reason you get undefined behavior is that the subscript operator [] takes precedence over the indirection operator *. The value of extrema is indexed as an array of pointers, which is incorrect, because there's only a single pointer there.
Since you are passing a pointer to a pointer, you need to put the asterisk inside parentheses:
if (quadrant == 1)
{
(*extrema)[0] = 0;
(*extrema)[1] = 90;
}
else if (quadrant == 2)
{
(*extrema)[0] = -90;
(*extrema)[1] = 0;
}
Demo on ideone.
a[b] is equal to *(a + b), but has higher precedence than the *. (And like a + b is b + a, so is a[b] equal to b[a]; and 5[a] equal to a[5]).
Thus:
*(extrema)[1] = 90;
// is equal to
*(*(extrema + 1)) = 99;
// When what you want to do is
*((*extrema) + 1) = 99;
// which is of course equal to
(*extrema)[1] = 99;
However, an even better question is: why are you using the double pointer, when it is not needed.
void get_extrema(int quadrant, int *extrema)
{
if (quadrant == 1)
{
extrema[0] = 0;
extrema[1] = 90;
}
else if (quadrant == 2)
{
extrema[0] = -90;
extrema[1] = 0;
}
}
void print(int *arr)
{
printf("%i,%i\n", arr[0], arr[1]);
}
int main(void)
{
int *extrema = (int *)malloc(2 * sizeof (int));
get_extrema(1, extrema);
print(extrema);
get_extrema(2, extrema);
print(extrema);
}

How to use a nested if else statements in a for loop in c

I'm having issues with my for statement. I'm trying to have a nested if else statement inside and I'm using pointers. I've tried everything and I've looked all over the internet. I've placed comments beside the lines with errors but if you see something else that's wrong please let me know. Thank you
#include <stdio.h>
#include <stdlib.h>
#define TRUE 1
#define FALSE 0
void getinput(double*xptr, int*nptr)
{
int flag;
do
{
flag = TRUE;
printf("What is the value of x and the number of terms:");
scanf("%lf %i", xptr, nptr);
if (*nptr <= 0)
{
printf("The number of terms must be positive\n");
flag = FALSE;
}
}
while(flag == FALSE);
}
double sinHyper(double *xptr, int *nptr) {
int i;
double sum;
double ti;
i = 0;
ti = 0;
for (i = 0; i < *nptr; i = i+1)// I'm getting a Warning: comparioson between pointer and integer
{
if (i == 0)
{
sum = xptr;
} else {
ti = 2*i+1;
ti = ti*2*i;
ti = (xptr*xptr)/ti;// I'm getting a error: invalid operands to binary * (have 'double*' and 'double*')
sum = ti*sum;
}
}
return (sum);
}
void main() {
int n;
double x;
double sinhx;
getinput(&x, &n);
sinhx = sinHyper(&x, &n);
printf("For an x of %.0f with %i terms the sinh(x) is %f", x, n, sinhx);
return 0;
}
You forgot to dereference your pointers in several places.
The fact that this line compiles
sum = xptr;
should not mislead you: C lets you convert a pointer to a number with only a warning, while in most cases this is an error. This line should be
sum = *xptr;
It does not let you multiply pointers, so the expression where you square your pointer is an error:
(xptr*xptr)
You should either dereference the pointer twice, i.e. write
((*xptr)*(*xptr))
or make a separate variable for the current value of *xptr and use it instead:
const double x = *xptr;
ti = (x*x)/ti;
Note: This exercise should be purely theoretical, because sinHyper does not change *xptr or *nptr. Therefore, you should pass them as values, not as pointers:
double sinHyper(const double x, const int n) {
...
}
...
sinhx = sinHyper(x, n);

[] precedence over * operator

Somewhere in my code I am doing something very bad. I'm getting undefined behavior in my extrema variable when it does run but most of the time it doesn't even run. Any help would be really great.
#include <stdio.h>
void get_extrema(int quadrant, int **extrema)
{
if (quadrant == 1)
{
*(extrema)[0] = 0;
*(extrema)[1] = 90;
}
else if (quadrant == 2)
{
*(extrema)[0] = -90;
*(extrema)[1] = 0;
}
}
void print(int* arr)
{
printf("%i",arr[0]);
printf(",");
printf("%i\n",arr[1]);
}
int main(void)
{
int *extrema = (int*)malloc(2*sizeof(int));
get_extrema(1,&extrema);
print(extrema);
get_extrema(2,&extrema);
print(extrema);
}
I also tried editing the extrema array using pointer arithmetic like the following:
**(extrema) = 0;
**(extrema+1) = 90;
But that did not work either. I really have no clue where this is going wrong and I could really use some help.
The reason you get undefined behavior is that the subscript operator [] takes precedence over the indirection operator *. The value of extrema is indexed as an array of pointers, which is incorrect, because there's only a single pointer there.
Since you are passing a pointer to a pointer, you need to put the asterisk inside parentheses:
if (quadrant == 1)
{
(*extrema)[0] = 0;
(*extrema)[1] = 90;
}
else if (quadrant == 2)
{
(*extrema)[0] = -90;
(*extrema)[1] = 0;
}
Demo on ideone.
a[b] is equal to *(a + b), but has higher precedence than the *. (And like a + b is b + a, so is a[b] equal to b[a]; and 5[a] equal to a[5]).
Thus:
*(extrema)[1] = 90;
// is equal to
*(*(extrema + 1)) = 99;
// When what you want to do is
*((*extrema) + 1) = 99;
// which is of course equal to
(*extrema)[1] = 99;
However, an even better question is: why are you using the double pointer, when it is not needed.
void get_extrema(int quadrant, int *extrema)
{
if (quadrant == 1)
{
extrema[0] = 0;
extrema[1] = 90;
}
else if (quadrant == 2)
{
extrema[0] = -90;
extrema[1] = 0;
}
}
void print(int *arr)
{
printf("%i,%i\n", arr[0], arr[1]);
}
int main(void)
{
int *extrema = (int *)malloc(2 * sizeof (int));
get_extrema(1, extrema);
print(extrema);
get_extrema(2, extrema);
print(extrema);
}

Multiplying a large number in C with a single digit number recursively?

I'm having trouble creating a recursive program that multiplies a large number with a single digit number. I understand they're are simpler methods to doing this, but I would like to do it recursively. I provided a SSCCE in the code. The problem is that the multiplication is not occurring correctly. For numbers with more than 1 digit, the program will only multiply the last digit, instead of multiplying the entire number.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *getmem(int len) {
char *ret;
ret = malloc(len);
if (NULL == ret) {
printf("memory allocation failed!\n");
exit (0);
}
else
return ret;
}
void printdigs(char *digs) {
if('0' == digs[0]) {
if (0 == digs[1]){
printf("%s", digs);
return;
}
else printdigs(&digs[1]);
}
else printf("%s",digs);
}
void multi_helper(char *a, char *r, char b, int len, int carry) {
int sum;
if (-1 == len) {
r[0] = (char) (carry + 48);
return;
}
sum = (a[len]-48) * (b-48) +carry;
r[len+1] = (char) ((sum % 10) + 48);
if (sum > 9)
carry = 1;
else carry = 0;
multi_helper(a,r,'0', len-1,carry);
}
char *multi(char *a, char b) {
char *res;
int l = strlen(a);
res = getmem(l + 2);
res[l+1] = 0;
multi_helper(a, res, b, l-1,0);
return res;
}
int main(int argc, char *argv[]) {
char *n1 = "1000";
printf("%s multiplied by 5 is ", n1);
printdigs(multi(n1,"5"));
printf("\n");
return 0;
}
Thanks for any help.
printdigs(multi(n1,"5"));
to
printdigs(multi(n1,'5'));
also need free return value of function multi
multi_helper(a,r,'0', len-1,carry);
to
multi_helper(a,r,b, len-1,carry);
I don't really know what you're looking for (this doesn't use strings to store numbers), but this uses recursion to add a number to itself a certain number of times (multiplication) using recursion for counting how many iterations are left.
int recursive_multiply(a, b) {
if (b==0) {
return 0;
}
char sign = 1;
if (b < 0) {
sign = -1;
b = -b;
}
return (a + recursive_multiply(a, b-1)) * sign;
}
edit: with the updates to the question, it's clear this solution doesn't directly answer the question Ace has, but it may answer questions other people may have when they search for something similar to the question, so I'm going to leave it. If anyone thinks this is wrong, comment and I'll consider removing it if warranted.

Resources