Problems to change macro through compiler (solved) and segmentation fault (solved)

Hi, i'm a new user and i need some help to understand how to put a macro in my code that can be changed from compiler before compilation.

My aim is changing DX value into 1,2,4,6 and 8 without rewrite the code and with 5 different compilation attempt(one for each value).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#define N 1000
#define DX 1

void RandomPath(int r2[],double av_r2[]){
  int x=0,i;
  double k;

  for(i=0;i<N;i++){
    k=(double)rand()/(double)RAND_MAX;
    if(k<0.5)
      x=x+DX;
    if(k>=0.5)
      x=x-DX;
    r2[i]=x*x;
    av_r2[i]=av_r2[i]+r2[i];
  }
}


void PrintResults(double av_r2[]){
  int i;
  FILE*fp;
  char filename[20];
  char numbers[8]={'1','2','3','4','5','6','7','8'};
  
  sprintf(filename,"sqm_DX_%c.dat",numbers[DX-1]);
    
  fp=fopen(filename,"w");
    
  for(i=0;i<N;i++){
    fprintf(fp,"%4i %5.5lf\n",i+1,av_r2[i]/(DX*DX));
  }
  
  fclose(fp);
}


int main(){
  int M,i,j,k=0,r2[N];
  double av_r2[N];
  
  srand(time(NULL));

  printf("Inserire il numero dei colloidi: "); // It means: insert number of colloids 
  do{
    scanf("%i",&M);
    if(M<=0)
      printf("Inserire un valore positivo: "); // it means: insert a positive number
  }
  while(M<=0);
  
  for(i=0;i<N;i++){  
    r2[i]=0;
    av_r2[i]=0.0;
  }
  
  for(i=0;i<M;i++){
    RandomPath(r2,av_r2);
    for(j=0;j<N;j++){
      av_r2[j]=av_r2[j]/N;
    }
  }
    
    PrintResults(av_r2);
 
}


I'm sorry if it's not optimized or well-written but i'm at the first year of physics and i have never done it before. I have an exam about this in two days.

i'm looking for someone who could explain how to do and what write in the compiler in order to change my macro as i wish.

P.S. My teacher told us how to do but i can't find my notes. I remember i should put -dDX=[macro value] while i'm compiling but i'dont know where.
Last edited on
Use the 'define' flag, -D, something like this:

gcc -std=c99 -Wall -W -pedantic -DDX=4 phys.c -o phys4

You'll need to either delete the #define DX 1 that you have in your code, or replace it with something like:

1
2
3
#ifndef DX    // only define DX if it hasn't already been defined
#define DX 1
#endif 


An alternative to defining the constant on the compile line and needing to compile the program for such a small change is to pass the value in as a command-line argument.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>

#define N 1000

void RandomPath(int r2[], double av_r2[], int dx) {
    int x = 0;
    for (int i = 0; i < N; i++) {
        if (rand() < RAND_MAX / 2)
            x += dx;
        else
            x -= dx;
        r2[i] = x * x;
        av_r2[i] = av_r2[i] + r2[i];
    }
}

void PrintResults(double av_r2[], int dx) {
    char filename[20];
    sprintf(filename, "sqm_DX_%c.dat", '0' + dx);
    
    FILE *fp = fopen(filename, "w");
    
    for (int i = 0; i < N; i++)
        fprintf(fp, "%4i %5.5lf\n", i + 1, av_r2[i] / (dx * dx));
  
    fclose(fp);
}

int main(int argc, char **argv) {
    int dx = 1;  // default value
    if (argc > 1) {
        dx = atoi(argv[1]);
        if (dx < 1 || dx > 8) {
            fprintf(stderr, "dx must be in [1, 8]\n");
            return EXIT_FAILURE;
        }
    }

    srand(time(NULL));

    int M;
    // insert number of colloids 
    printf("Inserire il numero dei colloidi: ");
    do {
        scanf("%d", &M);
        if (M <= 0)
            // insert a positive number
            printf("Inserire un valore positivo: ");
    } while (M <= 0);
  
    int r2[N];
    double av_r2[N];

    for (int i = 0; i < N; i++) {  
        r2[i] = 0;
        av_r2[i] = 0.0;
    }
  
    for (int i = 0; i < M; i++) {
        RandomPath(r2, av_r2, dx);
        for (int j = 0; j < N; j++)
            av_r2[j] /= N;
    }
    
    PrintResults(av_r2, dx);

    return 0;
}


Last edited on
Hi dutch, thank you, i solved this problem with your help.

Now i have another one that maybe is really stupid but i can't overcome: i don't now the reason why my array histo[r2] goes in segmentation fault.

