How to output a float product of int multipliers? - c

I am trying to calculate the exponent of a number. When I do everything as int I get the correct result, but the output must be float, when I try to convert with %f in printf() I get 0, when I use %d I get the correct result. I cannot change the main() portion of the program, I can only alter the *powerArgs() function. The program input is 3, 5.
Full disclosure, this is part of a school assignment. I am not asking for complete code. I would appreciate a more general answer showing me what I am forgetting, possibly what area I should study more to find the answer myself.
#include <stdio.h>
#include <stdlib.h>
int *powerArgs(int *pA, int *pB);
/* MAIN */
int main(int argc, char **argv)
{
if (argc != 3)
{
printf("?Invalid number of arguments\n");
system("pause");
exit(1);
}
int parmA = atoi(argv[1]);
int parmB = atoi(argv[2]);
int idx;
/* Part C: Raise parmA to the power of parmB. Return pointer to the result */
/* Reset the original values after we print the result */
printf("%d raised to the %d power is %0.1f\n", parmA, parmB, *powerArgs(&parmA, &parmB));
printf("\n");
system("pause");
exit(0);
}
int *powerArgs(int *pA, int *pB)
{
int idx, result = *pA;
for (idx = 1; idx < *pB; idx++)
{
result *= *pA;
}
return &result;
}

float and int convert automatically in C - you can assign either one to the other, and the only thing to watch out for is that if you assign too large a float to an int, then you get undefined behavior (or possibly an unspecified result, I forget. Either way it's not good).
So, your powerArgs function can just be:
float powerArgs(float a, int b) {
// do some stuff and return a value
}
Then you can call it as powerArgs(parmA, parmB), even though parmA is an int.
Edit: if you can't change the call parameters, you can do this instead
float powerArgs(int *a, int *b) {
float base = *a;
int exponent = *b;
...
}
If your professor has really set you code where the function is called as *powerArgs(int *a, int *b), then your professor is a menace. There is no earthly reason why an exponentiation function should return a pointer to a float. There's an ugly workaround you could use:
float *powerArgs(int *a, int *b) {
static float result;
...
result = /* the result of the calculation */;
return &result;
}
The problem with this is, all calls to powerArgs share the same object result. static stops it from ceasing to exist at the end of the call, but the sharing will introduce problems in the long run. It is not good practice to do this, but it might be the best solution to the problem you've been set.
C++ sneaky solution:
struct FloatWrapper {
float value;
float operator*() {
return value;
}
FloatWrapper(float f) : value(f) {}
};
FloatWrapper powerArgs(int *a, int *b) {
...
float result = /* whatever */;
...
return result;
}
This returns an object of class FloatWrapper, by value, and FloatWrapper overloads the * operator. This means that *powerArgs(...) evaluates to the float that the function should have returned by value in the first place, without needing a pointer to any special storage place.
By the way, you might want to check what your function does when parmB is 0.

First, your int *powerArgs(int *pA, int *pB) function returns the address of a local variable, which results in undefined behavior. Use the following instead:
int powerArgs(int *pA, int *pB)
{
int idx, result = *pA;
for (idx = 1; idx < *pB; idx++)
{
result *= *pA;
}
return result;
}
Next, if you want to convert to float, you shouldn't do that in the call to printf(), but rather convert the value to float before the call like so:
printf("%d raised to the %d power is %0.1f\n", parmA, parmB, (float)powerArgs(&parmA, &parmB));

When a function terminates, all its local variables cease to exist (and their addresses point to garbage). To please your teacher who came up with that very awkward interface, you have to find a way to keep an object alive after the function exists.
You have, at least, 3 options:
a) reuse one of the input parameters
b) use a global variable
c) use a static variable
option a)
int *powerArgs(int *pA, int *pB) {
/* calculate */
*pA = CALCULATED_VALUE;
return pA;
}
option b)
int global_power;
int *powerArgs(int *pA, int *pB) {
/* calculate */
global_power = CALCULATED_VALUE;
return &global_power;
}
option c)
int *powerArgs(int *pA, int *pB) {
static int static_power;
/* calculate */
static_power = CALCULATED_VALUE;
return &static_power;
}
Neither of these "solutions" is good; the least bad is option c)

Related

How do I make use of a custom library in C

