Related
I have the following code in c
#include <stdio.h>
int main(void)
{
int a, b, c, sum;
double d, p;
sum = a + b + c;
printf("请输入三个整数:");
scanf("%d %d %d", &a, &b, &c);
d = sum / 3;
printf("3个整数的平均值是:d=%.2f", d);
p = a / sum * 100;
printf(",第一个数占和的比例是:p=%4.2f%%", p);
}
It is about entering three integers from the keyboard, average them, and calculate the ratio of the first number to the sum of the three numbers. The output result retains 2 decimal places .
I cannot find where is wrong.
The two main issues are:
You calculate sum with uninitialized values for a, b and c. Move that calculation to after a successful scanf() to ensure those variables are set.
You probably want to do the calculations of d and p with double, rather than integer, precision. I make use of automatic type conversion via fractional constants. The other two options are to change the type of sum from an int to a double, or explicitly use a type cast (see answer by #FeihuLiu).
Minor issues:
Original code was formatted poorly (since fixed by one of our friends :-).
Optional for main() but it's a good idea to return an integer as your declaration said you would.
(not fixed) If you don't use p or d for anything else, consider just eliminating them in favor of doing the calculation call to printf()
It's generally a good idea to reduce the scope of variables so I moved those definitions to just before they are used.
#include <stdio.h>
int main(void) {
printf("请输入三个整数:");
int a, b, c;
if (scanf("%d %d %d", &a, &b, &c) != 3) {
// TBD: translate error message
printf("scanf failed\n");
return 1;
}
int sum = a + b + c;
double d = sum / 3.0;
printf("3个整数的平均值是:d=%.2f", );
double p = 100.0 * a / sum;
printf(",第一个数占和的比例是:p=%4.2f%%", p);
return 0;
}
Besides the sum problem, integer division will result in integer. You can use the following code:
#include <stdio.h>
int main(void) {
int a, b, c, sum;
double d, p;
printf("请输入三个整数:");
scanf("%d %d %d", &a, &b, &c);
sum = a + b + c;
d = (double) sum / 3;
printf("3个整数的平均值是:d=%.2f", d);
p = (double) a / sum * 100;
printf(",第一个数占和的比例是:p=%4.2f%%", p);
}
I need to initialize an array of pointers to pointers to four variables a, b, c and d in this way:
float a = 2.8f, b = 3.7f, c = 4.6f, d = 5.5f;
float *pts[] = { &a, &b, &c, &d };
float **ptpts[4];
void main() {
ptpts[0] = &pts[0];
ptpts[1] = &pts[1];
ptpts[2] = &pts[2];
ptpts[3] = &pts[3];
int i;
for (i = 0; i < 4; i++) {
printf("ptpts[%d] = %f\n", i, **ptpts[i]);
}
}
Isn't there a simpler way to initialize the array ptpts directly at declaration using directly the array pts in order to get rid of the assignment of each element in ptpts one by one. Something like that (but doesn't work):
float *pts[] = { &a, &b, &c, &d };
float **ptpts = &pts; // => initialization from incompatible pointer type
In other words, isn't there a way to get the corresponding array of references from an array of pointers ?
Edit:
Following some comments, I give here a piece of background to explain how I came to that question. This may help to propose the solution or give idea for a better architecture.
I have the following interface (interface.h) for the program I'm developing. Depending on a flag PTTYPE defined at compilation time, the interface will be a set of variables or a set of pointers depending on the environment where the program is deployed. The program must be compliant with both kind of interface type (PTTYPE=1 or PTTYPE=0).
// interface.h
#if PTTYPE
float *pta, *ptb, *ptc, *ptd;
#define a (*pta)
#define b (*ptb)
#define c (*ptc)
#define d (*ptd)
#else
float a, b, c, d;
#endif
I'm not the owner of this interface file and can't modify it. I must just include this file in my program and want to have a simple and unique way to reach the values. That's why I thought about using an array of pointers to pointers and would have something like that:
#include "interface.h"
#if PTTYPE
float **ptpts[]={ &pta, &ptb, &ptc, &ptd };
#else
float *pts[]={ &a, &b, &c, &d };
float **ptpts = &pts; // => initialization from incompatible pointer
#end
void main() {
a=2.8f;
b=3.7f;
c=4.6f;
d=5.5f;
int i;
for (i = 0; i < 4; i++) {
printf("ptpts[%d] = %f\n", i, **ptpts[i]);
}
}
float ..... = &pts;
Yes you can but you need another pointer type (pointer to array):
float a = 2.8f, b = 3.7f, c = 4.6f, d = 5.5f;
float *pts[] = { &a, &b, &c, &d };
float *(*ptpts)[4] = &pts;
for (size_t i = 0; i < 4; i++)
{
printf("*ptpts[0][%zu] = %f\n", i, *ptpts[0][i]);
}
or
for (size_t i = 0; i < 4; i++) {
printf("ptpts[%zu] = %f\n", i, *(*ptpts[i]));
}
Yes you can even without any variables
int main(void)
{
float **pptrs[] = {(float **){&(float *){&(float){1.0f}}},
(float **){&(float *){&(float){2.0f}}},
(float **){&(float *){&(float){3.0f}}},
(float **){&(float *){&(float){4.0f}}}, };
}
The array can be defined and initialized inline this way:
float **ptpts[] = { &pts[0], &pts[1], &pts[2], &pts[3]};
If the array is global and the initization local in main, a loop or a series of assignments is required.
It's okay to use whitespace to aid readability.
int main() {
float a=2.8f, b=3.7f, c=4.6f, d=5.5f;
float *pts[]={ &a, &b, &c, &d };
// What you want?
float **ptpts[] = { &pts[0], &pts[1], &pts[2], &pts[3] };
for( int i = 0; i < 4; i++ )
printf("ptpts[%d] = %f\n", i, **ptpts[i]);
return 0;
}
Output:
ptpts[0] = 2.800000
ptpts[1] = 3.700000
ptpts[2] = 4.600000
ptpts[3] = 5.500000
So, thanks to the help of 0___________, I was able to find a solution which answers to my initial problem (i.e. initialize the array of pointers to pointer with either pointers or variable). In this way, I'm not using any more the intermediate array of pointer pts but create directly the array of pointers to pointer using the compound-literals .
Here is the initialization part of the array ptpts:
#if ITYPE
#define ADAPT(name) pt##name
#else
#define ADAPT(name) (float *){&name}
#endif
float **ptpts[] = { &ADAPT(a),
&ADAPT(b),
&ADAPT(c),
&ADAPT(d) };
I am trying to write a code for a network of FitzHugh NAgumo neurons in C, using RK4 integrator. As that wasn't working, I decided to try something simpler, a simple pendulum system. I am using separate functions - one to return the differential array, one for the integrator, and a few functions to add and multiply numbers to each element of an array.
Here is the code that returns all '0' values:
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>
int N = 2;
float h = 0.001;
struct t_y_couple{
float t;
float* y;
};
float* array_add(int len_array_in,float array_in[2], float array_add[2]);
struct t_y_couple integrator_rk4(float dt,float t, float* p1);
float* oscnetwork_opt(float t, float *y);
float* array_mul(int len_array_in,float array_in[2], float num);
int main(void){
/* initializations*/
struct t_y_couple t_y;
int i,iter;
// time span for which to run simulation
int tspan = 20;
// total number of time iterations = tspan*step_size
int tot_time = (int) ceil(tspan/h);
// Time array
float T[tot_time];
// pointer definitions
float *p, *q;
// vector to hold values for each differential variable for all time iterations
float Y[tot_time][2];
// 2*N+sum_adj = total number of coupled differential equations to solve
// initial conditions vector for time = 0
Y[0][0] = 0;
Y[0][1] = 0.1;
// set the time array
T[0] = 0;
// This loop calls the RK4 code
for (i=0;i<tot_time-1;i++){
p = &Y[i][0]; // current time
q = &Y[i+1][0]; // next time step
// printf("\n\n");
// for (j=0;j<2*N+sum_adj;j++)
// printf("value passed in from main function: %f ,%d ",*(p+j),j);
// printf("\n");
// call the RK4 integrator with current time value, and current
// values of voltage
t_y = integrator_rk4(h,T[i],p);
// Return the time output of integrator into the next iteration of time
T[i+1] = t_y.t;
// copy the output of the integrator into the next iteration of voltage
q = memcpy(q, t_y.y, (2) * sizeof(float));
// q = memcpy(q, p, (2*N+sum_adj) * sizeof(float) );
printf("%f ",T[i+1]);
for (iter = 0;iter<N;iter++)
printf("%f ",*(p+iter));
printf("\n");
}
return 0;
}
struct t_y_couple integrator_rk4(float dt,float t, float y[2])
{
// initialize all the pointers
float *y1,*y2,*y3, *yout;
float tout,dt_half;
float *k1,*k2,*k3,*k4;
// initialize iterator
int i;
// printf("\n");
struct t_y_couple ty1;
tout = t+dt;
dt_half = 0.5*dt;
float addition[2];
// return the differential array into k1
k1 = oscnetwork_opt(t,y);
// multiply the array k1 by dt_half
k1 = array_mul(2,k1,dt_half);
// add k1 to each element of the array y passed in
y1 = array_add(2,y,k1);
// for (i=0;i<2*N+sum_adj;i++)
// printf("k1: %f y: %f y1: %f\n",*(k1+i), *(y+i), *(y1+i));
// do the same thing 3 times
k2 = oscnetwork_opt(t+dt_half,y1);
k2 = array_mul(2,k2,dt_half);
y2 = array_add(2,y,k2);
// for (i=0;i<2*N+sum_adj;i++)
// printf("k2: %f y: %f y2: %f\n",*(k2+i), *(y+i), *(y2+i));
k3 = oscnetwork_opt(t+dt_half,y2);
k3 = array_mul(2,k3,dt);
y3 = array_add(2,y,k3);
// for (i=0;i<2*N+sum_adj;i++)
// printf("k3: %f y: %f y3: %f\n",*(k3+i), *(y+i), *(y3+i));
k4 = oscnetwork_opt(tout,y3);
k4 = array_mul(2,k4,dt);
yout = array_add(2,y,k4);
// for (i=0;i<2*N+sum_adj;i++)
// printf("k4: %f y: %f y4: %f\n",*(k4+i), *(y+i), *(yout+i));
// Make the final additions with k1,k2,k3 and k4 according to the RK4 code
for (i=0;i<2;i++){
addition[i] = ((*(k1+i)) + (*(k2+i))*2 + (*(k3+i))*2 + (*(k4+i))) *dt/6;
// printf("final result : addition %f ", addition[i]);
}
// printf("\n");
// add this to the original array
yout = array_add(2,y,addition);
// for (i=0;i<2*N+sum_adj;i++)
// printf("yout: %f ",*(yout+i));
// printf("\n");
// return a struct with the current time and the updated voltage array
ty1.t = tout;
ty1.y = yout;
return ty1;
}
// function to add two arrays together, element by element
float* array_add(int len_array_in,float array_in[2], float array_sum[2]){
int i;
static float *array_out_add= NULL;
if (array_out_add != 0) {
array_out_add = (float*) realloc(array_out_add, sizeof(float) * (2));
} else {
array_out_add = (float*) malloc(sizeof(float) * (2));
}
for (i=0;i<len_array_in;i++){
array_out_add[i] = array_in[i]+array_sum[i];
// printf("before adding: %f, add amount: %f , after adding: %f, iteration: %d\n ", array_in[i], array_sum[i], array_out[i],i);
}
return array_out_add;
// return 0;
}
// function to multiply each element of the array by some number
float* array_mul(int len_array_in,float array_in[2], float num){
int i;
static float *array_out_mul= NULL;
if (array_out_mul != 0) {
array_out_mul = (float*) realloc(array_out_mul, sizeof(float) * (2));
} else {
array_out_mul = (float*) malloc(sizeof(float) * (2));
}
for (i=0;i<len_array_in;i++){
array_out_mul[i] =array_in[i]*num;
}
return array_out_mul;
// return 0;
}
// function to return the vector with coupled differential variables for each time iteration
float* oscnetwork_opt(float t, float *y){
// define and allocate memory for the differential vector
static float* dydt = NULL;
if (dydt != 0) {
dydt = (float*) realloc(dydt, sizeof(float) * (2));
} else {
dydt = (float*) malloc(sizeof(float) * (2));
}
dydt[0] = y[1];
dydt[1] = -(0.1*0.1)*sin(y[0]);
return dydt;
}
Here is a code that does return a sine wave for the omega variable on my laptop but not on my PC (both 64 bit, laptop running Ubuntu 14.04 and PC running Debian 8).
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>
int N = 2;
float h = 0.0001;
struct t_y_couple{
float t;
float* y;
};
float* array_add(int len_array_in,float array_in[2], float array_add[2]);
struct t_y_couple integrator_rk4(float dt,float t, float* p1);
float* oscnetwork_opt(float t, float *y);
float* array_mul(int len_array_in,float array_in[2], float num);
int main(void){
/* initializations*/
struct t_y_couple t_y;
int i,iter,j;
// time span for which to run simulation
int tspan = 20;
// total number of time iterations = tspan*step_size
int tot_time = (int) ceil(tspan/h);
// Time array
float T[tot_time];
// pointer definitions
float *p, *q;
// vector to hold values for each differential variable for all time iterations
float Y[tot_time][2];
// N = total number of coupled differential equations to solve
// initial conditions vector for time = 0
Y[0][0] = 3.14;
Y[0][1] = 0;
// set the time array
T[0] = 0;
// This loop calls the RK4 code
for (i=0;i<tot_time-1;i++){
p = &Y[i][0]; // current time
// q = &Y[i+1][0]; // next time step
// printf("\n\n");
// for (j=0;j<N;j++)
// printf("value passed in from main function: %f ,%d ",*(p+j),j);
// printf("\n");
// call the RK4 integrator with current time value, and current
// values of voltage
t_y = integrator_rk4(h,T[i],p);
// Return the time output of integrator into the next iteration of time
T[i+1] = t_y.t;
// copy the output of the integrator into the next iteration of voltage
// q = memcpy(q, t_y.y, (2) * sizeof(float));
// q = memcpy(q, p, (N) * sizeof(float) );
printf("%f ",T[i+1]);
for (iter = 0;iter<N;iter++){
Y[i+1][iter] = t_y.y[iter];
printf("%f ",Y[i+1][iter]);
}
printf("\n");
}
return 0;
}
struct t_y_couple integrator_rk4(float dt,float t, float y[2])
{
// initialize all the pointers
float y1[2],y2[2],y3[2], yout[2];
float tout,dt_half;
float k1[2],k2[2],k3[2],k4[2];
// initialize iterator
int i;
// for(i=0;i<N;i++)
// printf("into integrator %f ",y[i]);
// printf("\n");
struct t_y_couple ty1;
tout = t+dt;
dt_half = 0.5*dt;
float addition[2];
// return the differential array into k1
k1[0] = y[1];
k1[1] = -(1)*sin(y[0]);
// multiply the array k1 by dt_half
for (i=0;i<N;i++){
y1[i] = y[i] + k1[i]*dt_half;
// printf("k1: %f y: %f y1: %f\n",*(k1+i), *(y+i), *(y1+i));
}
// do the same thing 3 times
k2[0] = y1[1];
k2[1] = -(1)*sin(y1[0]);
for (i=0;i<N;i++){
y2[i] = y[i] + k2[i]*dt_half;
// printf("k2: %f y: %f y2: %f\n",*(k2+i), *(y+i), *(y2+i));
}
k3[0] = y2[1];
k3[1] = -(1)*sin(y2[0]);
for (i=0;i<N;i++){
y3[i] = y[i] + k3[i]*dt;
// printf("k3: %f y: %f y3: %f\n",*(k3+i), *(y+i), *(y3+i));
}
k4[0] = y3[1];
k4[1] = -(1)*sin(y3[0]);
// Make the final additions with k1,k2,k3 and k4 according to the RK4 code
for (i=0;i<N;i++){
addition[i] = (( k1[i]*dt) + (k2[i])*2 + (k3[i])*2 + (k4[i]))/6;
yout[i] = y[i] + addition[i];
// printf("y[%d]: %f + addition[%d]: %f = yout[%d] :%f ",i,y[i],i, addition[i], i, yout[i]);
// printf("final result : addition %f ", addition[i]);
}
// add this to the original array
// printf("\n");
// return a struct with the current time and the updated voltage array
ty1.t = tout;
ty1.y = yout;
return ty1;
}
I suspect that the problem lies mostly in the way I am passing the arrays through the functions - as it works when I do not have a separate function to run the integrator. Would appreciate some help on this.
Your code has undefined behavior. At its core, it's because you use static pointers in your multiplication and addition functions. Allow me to condense it into the problematic part:
k2 = array_mul(2,k2,dt_half);
k3 = array_mul(2,k3,dt); // This either makes k2 point to freed memory, or overwrites the values in the location it points to.
addition[i] = ((*(k1+i)) + (*(k2+i))*2 + (*(k3+i))*2 + (*(k4+i))) *dt/6; // This uses all four pointers as though they must point to distinct memory locations.
First get rid of that static. Then you can do one of two things:
Simply allocate memory inside the functions and return a pointer to it. It will be the calling codes responsibility to free it at the end, like this:
free(k1);
free(k2);
// etc
Pass a pointer into a your functions for them to populate, leaving the memory management entirely to the calling code:
// function to multiply each element of the array by some number
void array_mul(int len_array_in,float *array_in, float num, float *array_out){
int i;
for (i=0;i<len_array_in;i++){
array_out[i] =array_in[i]*num;
}
}
I've been working through this problem, and I believe I have an error in where my pointers within my struct are pointing. However, I can't seem to figure out where I'm going wrong.
My code is meant to take in 2 complex numbers, then multiply and divide them, and then spit out both answers.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
struct complex_t
{
double real; // real part
double imag; // imaginary part
} complex_t;
// Multiplication Function //
void *multiply()
{
struct complex_t a, b, c;
c.real == ((a.real * b.real) - (a.imag * b.imag));
c.imag == ((a.imag * b.real) + (a.real * b.imag));
if ( c.imag >= 0 )
printf("Multiplication = %d + %di\n", c.real, c.imag); // Postive Imaginary case
else
printf("Multiplication = %d %di\n", c.real, c.imag); // Negative Imaginary case
}
// Division Function //
void *divide()
{
int numer1, numer2, denom;
struct complex_t a, b, c;
if ( b.real == 0 || b.imag == 0 ) // Case to Avoid Dividing by 0
printf("Division by 0 + 0i is not allowed.");
else
{
numer1 = ((a.real * b.real) + (a.imag * b.imag));
numer2 = ((a.imag * b.real) - (a.real * b.imag));
denom = ((b.real * b.real) + (b.imag * b.imag));
c.real == (numer1/denom);
c.imag == (numer2/denom);
if (numer2/denom >= 0)
printf("Division = %d + %di \n", c.real, c.imag); // Postive Imaginary case
else
printf("Division = %d %di \n", c.real, c.imag); // Negative imaginary case
}
}
// Main - to execute the two functions //
int main() {
struct complex_t a, b, c;
printf("Enter a and b where a + ib, for the first complex number.");
printf("\na = ");
scanf("%d", &a.real);
printf("b = ");
scanf("%d", &a.imag);
printf("Enter c and d where c + id, for the second complex number.");
printf("\nc = ");
scanf("%d", &b.real);
printf("d = ");
scanf("%d", &b.imag);
multiply();
divide();
return 0;
}
This is an example of what this program is producing:
Multiplication = 69144 -4196352i
Division = -13339222 0i
Any tips as to where I can start figuring this error out would be great.
C is an exact language. There is no such thing as syntax that is close enough. This is a great strength in C, but it is one hurdle beginning programmers have to come to terms with and understand before any real learning can take place. That includes understanding what each part of each line does, including the format strings. If you don't fully understand what each part of each line is doing -- look it up. Read the man pages, search for further information, until you do. It will save you a ton of time in the long run.
One of the things you can do that will, above all, help you find the problems in your code is to compile with Warnings enabled. That means including at least -Wall -Wextra in your compile string. For example, in your code, the screen was littered with warnings, including code with no apparent function and expected double but have int. Those things are telling you, you can try and run your code -- but DO NOT expect it to work right. You have to fix those, before you can have reasonable confidence that you will get more than garbage (or a crash) out of your code.
Another primary bit of learning that must take place is Always initialize your variables (to zero if nothing else). Attempting to access an uninitialized variable is Undefined Behavior. (it's anybody's guess what will happen.)
That being said. You had part of the code right. Your issues basically took slowing down, reading what the compiler was telling you was wrong, fixing it, and trying again. That's the key to C, slow down and get it right.
Enough blather -- are you going to help or not? Of course. Read through the following. Understand why the changes were necessary, and you will be able to consider it a good bit of learning for the day. However, the fixes in the code below, are not near as important as the guidance above for approaching C programming. (give a man a fish....):
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
typedef struct {
double real; // real part
double imag; // imaginary part
} complex_t;
// Multiplication Function //
void multiply (complex_t *a, complex_t *b, complex_t *c) {
/* struct complex_t a, b, c; */
c->real = ((a->real * b->real) - (a->imag * b->imag));
c->imag = ((a->imag * b->real) + (a->real * b->imag));
if (c->imag >= 0)
printf ("\nMultiplication = %f + %fi\n", c->real, c->imag); // Postive Imaginary case
else
printf ("\nMultiplication = %f %fi\n", c->real, c->imag); // Negative Imaginary case
}
// Division Function //
void divide (complex_t *a, complex_t *b, complex_t *c) {
int numer1, numer2, denom;
/* struct complex_t a, b, c; */
if (b->real == 0 || b->imag == 0) // Case to Avoid Dividing by 0
printf ("Division by 0 + 0i is not allowed.");
else {
numer1 = ((a->real * b->real) + (a->imag * b->imag));
numer2 = ((a->imag * b->real) - (a->real * b->imag));
denom = ((b->real * b->real) + (b->imag * b->imag));
c->real = (numer1 / denom);
c->imag = (numer2 / denom);
if (numer2 / denom >= 0)
printf ("\nDivision = %f + %fi \n", c->real, c->imag); // Postive Imaginary case
else
printf ("\nDivision = %f %fi \n", c->real, c->imag); // Negative imaginary case
}
}
// Main - to execute the two functions //
int main () {
complex_t a = { 0, 0 }, b = { 0, 0 }, c = { 0, 0 };
printf ("\nEnter a and b where a + ib, for the first complex number.\n\n");
printf (" a (a.real) = ");
scanf ("%lf", &a.real);
printf (" b (a.imag) = ");
scanf ("%lf", &a.imag);
printf ("\nEnter c and d where c + id, for the second complex number.\n\n");
printf (" c (b.real) = ");
scanf ("%lf", &b.real);
printf (" d (b.imag) = ");
scanf ("%lf", &b.imag);
multiply (&a, &b, &c);
divide (&a, &b, &c);
printf ("\n");
return 0;
}
output:
$ ./bin/divmult
Enter a and b where a + ib, for the first complex number.
a (a.real) = 10
b (a.imag) = 3
Enter c and d where c + id, for the second complex number.
c (b.real) = 5
d (b.imag) = 5
Multiplication = 35.000000 + 65.000000i
Division = 1.000000 + 0.000000i
void *multiply()
The values of struct variables a and b are not initialized within this function you should be passing the scanned values in main() to this function as well as divide()
There is no reason here I see why you are returning void *. Pass parameters by reference or by value.
Here's my code, it is supposed to calculate the standard deviation of the randomly generated array that fillArray populates. stdDev is supposed to calculate the standard deviation. otherStats is supposed to find the largest and smallest value in the array. So far, the only thing that is being generated are 0s for the deviation, smallest, and largest. Here's the code:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
float fillArray (float array[7][5]);
float printArray (float array[7][5], float deviation, float largest, float smallest);
float stdDev (float array[7][5], float deviation, float average);
float otherStats (float array[7][5], float largest, float smallest);
int main ()
{
float deviation, average, largest, smallest;
float array[7][5];
fillArray (array);
stdDev (array, deviation, average);
otherStats (array, largest, smallest);
printArray (array, deviation, largest, smallest);
}
float fillArray (float array[7][5])
{
int row, column;
for (row = 0; row < 7; row++)
{
for (column = 0; column < 5; column++)
{
array[row][column] = (float) rand () / (float) RAND_MAX;
}
}
return array[7][5];
}
float stdDev (float array[7][5], float deviation, float average)
{
float number1, number2;
array[7][5] = fillArray(array);
int ROw, Col;
for (ROw = 0; ROw < 7; ROw++)
{
for (Col = 0; Col < 5; Col++)
{
number1 = array[ROw][Col] + number1;
average = number1 / 35;
}
}
for (ROw = 0; ROw < 7; ROw++)
{
for (Col = 0; Col < 5; Col++)
{
number2 = average - array[ROw][Col];
deviation = sqrt (number2 / 35);
}
}
return deviation;
}
float otherStats (float array[7][5], float largest, float smallest)
{
array[7][5] = fillArray(array);
float num1, num2; //Check which ones largest or smallest.
int ROW, COLUMN;
for (ROW = 0; ROW < 7; ROW++)
{
for (COLUMN = 0; COLUMN < 5; COLUMN++)
{
num1 = array[ROW][COLUMN];
num2 = array[1][1];
largest = num2;
smallest = num1;
if (num1 > num2)
{
largest = num1;
}
else
{
smallest = num1;
}
}
}
return largest, smallest;
}
float printArray (float array[7][5], float deviation, float largest, float
smallest)
{
int Row, Column;
printf("Column #: ");
for (Column = 0; Column < 5; Column++)
{
printf ("%d ", Column);
}
printf("\nRow #|________________________________\n");
for (Row = 0; Row < 7; Row++)
{
printf("%d | ", Row);
for (Column = 0; Column < 5; Column++)
{
printf ("%4.2f ", array[Row][Column]);
}
printf ("\n");
}
printf("The standard deviation is %f, the largest is %f, the smallest is %f.\n",
deviation, largest, smallest);
}
Any help to figure out my error would be super appreciate. It compiles fine, it's just that my logic or something is messed up.
Thanks in advance.
This is the output:
Column #: 0 1 2 3 4
Row #|________________________________
0 | 0.53 0.04 0.44 0.93 0.93
1 | 0.72 0.28 0.74 0.64 0.35
2 | 0.69 0.17 0.44 0.88 0.83
3 | 0.33 0.23 0.89 0.35 0.69
4 | 0.96 0.59 0.66 0.86 0.44
5 | 0.92 0.40 0.81 0.68 0.91
6 | 0.48 0.22 0.95 0.92 0.15
The standard deviation is -0.000000, the largest is 0.000000, the smallest is 0.000000.
This is not the answer to your coding woes, but it is an example of what you're doing wrong. I certainly won't expect this to garner much attention (besides maybe a few down votes and some sharp criticisms).
C is a pass-by-value language. Though not easily grasped by most that experience it, this includes everything, (arrays not withstanding, but even those are if you apply the term "value" correctly).
Example #1: Value Parameters
This trivial example is to demonstrate that the address of the passed parameters to a function are not the same as the address of the arguments supplied to the function.
#include <stdio.h>
int foo_one(int a, int b)
{
printf("foo: &a = %p, &b=%p\n", &a, &b);
return a+b;
}
int main()
{
int a = 1, b = 2;
printf("main: &a = %p, &b=%p\n", &a, &b);
foo_one(a,b);
return 0;
}
Output (address values will vary on your system)
main: &a = 0x7fff5fbff938, &b=0x7fff5fbff934
foo: &a = 0x7fff5fbff90c, &b=0x7fff5fbff908
Note the logical address of the variables in the function are different than those in main(). The values of a and b are pushed into temporary storage (commonly a "stack", but you likely don't know what that is without a formal data-structures course, and if you had one of those under your belt you probably would not be asking this question). Then the function call is made.
Example #2: Dysfunctional Out-Parameter
So why do you care. Well, now consider this:
#include <stdio.h>
void foo_two(int a, int b, int c)
{
printf("foo: &a = %p, &b=%p, &c=%p\n", &a, &b, &c);
c = a + b;
}
int main()
{
int a = 1, b = 2, c = 0;
printf("main: &a = %p, &b=%p, &c=%p\n", &a, &b, &c);
foo_two(a,b,c);
printf("c = %d\n", c);
return 0;
}
Output (address values will vary on your system)
main: &a = 0x7fff5fbff938, &b=0x7fff5fbff934, &c=0x7fff5fbff930
foo: &a = 0x7fff5fbff90c, &b=0x7fff5fbff908, &c=0x7fff5fbff904
c = 0
What just happened? The c variable we modified in foo_two() was not the variable in main(). They have different memory addresses. The one we modified in foo_two() was a by-value copy (a "temp" variable discussed in Example #1).
Example #3: Functional Out-Parameter
If only there was a way we could tell foo_three() the memory address of the variable in main() directly... Somehow pass that address as the "value" for the parameter, then use it to store our result where it needs to go; in main::c.
This is exactly what pointers do. In C, a pointer is a variable that holds an address to some other data of a specific type. Where an int holds an integer value, a int* holds an address where an int can be found.
#include <stdio.h>
void foo_three(int a, int b, int* ptr)
{
printf("foo: &a = %p, &b=%p, ptr=%p\n", &a, &b, ptr);
*ptr = a + b; // note the dereference operator
}
int main()
{
int a = 1, b = 2, c = 0;
printf("main: &a = %p, &b=%p, &c=%p\n", &a, &b, &c);
foo_three(a,b,&c); // note the address of c being passed
printf("c = %d\n", c);
return 0;
}
Output (address values will vary on your system)
main: &a = 0x7fff5fbff938, &b=0x7fff5fbff934, &c=0x7fff5fbff930
foo: &a = 0x7fff5fbff90c, &b=0x7fff5fbff908, ptr=0x7fff5fbff930
c = 3
This is important. Look carefully at what is being printed in foo_three(). The value of the ptr parameter, a pointer, is the same as the address of the c variable in main() this gives us the ability to modify the int at that address directly.
Summary
If you want to pass something by address in C, then passing the address is exactly what you have to do; pass the address and declare the parameter to be a pointer to the variable type. Use the dereference operator to write/read data to/from said address while in the function, and the caller-side variable will be appropriately modified.
Now after all that, look back at your program and see if you can understand how this can be applied to your problem(s). And study C pointers. They're not magic, and they are heavily used in most C programs. It's worth the time to learn as soon as possible.
I presume you're a student. When learning a new language, it really helps to read other people's code. I rewrote your mean / standard deviation function, showing how I approach this kind of thing. (1-dimensional not 2-dimensional... no free lunch!)
Hope this gets you on the right track.
I do agree with the other posters that you need to get comfortable using the debugger... even if there are no compiler errors or linker errors, the program still may not work correctly. You can validate the correctness of a function by using a unit test framework such as Google Test or CppUnit, or you can just use an ad hoc test function as I show below.
// tested with minGW_w32 gcc-4.7.2
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
/// Calculate mean and standard deviation of a 1-dimensional array.
/// Example showing how to pass values by reference.
///
/// #param[in] x = 1-dimensional array of values to evaluate
/// #param[in] length = number of elements in array
/// #param[out] pdMean = caller-allocated storage for arithmetic mean average
/// #param[out] pdStdDev = caller-allocated storage for standard deviation
///
/// void return type because this function does not have a return value.
///
void calculateMeanAndStdDev (double x[], size_t length, double* pdStdDev, double* pdMean)
{
size_t index; // size_t is an unsigned integer type useful for counting array elements
double sumX = 0;
double sumXSquared = 0;
for (index = 0; index < length; index++)
{
// accumulate sum of the x values
sumX += x[index];
// accumulate the sum of each x squared
sumXSquared += ( x[index] * x[index] );
}
// pdMean is a pointer to the variable in the caller, which will receive the value
// *pdMean is the object that double& pdMean points to.
// I'm using the pd prefix to mean pointer to double.
// I prefer to write this as (*pdMean) to help clarify that I'm using * to dereference a pointer, not to perform multiplication.
(*pdMean) = sumX / length;
double variance = 0;
for (index = 0; index < length; index++)
{
const double differenceFromMean = x[index] - (*pdMean);
// without the parenthesis this is written as differenceFromMean = x[index] - *pdMean;
variance += differenceFromMean * differenceFromMean;
}
(*pdStdDev) = sqrt ( variance / length);
/// #note there's a more effient way to calculate mean and standard deviation, where you accumulate sumX and sumXSquared in a single pass,
/// then mean is sumX / length and StdDev is calculated from sumXsquared and (sumX)*(sumX).
/// For purposes of this exercise I stuck with the more direct equation.
}
/// Example ad hoc test driver calling calculateMeanAndStdDev()
void Test_calculateMeanAndStdDev()
{
double demoArray[] = { 1.0, 2.0, 3.0, 7.5, 9.2 };
const double expect_Mean = 4.54;
const double expect_StdDev = 3.2196894260161177;
double Mean; // will be filled in by calculateMeanAndStdDev
double StdDev; // will be filled in by calculateMeanAndStdDev
calculateMeanAndStdDev(demoArray, sizeof(demoArray)/sizeof(double), &StdDev, &Mean);
const double compare_threshold = 0.001;
if ( abs(Mean - expect_Mean) > compare_threshold ) {
printf("\n""Test_calculateMeanAndStdDev() fail: Mean=%1.6f buf expect_Mean=%1.6f", Mean, expect_Mean);
} else {
printf("\n""Test_calculateMeanAndStdDev(): Mean=%1.6f as expected", Mean);
}
if ( abs(StdDev - expect_StdDev) > compare_threshold ) {
printf("\n""Test_calculateMeanAndStdDev() fail: StdDev=%1.6f buf expect_StdDev=%1.6f", StdDev, expect_StdDev);
} else {
printf("\n""Test_calculateMeanAndStdDev(): StdDev=%1.6f as expected", StdDev);
}
}
int main(void)
{
Test_calculateMeanAndStdDev();
return 0;
}
C pointers are very powerful and fundamental to the language, but they're also one of the trickiest features to understand. That's why languages like Java hide this pointer mechanism from the programmer. In C you have to program defensively, because the compiler always assumes you know what you're doing. Want to write code that modifies itself during execution? C is ok with that, even if your program kills itself. Write outside the bounds of an array allocated on the stack? Sure, no problem, your function just won't be able to return... So all in all, when dealing with pointers, especially when first starting out, code defensively to try to avoid getting confused. Because you can't rely on compiler warnings to tell you if there's going to be a problem.