(This is another code that is based on the first one)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>

#define DX 1
#define N 1000
#define M 10000


void RandomPath(int r2,int histo[]){
  int x=0,i;
  double k;

  for(i=0;i<N;i++){
    k=(double)rand()/(double)RAND_MAX;
    if(k<0.5)
      x=x+DX;
    if(k>=0.5)
      x=x-DX;
  }
  r2=x*(DX*DX);  // The range of r2 is from -N/2 (-500) to N/2 (500)
}


void FillHisto(int r2,int histo[]){
  
  histo[r2]++;  // I need to create an histogram
                        // i suppose the problem is here,
                        //it should be something like wrong memory allocation 
                        // but i can't understand what i did wrong 
                        //because i initialized histo to contain numbers from
                        // -500 to 500 and r2 is in this range
}
  

int main(){
  int i,r2,histo[N+1],bin;
  
  
  srand(time(NULL));
  
  for(i=0;i<=N;i++){   // I want my array to have 1001 memory cells
    bin=i-(N/2);           // from -N/2 (-500) to N/2 (500), o i think i did well here
    histo[bin]=0;
  }

  
  for(i=0;i<M;i++){
    RandomPath(r2,histo);
    FillHisto(r2,histo);
  }
 
}
Last edited on
Perhaps you need to increase your compiler warning levels? It should be telling you something that may be related.

In function 'int main()':
28:11: warning: 'r2' is used uninitialized in this function [-Wuninitialized]
38:9: note: 'r2' was declared here
Sorry but i am not understanding what you are saying.
r2 is not an array anymore, so i think i shouldn't initialize it.
You are suggesting me to re-transform r2 in an array?
Last edited on
You are suggesting me to re-transform r2 in an array?

No, the compiler is saying you should initialize that variable before you use it.

r2 is not an array anymore, so i think i shouldn't initialize it.

What? Every variable should be initialized before you try to use it.

Look at those error messages, r2 (the array index value on line 28) is not initialized. This means it could contain any value which could very easily lead to a program crash.

By the way if you run the program with your debugger it will tell you exactly where it detects the problem and you should be able to view the values held in the variables at the time of the crash.

Arrays can't have negative indices (in c++). Note lines 43-45.

Later on (a separate problem) a value for r2 is not returned from RandomPath, so it can't be used in FillHisto. You could either make r2 a reference parameter in RandomPath or, better, make that function an int function thar returns r2.

But I'd fix your negative array indices first.
Last edited on
Ok, i'm not very keen on programming, so i'm sorry if you have waste your time.

Now the program goes smooth.

Thank you so much.

Arrays can't have negative indices (in c++). Note lines 43-45.

Later on (a separate problem) a value for r2 is not returned from RandomPath, so it can't be used in FillHisto. You could either make r2 a reference parameter in RandomPath or, better, make that function an int function thar returns r2.

But I'd fix your negative array indices first.


Can you help me to fix it? i don't know how to do it.

if you have time, can you explain me your steps?
@Darius00,

There is a huge amount to "fix" in your code.

First of all, forget your histogram initially and just try to return some final points. Note that your end point (r2) could (in principle) be anything from -N to N unless you divide by 2. I suggest that your RandomPath routine simply return the integer at the end; i.e.
1
2
3
4
5
int RandomPath()
{
  // your routine
  return x * DX * DX / 2;     // divide by 2, or they will all end up even!
}



You really don't need FillHisto() at all if all it does is increment one array element. Delete that routine; it has no use.


Forget your lines initialising histo[] in main(). You can achieve what you want when you declare it:
int histo[N+1]{};


I would make your headers "modern":
1
2
3
4
5
#include <iostream>
#include <cstdlib>
#include <cmath>
#include <ctime>
using namespace std;



Before you try to bin your results, just make sure that you can print your random values out:
1
2
3
4
  for(i=0;i<M;i++){
    r2 = RandomPath();
    cout << r2 << '\n';
  }


When - and only when - you are sure that that is working you can bin your random values. Note that, if r2 goes from -N/2 to N/2 you will need to add N/2 to get the non-negative index required in histo[]. replace the output statement in the loop above by
histo[r2+N/2]++;


If that is OK then you can print out your histogram. Be prepared for a lot of 0's at the ends.

for(i=0;i<N;i++) cout << i << '\t' << histo[i] << '\n';


If you make DX anything other than 1 (and there is no good reason for that, because it would simply spread the graph) then you may have to adjust the size of your histogram array or risk out-of-bounds errors.
Last edited on
Topic archived. No new replies allowed.