I've written some code in regard to a uni assignment, but I keep stumbling across the problem where my custom function doesn't give any other output then zero.
Basically, I'm asking how to retrieve the result of the function to use in my code.
Here I will paste my code.
#include <stdio.h>
//math.h is included via the header file because the compiler liked it better.
int V;
int H;
int R;
int result;
#include "A1_header.h"
int main()
{
//small introduction
printf("Welcome to the volume test game\n");
printf("We will start with spheres. \n");
printf("Please input your sphere radius here:");
scanf("%d", &R);
CalcSphVolume(&V, &R);
printf("please input your result:");
scanf("%d", &result);
if(result == V){
printf("Congratulations, your answer is correct!\n");
}
else{
printf("Wrong answer, the correct result was %d \n", V);
}
return 0;
}
Below is my .h file which I use to define functions.
#ifndef Point
#define Point
#include <math.h>
//these are the functions for Sphere calculations
void CalcSphVolume(int V, int R) {
V = 1.33*3.14(R*R*R);
}
void CalcSphRadius(int V, int R) {
R = cbrt(V/4.1762);
return;
}
//these are the functions for the Cone calculations
void CalcConVolume(int V, int R, int H) {
V = 0.33*(3.14*(R*R))H;
return;
}
void CalcConHeight(int V, int R, int H) {
H = V/(0.33*(3.14*(R*R)));
}
void CalcConRadius(int V, int R, int H) {
R = sqrt(V/(0.33*3.14H));
}
//these are the functions for the Cilinder calculations
void CalcCilVolume(int V, int R, int H) {
V = 3.14*H*(R*R);
}
void CalcCilHeight(int V, int R, int H) {
H = V/(3.14(R*R));
}
void CalcCilRadius(int V, int R, int H) {
R = sqrt(V/(3.14*H));
}
#endif
I am not sure how you are running the code, because under ordinary circumstances this code will not compile.
There are a couple of things that are wrong in this code -
void CalcSphVolume(int V, int R) {
V = 1.333.14(RRR);
}
Firstly, I think there might be an error in your formatting, because RRR is not the correct way to compute, what you want is (R*R*R), similarly, 1.333.14 is not an accepted datatype. From context, since it is the volume of a sphere, this should be
void CalcSphVolume(int V, int R) {
V = 1.333 * 3.14 * (R*R*R);
}
Now that this is out of the way, there are some issues with this function (and similar to the other functions in your code.)
You are mixing types here - 1.333 is double, but V is int, so your actual answer will be implicitly converted to an integer, and you will lose precision. So V should be of the type double. So you get a more accurate answer.
void CalcSphVolume(double V, int R) {
V = 1.333 * 3.14 * (R*R*R);
}
Another thing to note here is that your functions parameters are by value and do not accept pointers. This means that any result that you get in this void function, will be lost unless you explicitly return it. Local variables only exist in the scope of the function. Since you are passing a pointer to the function and trying to populate the value outside the function, you should modify the function and function signature to
void CalcSphVolume(double* V, int* R) {
int r = *R // for clarity
*V = 1.333 * 3.14 * (r*r*r);
}
We have to dereference to get the "actual" value that is held by the pointer. You cannot apply arithmetic logic in this manner to raw pointers.
An alternative way to accomplish the same is
double CalcSphVolume(int R) {
double V = 1.333 * 3.14 * (R*R*R);
return V; // or simply return 1.333 * 3.14 * (R*R*R)
}
Here you are passing by value, but returning the value computer back to the caller. So you could use this function like so -
double Volume = CalcSphVolume(R);
This is much more clearer in this case, instead of having to pass pointers all over the place.
For your use case, using pointers is not necessary - consider using pointers when you have to mutate or pass large objects (Imagine a really huge array, so you don't want to create a copy it each time you use it in a function) which cannot be declared on the stack.
The issue is your function parameters are taking in an integer rather than a pointer to the memory address.
What you want to do instead is:
void CalcSphRadius(int *V, int *R)
{
*R = cbrt((*V)/4.1762);
return;
}
Now, the function is taking in a pointer to V and R and will read/write to their memory address.
As shown above, don't forget to dereference your pointers by using an asterisk '*' so that way you are writing to the value stored in those addresses, rather than just doing pointer arithmetic.
You can also retrieve values by using return types for functions.
int CalcSphRadius(int V)
{
return cbrt(V/4.1762);
}
And then use them to assign variables like so:
R = CalcSphRadius(V);
Your .h file name should be A1_header.h
Also, the code can be like this:
#ifndef Point
#define Point
#include <math.h>
#include <stdio.h>
//these are the functions for Sphere calculations
void CalcSphVolume(int V, int R);
void CalcSphRadius(int V, int R);
//these are the functions for the Cone calculations
void CalcConVolume(int V, int R, int H);
void CalcConHeight(int V, int R, int H);
void CalcConRadius(int V, int R, int H);
//these are the functions for the Cilinder calculations
void CalcCilVolume(int V, int R, int H);
void CalcCilHeight(int V, int R, int H);
void CalcCilRadius(int V, int R, int H);
#endif
#include "A1_header.h" in the wrong place.
It should be like
//directives
#include <stdio.h>
#include "A1_header.h"
int main(void)
{
variable declaration;
statements
}
Please try to learn the structure of the C program.
You need to declare the variables inside the main function.
When you call the function CalcSphVolume(V, R); why the address of the variable? It should be:
printf("Please input your sphere radius here:");
scanf("%d", &R);
CalcSphVolume(V, R);
Arrange all the functions properly
eg: CalcCilHeight function should be properly formatted with *
void CalcCilHeight(int V, int R, int H)
{
H = V/(3.14 * (R * R));
}

I am trying to pass 2 sums from a subroutine back to the main function in C

I am currently trying to take a sum from two different subroutine and pass it back to the main function, but every time I do this, it just comes up with a zero value and I am unsure why. I have tried putting my print statements in the main function and just doing calculations in the subroutines and that still didn't work, so I know that my variables aren't returning right and my sum is an actual number. How do I pass my variable sum back to my main function correctly?
Here is my code:
#include<stdio.h>
int X[2000];
int Y[2000];
int main()
{
FILE*fpdata1= NULL;
FILE*fpdata2 = NULL;
fpdata1=fopen("DataSet1.txt","r");
fpdata2=fopen("DataSet2.txt","r");
if(fpdata1==NULL || fpdata2 == NULL)
{
printf("file couldn't be found");
}
int i=0;
while(i<2000)
{
fscanf(fpdata1,"%d!",&X[i]);
fscanf(fpdata2,"%d!",&Y[i]);
// printf("This is X: %d\n",X[i]);
// printf("This is Y: %d\n",Y[i]);
i++;
}
fclose(fpdata1);
fclose(fpdata2);
avgX(X);
avgY(Y);
float sum;
float sumY;
float totalsum;
float totalavg;
totalsum= sum + sumY;
totalavg= totalsum/4000;
printf("Sum X: %f\n\n",sum);
printf("Total sum: %f\n\n",totalsum);
printf("The total average is: %0.3f\n\n",totalavg);
return 0;
}
int avgX(int X[])
{
int i=0;
float averageX;
float sum;
sum = 0;
while (i<2000)
{
sum += X[i];
i++;
}
averageX = sum/2000;
printf("Sum of X: %f\n\n",sum);
printf("The sum of Data Set 1 is: %0.3f\n\n",averageX);
return(sum);
}
int avgY(int Y[])
{
int i=0;
float averageY;
float sumY;
sumY = 0;
while (i<2000)
{
sumY += Y[i];
i++;
}
averageY = sumY/2000;
printf("Sum of Y: %f\n\n",sumY);
printf("The sum of Data Set 2 is: %0.3f\n\n",averageY);
return (sumY);
}
Firstly, it would appear you are expecting the lines
avgX(X);
avgY(Y);
to somehow update the sum and sumY variables in the main function. This is a fundamental misunderstanding of how memory is accessed.
Local variable declarations with the same identifier are not shared between functions. They can be accessed only from within the function in which they are declared (and only for the duration of the function call).
In this example, the apples variables in each of the functions have absolutely no correlation to one another. Expecting this program to print 15 is wrong. This program has undefined behavior because foo and bar read values from uninitialized variables.
void foo(void) {
int apples;
/* This is undefined behaviour,
* as apples was never initialized. Do not do this. */
apples += 5;
}
void bar(void) {
int apples;
/* This is undefined behaviour,
* as apples was never initialized. Do not do this. */
printf("%d\n", apples);
}
int main(void) {
int apples = 10;
foo();
bar();
return 0;
}
Instead of this, you'll want to utilize the arguments and return values of your functions. In this example, in main we pass the value of apples as an argument to foo, which adds 5 to this value and returns the result. We assign this return value, overwriting our previous value.
int foo(int val) {
return value + 5;
}
void bar(int val) {
printf("%d\n", val);
}
int main(void) {
int apples = 10;
apples = foo(apples);
bar(apples);
return 0;
}
Again note that the val parameters do not refer some "shared variable", they are local to both foo and bar individually.
As for the specifics of your program:
The functions avgX and avgY do the exact same thing, just with different identifiers.
It would be better to write a more generic summation function with an additional length parameter so that you are not hard-coding data sizes everywhere.
int sum_ints(int *values, size_t length) {
int result = 0;
for (size_t i = 0; i < length; i++)
result += values[i];
return result;
}
You can then easily write averaging logic utilizing this function.
You do check that your file pointers are not invalid, which is good, but you don't halt the program or otherwise remedy the issue.
It is potentially naive to assume a file will always contain exactly 2000 entries. You can use the return value of fscanf, which is the number of conversions that took place, to test if you've failed to read data. Its also used to signify errors.
Though the fact that global variables are zeroed-out saves you from potentially operating on unpopulated data (in the event the files contain less than 2000 entries), it would be best to avoid global variables when there is an alternative option.
It might be better to separate the reading of files to its own function, so that failures can be handled per-file, and reading limits can be untethered.
int main(void) or int main(int argc, char **argv) are the correct, valid signatures for main.
With all that said, here is a substantially refactored version of your code. Note that an implicit conversion takes place when we assign the integer return value of sum_ints to our floating point variables.
#include <stdio.h>
#include <stdlib.h>
#define DATA_SIZE 2000
int sum_ints(int *values, size_t length) {
int result = 0;
for (size_t i = 0; i < length; i++)
result += values[i];
return result;
}
size_t read_int_file(int *dest, size_t sz, const char *fname) {
FILE *file;
size_t i;
if ((file = fopen(fname, "r")) == NULL) {
fprintf(stderr, "Critical: Failed to open file: %s\n", fname);
exit(EXIT_FAILURE);
}
for (i = 0; i < sz; i++)
if (fscanf(file, "%d!", dest + i) != 1)
break;
fclose(file);
return i;
}
int main(void) {
int data_x[DATA_SIZE] = { 0 },
data_y[DATA_SIZE] = { 0 };
size_t data_x_len = read_int_file(data_x, DATA_SIZE, "DataSet1.txt");
size_t data_y_len = read_int_file(data_y, DATA_SIZE, "DataSet2.txt");
float sum_x = sum_ints(data_x, data_x_len),
sum_y = sum_ints(data_y, data_y_len);
float total_sum = sum_x + sum_y;
float total_average = total_sum / (data_x_len + data_y_len);
printf("Sums: [X = %.2f] [Y = %.2f] [Total = %.2f]\n"
"The total average is: %0.3f\n",
sum_x, sum_y, total_sum,
total_average);
}

Ex. 2.1 K&R 2nd edition: How can I calculate the variables?

I am a beginner in programming. I referred to power function in chapter 1 and modified it to be power_sum function. My calculation is to insert value of bits in "show_val()" to show range of each variable. The problem is in the main when I want to insert a value into show_val. Please guide me how to solve this. Thank you.
#include <stdio.h>
int power_sum(int base, int n);
void show_val(int power);
int main() {
unsigned char vc = show_val(8);
/* I try to show range of unsigned char here, but because show_val
is a void function, so it becomes error.*/
}
/* power_sum: raise base to n-th power and sum up; n => 0 */
int power_sum(int base, int n) {
int i, p, sum;
p = 1;
sum = 0;
for (i = 1; i <= n; ++i) {
p = p * base;
sum = sum + p;
}
sum = sum - 2;
return sum;
}
/* show_val: to show value of each variable */
void show_val(int pw) {
int n;
int i;
n = power_sum(2, pw);
for (i = 0; i < 10; ++i) /* to display increments of a value ten times */ {
printf("%d\n", ++n);
}
}
You are trying to assign void function void show_val(int pw) (a function that returns nothing) to unsigned char vc variable. If you want to return value from show_val function change: int show_val(int pw) and return something.
Otherwise, if you don't want to return anything, you can just call function in main:
int main()
{
show_val(8);
}
unsigned char vc = show_val(8);
Let us break the above piece of code into LHS and RHS.
LHS :
Its a variable expecting a character to be inputed.
Now what is being done in RHS
RHS:
You have given show_val(8)
Which is a mistake
Why?
Because if you see you show_val declaration:
void show_val(int)
You are returning a void i.e nothing.
And trying to equate with char on LHS.
So, the compiler will definitely throw an error.
There are more changes to be made,
1st edit this part correctly in the question if you are clear and then we can look upon the other changes.

Regarding null pointers and an assignment C

I'm stuck with my assignment and i can't seem to get it working, your help would be appreciated!:)
Task was to list prime numbers between a min max passed from program arguments (swap min&max if in wrong order). I was told to protect against null pointers and that there is some problem with not checking argv(?).(I won't include the prime part since that works )
Main.c
void proc(int argc, char *argv[])
{
int min,max;
min=atoi(argv[1]);
max=atoi(argv[2]);
if(min>max)
{
swap(min, max);
printf("Min&max swapped!");
}
if(argc!=3)
{
printf("Please set 2 numbers as interval");
exit(EXIT_FAILURE);
}
prime(min,max);
return EXIT_SUCCESS;
}
int main(int min,int max)
{
proc(min, max);
}
Swap.c
void swap(int *a,int *b)
{
int c = *a;
*a = *b;
*b = c;
}
Check argcvalue before accessing argv that way you eliminate the chance of accessing out of bound memory.
Also swap should get address of min and max so that the change can be reflected.
swap(&min,&max);
void swap(int *x,int *y)
{
int t=*x;
*x=*y;
*y=t;
}
How you should go about?
if( argc != 3)
{
printf("[%s]:[progname num1 num2]\n");
return 0;
}
...
...
min = atoi(argv[1]);
..
max = ..
if(max<min)
swap(&max,&min);
int min,max;
...
swap(min, max);
Okay, so you pass the swap function two ints.
void swap(int *a,int *b)
But swap expects two int*s. That can't be good.
Also:
int* c = *a;
Hmm, a is of type int*, so *a is of type int. So why are you assigning it to a variable of type int*? That can't be good either.

Using variables

I have a problem with this simple program because it doesnt give me the true outcome. I just want to sum two arguments in the first function and then use the outcome in the second one. It will be nice to have overall outcome in the main function. Also I would like to ask the same question with arrays.
#include <stdio.h>
#include <stdlib.h>
int sum()
{
int a=2;
int b=3;
int s=a+b;
printf("sum=%d\n",s);
return s;
}
int sum2(int s)
{
int c=5;
int d=c+s;
}
int main(int s,int d)
{
sum();
printf("sum=%d\n",s);
printf("sum2=%d\n",d);
getchar();
return 0;
}
There are many problems with this code:
int main(int s, int d) won't do what you think. Command-line arguments to your program come in string format. So you would need to use int main(int argc, char *argv[]).
The variables s and d in main() are completely independent to the variables in sum() and sum2(). So changing their values in those functions will not affect the original variables.
You're not even calling the second function!
You can do things like this:
int sum(int a, int b)
{
return a+b;
}
int sum2(int c)
{
return c+5;
}
int main(void)
{
int x = 2;
int y = 3;
int z = sum(x,y);
int w = sum2(z);
printf("z = %d\n", z);
printf("w = %d\n", w);
}
First of all, s is a local variable inside sum( ). Hence it cannot be available outside the function.
int sum() {
// ..
int s = a+b; // local variable, hence local scope
// ..
}
Also, secondly, int main(int s,int d) won't work since in command line arguments come in String format. So can't use a int there
I won't tell you the answer (lol but others have) but I'll give you these clues to figuring it out.
Ask your self which functions are returning data and which ones aren't.
Clue: the function needs a return to return some data.
Then ask yourself which functions' returns are actually being used.
Clue: to collect the data returned from a function you need to assign the result to a variable like so
int i;
i = somefunct();
You can't access the value of variable 's' outside the function sum() since it is out of scope. You'll have to return the value to your main() function. Also your main function parameters are incorrect. You need something more like this:
#include <stdio.h>
#include <stdlib.h>
int sum(int a, int b)
{
int s=a+b;
printf("sum=%d\n",s);
return s;
}
int sum2(int c, int sum)
{
return c+sum;
}
int main(int argc, char *argv[])
{
int val1 = sum(2, 3);
printf("sum=%d\n",val1);
int val2 = sum2(5, val1);
printf("sum2=%d\n", val2);
getchar();
return 0;
}

Resources