Using a variable outside of a loop, value changes within the loop - c

I am relatively new to programming and I have come across an issue whilst trying to write a function that utilizes loops. The function should work as such:
The array Data consists of a 51X2 set of doubles, which are all used in the program through the initial for loop, the a variable and the b variable. The X and Y variables are both set to the minimum values of the array.
Using the a and X variables as an example, the X value is compared to a and incremented until it surpasses a. The number of loop iterations are tracked by the c variable. This c variable is then used in the Graph array. The same procedure occurs for the b and Y variables. This process is repeated for every value of S to analyse all data points from the Data array.
The issue I'm having is that the c and d variables don't change relative to the changes inside the loops. The variables will not change from their initialized value. I am looking to find a solution that allows for the c and d variables to change in relation to the number of iterations of the for loop.
The relevant function code can be seen below:
void Data_Plot(double Data[51][2], char Graph[44][56])
{
int N = 50;
int S,q,r;
int c = 0;
int d = 0;
double a = Data[S][0];
double b = Data[S][1];
double X = Data[0][0];
double Y = Data[0][1];
for (S=0;S<N;S++)
{
for(X;X<a;X+=0.1428571429)
{
c++;
}
for(Y;Y<b;Y+=2)
{
d++;
}
Graph[c][d] = '*';
}
I am aware that my code is very unoptimized and messy, but I can fix those issues up with future projects after I have finished this one.
Edit: I would like to note that I have attempted this with c and d being set to other values, as well as being left as NULL. The same result occurred regardless of the variable initialization.

Since a and b depend on S, which you change during the for loop, you need to move those variables inside the loop.
void Data_Plot(double Data[51][2], char Graph[44][56])
{
int N = 50;
int S,q,r;
int c = 0;
int d = 0;
double X = Data[0][0];
double Y = Data[0][1];
for (S=0;S<N;S++)
{
double a = Data[S][0];
for(X;X<a;X+=0.1428571429)
{
c++;
}
double b = Data[S][1];
for(Y;Y<b;Y+=2)
{
d++;
}
Graph[c][d] = '*';
}

Related

If I run a loop a million times, do I have to worry about declaring doubles in each iteration?

I run a loop a million times. Within the loop I call a C function to do some math (generating random variables from various distributions, to be exact). As part of that function, I declare a couple of double variables to hold parts of the transformation. An example:
void getRandNorm(double *randnorm, double mean, double var, int n)
{
// Declare variables
double u1;
double u2;
int arrptr = 0;
double sigma = sqrt(var); // the standard deviation
while (arrptr < n) {
// Generate two uniform random variables
u1 = rand() / (double)RAND_MAX;
u2 = rand() / (double)RAND_MAX;
// Box-Muller transform
randnorm[arrptr] = sqrt(-2*log(u1))*cos(2*pi*u2)*sigma+mean;
arrptr++;
if (arrptr < n) { // for an odd n, we cannot add off the end
randnorm[arrptr] = sqrt(-2*log(u2))*cos(2*pi*u1)*sigma+mean;
arrptr++;
}
}
}
And the calling loop:
iter = 1000000 // or something
for (i = 0; i < iter; i++) {
// lots of if statements
getRandNorm(sample1, truemean1, truevar1, n);
// some more analysis
}
I am working on speeding up the runtime. It occurs to me that I don't know what is happening with all these double variables that I am declaring. I assume a new 8 byte chunk of memory is allocated for the double for each of the one million loops. What happens to all those memory locations? They are declared within a C function; do they survive that function? Are they still locked up until the script exits?
The context for this question is wrapping this C program into a python function. If I'm going to execute this function multiple times in parallel from python, I want to be sure that I'm being as thrifty with memory usage as possible.
If you're talking about something like this:
for(int i=0;i<100000;i++){
double d = 5;
// some other stuff here
}
d is only allocated once by the compiler. It's mostly equivalent to declaring it above the for loop, except that the scope doesn't extend as far.
However, if you are doing something like this:
for(int i=0;i<1000000;i++){
double *d = malloc(sizeof(double));
free(d);
}
Then yes, you will allocate a double 1 million times, but it will likely re-use the memory for subsequent allocations. Finally, if you don't free the memory in my second example, you'll leak 16-32MB of memory.
The short answer is: NO, it should not matter if you declare these double variables inside the loop in C. By double variable, I assume you mean variables of type double.
The long answer is: Please post your code so people can tell you if you do something wrong and how to fix it to improve correctness and/or performance (a vast subject).
The final answer is: with the code provided, it makes no difference whether you declare u1 and u2 inside the body of the loop or outside. A good compiler will likely generate the same code.
You can improve the code a tiny bit by testing the odd case just once:
void getRandNorm(double *randnorm, double mean, double var, int n, double pi) {
// Declare variables
double u1, u2;
double sigma = sqrt(var); // the standard deviation
int arrptr, odd;
odd = n & 1; // check if n is odd
n -= odd; // make n even
for (arrptr = 0; arrptr < n; arrptr += 2) {
// Generate two uniform random variables
u1 = rand() / (double)RAND_MAX;
u2 = rand() / (double)RAND_MAX;
// Box-Muller transform
randnorm[arrptr + 0] = sqrt(-2*log(u1)) * cos(2*pi*u2) * sigma + mean;
randnorm[arrptr + 1] = sqrt(-2*log(u2)) * cos(2*pi*u1) * sigma + mean;
}
if (odd) {
u1 = rand() / (double)RAND_MAX;
u2 = rand() / (double)RAND_MAX;
randnorm[arrptr++] = sqrt(-2*log(u1)) * cos(2*pi*u2) * sigma + mean;
}
}
Note: arrptr + 0 is here for symmetry, the compiler will not generate any code for this addition.
regarding your question: If I run a loop a million times, do I have to worry about declaring doubles in each iteration?
The variables are being declared on the stack. So they 'disappear' when the function exits. The next execution of the function 're-creates' the variables, so (in reality) there is only a single instance of the variables and even then, only while the function is being executed.
So it does not matter how many times you call the function.

Using assert with arrays in C

part of the program I'm writing involves making a function to test assertions. This one is testing my Shift3DPoint function, which takes the first array and modifies it by adding the contents of the second array (so for example, test14 and test15 (as seen below) would result with the new test14 {6,8,0}. However, I'm confused about how I can word this in my function because it's supposed to return an array and I've only worked with doubles before for assert. Any help would be appreciated!
void UnitTest3D(void); //function for assertions
void Shift3DPoint (double pt[], double offset[]);
void UnitTest3D(void){
double test13[3] = {0,0,0};
double test14[3] = {6,0,0};
double test15[3] = {0,8,0};
assert(UnitTest3D(test13, test14) ???
return;
}
void Shift3DPoint(double pt[], double offset[]) {
int i = 0;
for (i = 0; i < 3; ++i) {
pt[i] = pt[i] + offset[i]; //changes array contents by adding corresponding ptB
}
return;
}
assert is just a helper function you may or may not use. If you want to use assert explicitly (maybe because it aborts your program if it fails) you can write the test itself and then test it with assert. In your case, it would be that the test14 would have an expected value. How I would treat the thing, at first sight could be:
void UnitTest3D(void){
double test14[3] = {6,0,0};
double test15[3] = {0,8,0};
double expected_result[3] = {6,8,0};
// Test the result after calling the function
Shift3DPoint(test14, test15);
for (int i = 0; i < 3; ++i)
assert(test14[i] == expected_result[i]);
return;
}
(note that you have the call with different arrays, but I think you get the point). You can write helper macros or more generic functions, but you get the idea.
Also, take into account that double values are rarely checked with ==, as precission issues arise, so you should give some kind of epsilon, for the precission you want your calculations to be held:
assert ( fabs(test14[i] - expected_result[i]) < epsilon);

Passing 2d arrays and then not getting a value

I am having an issue with some code that I am writing.
I use this site often as I have found many people who have already asked the same questions I am wondering. With that I want to thank the community on here for all of the previous insight into my programming conundrums.
(And before we get too far, no this is not a 'school project' or 'school homework', I am simply trying to solve the 'Travelling Salesman Problem' and better my C skills.
This is the portion of code I have been stuck on:
void printAndFlip(int arrayone[][20], int citytotal, int arrayCities[])
{
////Finds cost:
int x, y, z;
int totalCost
int singleTrip;
int cheepestTrip;
int nCity = citytotal + 1; //nCity is the number of Cities //Adding one to accomadate going back to the first city
int gCounter;
int gCounterTrue = 1;
int cheepestTrip[20];
int totalCost = 0;
int lCounter;
int i;
int n = citytotal;
////Sets up for a default case to set cheepestTrip:
for(gCounter = 1; gCounter <= nCity; gCounter++)
{
while(gCounterTrue == 1)
{
if(gCounter == arrayCities[gCounter])
{
gCounterTrue = 1;
}
else
{
gCounterTrue = 0;
gCounter = 50; //Stopping the larger for loop with 50 (the nCity can't be larger than 20) so that it will hopefully be faster
}
if(gCounter == nCity)
{
if(arrayCities[1] == arrayCities[nCity])
{
!!!!! cheepestTrip = totalCost;
}
}
}
}
for(x = 1; x < nCity; x++)
{
y = arrayCities[x];
z = arrayCities[x+1];
singleTrip = arrayone[y][z]; //finding individual cost of each trip...will be added to 'totalCost' below
totalCost = singleTrip + totalCost;
}
!!!!!!!! if(totalCost <= cheepestTrip)
{
for(lCounter = 1; lCounter <= nCity; lCounter++)
{
cheepestTrip[lCounter] = arrayCities[lCounter];
}
}
To make it easier to show where my compile errors are at I put exclamation points on the lines.
Please tell me if I am wrong, but I am passing an array of pointers with an array when I send 'arrayone' to printANDFlip right?
I know the compile errors are relating to the pointers but I am just uncertain of where they should be placed.
Any and all help will be appreciated.
Much thanks,
Alex
To make explicit what some of the other replies are saying: You have two variables with the same name but different types:
int cheepestTrip; /* This is an single integer... */
and
int cheepestTrip[20]; /* ...but this is an array of integers. */
This should be triggering a warning at compile time (probably something about redeclaring an existing variable).
Here you are comparing an array pointer with a int value
if(totalCost <= cheepestTrip)
For example you should compare it to an element of that array
if(totalCost <= cheepestTrip[0])
cheepestTrip is the name of the array, which is equivalent to a pointer to the first element. totalCost is an int. Just remove the [20] from your declaration at the top part of the code.
you are comparing a pointer to an int, which your particular compiler might not be allowing (though I though with C you could). but cheapestTrip is essentially a pointer to the first element in your array of ints, while totalcost is simply an int primative

C array of functions

I have a problem with a series of functions. I have an array of 'return values' (i compute them through matrices) from a single function sys which depends on a integer variable, lets say, j, and I want to return them according to this j , i mean, if i want the equation number j, for example, i just write sys(j)
For this, i used a for loop but i don't know if it's well defined, because when i run my code, i don't get the right values.
Is there a better way to have an array of functions and call them in a easy way? That would make easier to work with a function in a Runge Kutta method to solve a diff equation.
I let this part of the code here: (c is just the j integer i used to explain before)
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int N=3;
double s=10.;
//float r=28.;
double b=8.0/3.0;
/ * Define functions * /
double sys(int c,double r,double y[])
{
int l,m,n,p=0;
double tmp;
double t[3][3]={0};
double j[3][3]={{-s,s,0},{r-y[2],-1,-y[0]},{y[1],y[0],-b}}; //Jacobiano
double id[3][3] = { {y[3],y[6],y[9]} , {y[4],y[7],y[10]} , {y[5],y[8],y[11]} };
double flat[N*(N+1)];
// Multiplication of matrices J * Y
for(l=0;l<N;l++)
{
for(m=0;m<N;m++)
{
for(n=0;n<N;n++)
{
t[l][m] += j[l][n] * id[n][m];
}
}
}
// Transpose the matrix (J * Y) -> () t
for(l=0;l<N;l++)
{
for(m=l+1;m<N;m++)
{
tmp = t[l][m];
t[l][m] = t[m][l];
t[m][l] = tmp;
}
}
// We flatten the array to be left in one array
for(l=0;l<N;l++)
{
for(m=0;m<N;m++)
{
flat[p+N] = t[l][m];
}
}
flat[0] = s*(y[1]-y[0]);
flat[1] = y[0]*(r-y[2])-y[1];
flat[2] = y[0]*y[1]-b*y[2];
for(l=0;l<(N*(N+1));l++)
{
if(c==l)
{
return flat[c];
}
}
}
EDIT ----------------------------------------------------------------
Ok, this is the part of the code where i use the function
int main(){
output = fopen("lyapcoef.dat","w");
int j,k;
int N2 = N*N;
int NN = N*(N+1);
double r;
double rmax = 29;
double t = 0;
double dt = 0.05;
double tf = 50;
double z[NN]; // Temporary matrix for RK4
double k1[N2],k2[N2],k3[N2],k4[N2];
double y[NN]; // Matrix for all variables
/* Initial conditions */
double u[N];
double phi[N][N];
double phiu[N];
double norm;
double lyap;
//Here we integrate the system using Runge-Kutta of fourth order
for(r=28;r<rmax;r++){
y[0]=19;
y[1]=20;
y[2]=50;
for(j=N;j<NN;j++) y[j]=0;
for(j=N;j<NN;j=j+3) y[j]=1; // Identity matrix for y from 3 to 11
while(t<tf){
/* RK4 step 1 */
for(j=0;j<NN;j++){
k1[j] = sys(j,r,y)*dt;
z[j] = y[j] + k1[j]*0.5;
}
/* RK4 step 2 */
for(j=0;j<NN;j++){
k2[j] = sys(j,r,z)*dt;
z[j] = y[j] + k2[j]*0.5;
}
/* RK4 step 3 */
for(j=0;j<NN;j++){
k3[j] = sys(j,r,z)*dt;
z[j] = y[j] + k3[j];
}
/* RK4 step 4 */
for(j=0;j<NN;j++){
k4[j] = sys(j,r,z)*dt;
}
/* Updating y matrix with new values */
for(j=0;j<NN;j++){
y[j] += (k1[j]/6.0 + k2[j]/3.0 + k3[j]/3.0 + k4[j]/6.0);
}
printf("%lf %lf %lf \n",y[0],y[1],y[2]);
t += dt;
}
Since you're actually computing all these values at the same time, what you really want is for the function to return them all together. The easiest way to do this is to pass in a pointer to an array, into which the function will write the values. Or perhaps two arrays; it looks to me as if the output of your function is (conceptually) a 3x3 matrix together with a length-3 vector.
So the declaration of sys would look something like this:
void sys(double v[3], double JYt[3][3], double r, const double y[12]);
where v would end up containing the first three elements of your flat and JYt would contain the rest. (More informative names are probably possible.)
Incidentally, the for loop at the end of your code is exactly equivalent to just saying return flat[c]; except that if c happens not to be >=0 and <N*(N+1) then control will just fall off the end of your function, which in practice means that it will return some random number that almost certainly isn't what you want.
Your function sys() does an O(N3) calculation to multiply two matrices, then does a couple of O(N2) operations, and finally selects a single number to return. Then it is called the next time and goes through most of the same processing. It feels a tad wasteful unless (even if?) the matrices are really small.
The final loop in the function is a little odd, too:
for(l=0;l<(N*(N+1));l++)
{
if(c==l)
{
return flat[c];
}
}
Isn't that more simply written as:
return flat[c];
Or, perhaps:
if (c < N * (N+1))
return flat[c];
else
...do something on disastrous error other than fall off the end of the
...function without returning a value as the code currently does...
I don't see where you are selecting an algorithm by the value of j. If that's what you're trying to describe, in C you can have an array of pointers to functions; you could use a numerical index to choose a function from the array, but you can also pass a pointer-to-a-function to another function that will call it.
That said: Judging from your code, you should keep it simple. If you want to use a number to control which code gets executed, just use an if or switch statement.
switch (c) {
case 0:
/* Algorithm 0 */
break;
case 1:
/* Algorithm 1 */
etc.

Syntax error while copying an multidimensional array to another in C

We are programming a ST269 microcontroller which has two IR distance sensors. To calibrate these sensors we made one table for each sensor with the distance we measured and the corresponding value we get from the ADC.
Now we want to use one function to approximate the values in between. So we defined two two-dimensional arrays (one for each sensor) as global variables. In our function we then want to copy the one array we want to work with to a working array and approximate our values.
So here's the code:
...
unsigned int ir_werte_re[][] = {
{8,553},
...
{83,133}
};
unsigned int ir_werte_li[][] = {
{8,566},
...
{83,147}
};
...
unsigned int geradenaproximation(unsigned int messwert, unsigned int seite)
{
unsigned int working_array[16][16];
unsigned int i = 0;
if (seite == 0) {
for (i = 0; i < sizeof(working_array); i++) {
working_array[i][0] = ir_werte_li[i][0];
i++;
}
}
else {
for (i = 0; i < sizeof(working_array); i++) {
working_array[i][0] = ir_werte_re[i][0];
i++;
}
}
i = 0;
unsigned int y1 = 0;
unsigned int x1 = 0;
...
}
This code is in a file called sensor.c. We didn't write anything about our global arrays in the sensor.h should we? The sensor.h of course is included in our main.c and there the function is called.
We also tried to copy the arrays via
memcpy(working_array, ir_werte_li, sizeof(working_array));
And in every way we do this we get a
syntax error near unsigned
in the line where we're declaring
unsigned int y1 = 0;
and I'm pretty sure that there is no syntax error in this line : )
The last time I spend coding in C is a few years away so I'm not sure if the way we try to do this is good. Perhaps we can solve this by using a pointer instead of really copying the array or something. So please help me out I'll appreciate your bits on this.
In C (pre-C99), all variable definitions must appear at the top of the current block scope.

Resources