This is the programm I wrote:
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
void meanVariance(double* x, int n, double* mean, double* variance);
double* scanVector(int length);
void meanVariance(double* x, int n, double* mean, double* variance){
double sum = 0;
for (int i = 0; i < n; i++){
sum += x[i];
}
*mean = sum / ((double)n);
sum = 0;
for (int i = 0; i < n; i++)
{
double sq = x[i] - *mean;
sum += sq * sq;
}
if (n != 1)
{
*variance = sum / ((double)n );
}
else
{
*variance = 1;
}
}
int main() {
double *x = malloc(sizeof(double)), mean = 0, variance = 0;
int n = 0;
do {
n++;
x = realloc(x, sizeof(double) * (n));
printf("Type in the %d- Number
: ", n);
scanf("%lf", (x+(n-1)));
meanVariance(x, n, &mean, &variance);
printf("Mittelwert: %f\n", mean);
printf("Varianz: %f\n", variance);
} while(*(x+(n-1)) != 0);
free(x);
}
I don't unterstand why there is no & in the scanf function. The program works but I just don't unterstand why cause the & is missing. I'm guessing it has something to do with the pointer x however i'm not sure at all.
You only need & if you need to take the address of a value, that is, produce a pointer to that value. But x is already a pointer, so there is no need for &. It would be quite wrong to use & in this case, because you'd end up with a pointer to a pointer!
There is also some pointer arithmetic going on: x+(n-1) advances the pointer by n-1 positions in memory, each position being sizeof(double) bytes. If you view x as an array, it's the same as &x[n-1]; that is, the address of the n-1th element in the array.
x+(n-1) - this is pointer arithmetic (study the term).
The [] operator is specified with the guarantee that array[i] (readable) is 100% equivalent to *((array) + (i)) (unreadable).
In your case &x[n-1] is the same as &*( (x) + (n-1) ). The & and * cancel each other out and what remains is x + (n-1).
So we can unslopify the code using readable form like this: scanf("%lf", &x[n-1]);
Related
I am quite new to programming with C, so hope someone can bear with me and help me solve the issue I am facing.
I am writing a code to estimate the value of pi with Monte-Carlo method. however, when I build and debug I get an error that says:
"Exception thrown: write access violation.
a was 0x1110112.
I get this error in generate_random_array function
in this line of code:
a[i] = (((double)rand() / (double)RAND_MAX) * 2.0 ) - 1.0;
I am posting the whole code as well for reference.
note: I am using visual studio with MSVC compiler
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void generate_random_array(int sz, double a[]);
void count_points_inside_circle(int sz, double x[], double y[], int* counter);
int main()
{
int tot = 1000000000;
int incircle_c = 0;
double distance_sq, pi;
double* x = NULL;
double* y = NULL;
/*create arrays in the heap*/
x = malloc(tot * sizeof(double));
y = malloc(tot * sizeof(double));
/*generate random locations*/
generate_random_array(tot, x);
generate_random_array(tot, y);
/*count the points inside te circle by checking the location distance*/
count_points_inside_circle(tot, x, y, &incircle_c);
/*estimate pi*/
pi = 4.0 * incircle_c / (double)tot;
printf("pi estimated value using %d samples was found to be %lf", tot, pi);
free(x);
free(y);
return 0;
}
void generate_random_array(int sz, double a[]) {
int i;
srand(time(NULL));
for (i = 0; i < sz; i++)
a[i] = (((double)rand() / (double)RAND_MAX) * 2.0 ) - 1.0;
}
void count_points_inside_circle(int sz, double x[], double y[],int* counter_p) {
int i;
double distance_sq;
for (i = 0; i < sz; i++) {
distance_sq = x[i] * x[i] + y[i] * y[i];
if (distance_sq <= 1)
(*counter_p)++;
}
}
You must always check the pointer returned from malloc against NULL. For example:
x = malloc(n * sizeof *x);
if (x == NULL) { /* Handle the failure and/or exit */ }
On the other hand, this task doesn't require use of an array (or allocated space used as an array) at all; you need only the number of points inside the circle and the number of total points generated. It could be simply done like that:
#include <stdio.h>
#include <stdlib.h>
double estimate_pi (unsigned trial_count)
{
const double rr = (double)RAND_MAX * RAND_MAX;
unsigned inner_point_count = 0;
unsigned i;
for (i = 0; i < trial_count; ++i) {
double x = rand();
double y = rand();
if (x * x + y * y <= rr)
++inner_point_count;
}
return 4.0 * inner_point_count / trial_count;
}
int main (void)
{
printf("%f\n", estimate_pi(1000000000));
return 0;
}
Note that, quality of random number generator used by the standard library significantly affects the result of this simulation.
I have this recursive function, and I try to pass the result in 's' variable.
However if I use *s=*s+v[i]; the function works.
But if I try to call sum(v,i+2,s+v[i],n); It doesn't work anymore.
Can someone tell me what is wrong?
Here is the code:
void sum(int v[], int i, int *s, int n)
{
if (i < n)
{
if (v[i] < 0)
{
//*s = *s + v[i];
//sum(v, i + 2, s, n);
sum(v, i + 2, s + v[i], n);
}
else
sum(v, i + 2, s, n);
}
}
int main()
{
int n = 7;
int v[] = { -5,-8,4,4,3,9,-5 };
int i = 0;
int s = 0;
sum(v, i, &s, n);
printf("SUM IS: %d", s);
return 0;
}
There is a major difference between to 2 ways.
The correct one:
*s = *s +v[i]; // increases the int object pointed to by s
sum(v, i + 2, s, n); // still pass the same pointer to sum
The wrong one:
sum(v, i+2, s+v[i], n);
Here, the pointer is increased instead of the pointed object. It is equivalent to:
s = s +v[i]; // s is not dereferenced here!
sum(v, i + 2, s, n); // pass an incorrect pointer to sum
Looks like you have multiple problems that need correction.
First of all, the inner if is not needed. It is unclear what you wanted to do with this. Handling negative numbers separately? If so, it is not needed since the + operator can also handle addition of negative numbers.
Secondly, the s + v[i] adds the value in your array to the pointer to sum, which is not what you want. You need to use the * operator to dereference s here so that the number is added to the sum that the pointer points to. Your own commented-out code does this correctly.
Thirdly, using sum(v, i + 2, s, n); skips alternate elements so to sum the whole array properly, you need to use i + 1 instead of i + 2.
The following code fixes these issues.
void sum(int v[], int i, int *s, int n)
{
if (i < n)
{
*s += v[i];
sum(v, i + 1, s, n);
}
}
int main()
{
int n = 7;
int v[] = { -5,-8,4,4,3,9,-5 };
int i = 0;
int s = 0;
sum(v, i, &s, n);
printf("SUM IS: %d", s);
return 0;
}
In my program the user allocates a number of random float values to a pointer array.
After that I wish to use the values generated in the array in a function to calculate the mean-value, but I dont get the correct values
This is what I use to allocate random float numbers to the pointer *arr
for (int i = 0; i < antalVarde; i++)
{
if (i % 10 == 0)
printf("\n");
*arr = RandomReal(low, high);
printf("%.1f ", *arr);
}
And this is my function to calculate the mean-value.
float mean(int antalVarde, float *arr)
{
float medel = 0.0;
for (int i = 0; i < antalVarde; i++)
{
medel = medel + *(arr + i);
}
medel = medel / antalVarde;
return medel;
}
When I debug while stepping-into the code it gets messed up when I get to
medel = medel + *(arr + i);
Can this not be used to access the values in a pointer array?
Forgive me if it's a poorly asked question.
grateful for answers.
You don't increment pointer arr in the initialisation loop. Only the first float at the addresse pointed by arr is written.
So.. I have something like this. It is supposed to create arrays with 10, 20, 50 100 .. up to 5000 random numbers that then sorts with Insertion Sort and prints out how many comparisions and swaps were done .. However, I am getting a runtime exception when I reach 200 numbers large array .. "Access violation writing location 0x00B60000." .. Sometimes I don't even reach 200 and stop right after 10 numbers. I have literally no idea.
long *arrayIn;
int *swap_count = (int*)malloc(sizeof(int)), *compare_count = (int*)malloc(sizeof(int));
compare_count = 0;
swap_count = 0;
int i, j;
for (j = 10; j <= 1000; j*=10) {
for (i = 1; i <= 5; i++){
if (i == 1 || i == 2 || i == 5) {
int n = i * j;
arrayIn = malloc(sizeof(long)*n);
fill_array(&arrayIn, n);
InsertionSort(&arrayIn, n, &swap_count, &compare_count);
print_array(&arrayIn, n, &swap_count, &compare_count);
compare_count = 0;
swap_count = 0;
free(arrayIn);
}
}
}
EDIT: ok with this free(arrayIn); I get this " Stack cookie instrumentation code detected a stack-based buffer overrun." and I get nowhere. However without it it's "just" "Access violation writing location 0x00780000." but i get up to 200numbers eventually
void fill_array(int *arr, int n) {
int i;
for (i = 0; i < n; i++) {
arr[i] = (RAND_MAX + 1)*rand() + rand();
}
}
void InsertionSort(int *arr, int n, int *swap_count, int *compare_count) {
int i, j, t;
for (j = 0; j < n; j++) {
(*compare_count)++;
t = arr[j];
i = j - 1;
*swap_count = *swap_count + 2;
while (i >= 0 && arr[i]>t) { //tady chybí compare_count inkrementace
*compare_count = *compare_count + 2;
arr[i + 1] = arr[i];
(*swap_count)++;
i--;
(*swap_count)++;
}
arr[i + 1] = t;
(*swap_count)++;
}
}
I am sure your compiler told you what was wrong.
You are passing a long** to a function that expects a int* at the line
fill_array(&arrayIn, n);
function prototype is
void fill_array(int *arr, int n)
Same problem with the other function. From there, anything can happen.
Always, ALWAYS heed the warnings your compiler gives you.
MAJOR EDIT
First - yes, the name of an array is already a pointer.
Second - declare a function prototype at the start of your code; then the compiler will throw you helpful messages which will help you catch these
Third - if you want to pass the address of a simple variable to a function, there is no need for a malloc; just use the address of the variable.
Fourth - the rand() function returns an integer between 0 and RAND_MAX. The code
a[i] = (RAND_MAX + 1) * rand() + rand();
is a roundabout way of getting
a[i] = rand();
since (RAND_MAX + 1) will overflow and give you zero... If you actually wanted to be able to get a "really big" random number, you would have to do the following:
1) make sure a is a long * (with the correct prototypes etc)
2) convert the numbers before adding / multiplying:
a[i] = (RAND_MAX + 1L) * rand() + rand();
might do it - or maybe you need to do some more casting to (long); I can never remember my order of precedence so I usually would do
a[i] = ((long)(RAND_MAX) + 1L) * (long)rand() + (long)rand();
to be 100% sure.
Putting these and other lessons together, here is an edited version of your code that compiles and runs (I did have to "invent" a print_array) - I have written comments where the code needed changing to work. The last point above (making long random numbers) was not taken into account in this code yet.
#include <stdio.h>
#include <stdlib.h>
// include prototypes - it helps the compiler flag errors:
void fill_array(int *arr, int n);
void InsertionSort(int *arr, int n, int *swap_count, int *compare_count);
void print_array(int *arr, int n, int *swap_count, int *compare_count);
int main(void) {
// change data type to match function
int *arrayIn;
// instead of mallocing, use a fixed location:
int swap_count, compare_count;
// often a good idea to give your pointers a _p name:
int *swap_count_p = &swap_count;
int *compare_count_p = &compare_count;
// the pointer must not be set to zero: it's the CONTENTs that you set to zero
*compare_count_p = 0;
*swap_count_p = 0;
int i, j;
for (j = 10; j <= 1000; j*=10) {
for (i = 1; i <= 5; i++){
if (i == 1 || i == 2 || i == 5) {
int n = i * j;
arrayIn = malloc(sizeof(long)*n);
fill_array(arrayIn, n);
InsertionSort(arrayIn, n, swap_count_p, compare_count_p);
print_array(arrayIn, n, swap_count_p, compare_count_p);
swap_count = 0;
compare_count = 0;
free(arrayIn);
}
}
}
return 0;
}
void fill_array(int *arr, int n) {
int i;
for (i = 0; i < n; i++) {
// arr[i] = (RAND_MAX + 1)*rand() + rand(); // causes integer overflow
arr[i] = rand();
}
}
void InsertionSort(int *arr, int n, int *swap_count, int *compare_count) {
int i, j, t;
for (j = 0; j < n; j++) {
(*compare_count)++;
t = arr[j];
i = j - 1;
*swap_count = *swap_count + 2;
while (i >= 0 && arr[i]>t) { //tady chybí compare_count inkrementace
*compare_count = *compare_count + 2;
arr[i + 1] = arr[i];
(*swap_count)++;
i--;
(*swap_count)++;
}
arr[i + 1] = t;
(*swap_count)++;
}
}
void print_array(int *a, int n, int* sw, int *cc) {
int ii;
for(ii = 0; ii < n; ii++) {
if(ii%20 == 0) printf("\n");
printf("%d ", a[ii]);
}
printf("\n\nThis took %d swaps and %d comparisons\n\n", *sw, *cc);
}
You are assigning the literal value 0 to some pointers. You are also mixing "pointers" with "address-of-pointers"; &swap_count gives the address of the pointer, not the address of its value.
First off, no need to malloc here:
int *swap_count = (int*)malloc(sizeof(int)) ..
Just make an integer:
int swap_coint;
Then you don't need to do
swap_coint = 0;
to this pointer (which causes your errors). Doing so on a regular int variable is, of course, just fine.
(With the above fixed, &swap_count ought to work, so don't change that as well.)
As I told in the comments, you are passing the addresses of pointers, which point to an actual value.
With the ampersand prefix (&) you are passing the address of something.
You only use this when you pass a primitive type.
E.g. filling the array by passing an int. But you are passing pointers, so no need to use ampersand.
What's actually happening is that you are looking in the address space of the pointer, not the actual value the pointer points to in the end. This causes various memory conflicts.
Remove all & where you are inputting pointers these lines:
fill_array(&arrayIn, n);
InsertionSort(&arrayIn, n, &swap_count, &compare_count);
print_array(&arrayIn, n, &swap_count, &compare_count);
So it becomes:
fill_array(arrayIn, n);
InsertionSort(arrayIn, n, swap_count, compare_count);
print_array(arrayIn, n, swap_count, compare_count);
I also note that you alloc memory for primitive types, which could be done way simpler:
int compare_count = 0;
int swap_count = 0;
But if you choose to use the last block of code, DO use &swap_count and &compare_count since you are passing primitive types, not pointers!
I keep getting the following error message when I run my code in debug.
Windows has triggered a breakpoint in Linear Equations 331.exe.
This may be due to a corruption of the heap, which indicates a bug in
Linear Equations 331.exe or any of the DLLs it has loaded.
Then it comes up with a break/continue.
The code uses a Gauss-Siedel Iterative method to solve a n x n system of linear equations. In this case I need to find the total amount of stretch (X) for 3 bungee cords in series,with 3 people (A,B,C) attached to it. Each solution has a different permutation of the people attached (i.e. A,B,C ; A,C,B ; B,A,C etc.)
We were supplied with a memory allocation header file called alloc.h, though I don't fully understand how it works which may be causing my problem. It worked fine before I started using ALLOCATE() for more variables. Any help in explaining why this is happening would be really helpful.
The main code is first. Header Files are at the bottom. Sorry if the code is a bit messy. I tried to comment as best as I could:
#define _CRT_SECURE_NO_DEPRECATE
#define _CRT_SECURE_NO_WARNINGS
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "allocate.h"
#include "iter.h"
void position_solve(int n,int k,double X[], double x[],double order[]);
void inverse(int n, double A[],double X[],double b[]);
void swap(double *,double*);
void permute(int n, double a[]);
int noofpermutations();
void next(int n,double a[]);
void permutation(int n, double a[]);
int count = 0;
int main(void)
{
int i,j,k,num=0, n=3, p=noofpermutations(n);
double *A = NULL, *m = NULL, *X = NULL,* b= NULL,*K=NULL, *x=NULL, *order=NULL, *length=NULL;
/* Allocate the required memory */
ALLOCATE(A, double, n * n);
ALLOCATE(m, double, n * p);
ALLOCATE(b, double, n);
ALLOCATE(x, double, n * p);
ALLOCATE(K, double, n * p);
ALLOCATE(X, double, n);
ALLOCATE(order,double, n);
ALLOCATE(length,double,1);
/*Defining the Order of A,B,C jumpers where 1 = A, 2 = B, 3 = C*/
printf("+-----------------------------------------------------------------------------+\n");
printf("The Order of Bungee Jumpers A,B and C is represented by \n1,2,and 3 respectively. \n");
printf("\n+-----------------------------------------------------------------------------+\n");
for(i=0;i<n;i++){
order[i] = i+1;
b[i] = 0;
}
length[0] = 0;
/*Hardcoding k(spring constant),x(initial length of each bungee cord) and m(mass in kg) for 3 bunjee jumpers*/
K[0] = 50;
K[1] = 100;
K[2] = 50;
m[0] = -60*9.81;
m[1] = -70*9.81;
m[2] = -80*9.81;
x[0] = 20;
x[1] = 20;
x[2] = 20;
for(i=3;i<n*p;i++){
K[i] = 0;
m[i] = 0;
x[i] = 0;
}
/*Generate Permutations of K,m for the given Order of Bungee Jumpers */
permutation(n,K);
permutation(n,m);
permutation(n,order);
/*Calculate A matrix*/
for(k=0;k<p;k++){
for (i = 0; i < n; i++) {
for (j = 0; j < n; j++) {
if(i==j){
A[i*n + j] = -K[k*n + i] - K[k*n + j];
}
else if(j == (i+1)){
A[i*n+j] = K[k*n + j];
A[j*n+i] = K[k*n + j];
}
else if(j>(i+1)){
A[i*n + j] = 0;
}
}
}
printf("\nFor a Bungee Jumper order %1.0lf %1.0lf %1.0lf :\n",order[k*n],order[k*n+1],order[k*n+2]);
/*Determine multiple X (stretch of bungee in m) vecotrs*/
/*Extract a single RHS vector (from B) into b*/
for(i=0;i<n;i++){
b[i]= m[k*n + i];
}
/*Perform Iterative Method*/
iter_solve(n, A, b, X);
/* Output X solutions*/
printf("\nX = [\n");
for (j = 0; j < n; j++) {
printf("%f ", X[j]);
printf("\n");
}
printf("]\n");
/*Determine Order of Jumpers*/
position_solve(n,k,X,x,order);
printf("--------------------------------------------\n\n");
/*If A,B,C Permutation find inverse*/
if(((int)(order[k*n])==1) && ((int)(order[k*n+1])==2)){
inverse(n,A,X,b);
}
}
/* Free allocated memory */
FREE(A);
FREE(b);
FREE(x);
FREE(X);
FREE(order);
FREE(length);
FREE(m);
return 0;
}
void iter_solve(int n, double A[], double b[], double x[])
{
int i, j, k = 0;
double sum, delta = 0.2, x_store;
/*Check for division by zero and guess X=Zeros*/
for(i=0;i<n;i++){
x[i] = 0;
if(fabs(A[i*n + i]) < ZERO){
//exit if division by zero occurs
printf("Division by zero occurs. Preconditioning A matrix may be required.");
exit(EXIT_FAILURE);
}
}
/*Perform Gauss-Seidel Iteration*/
while( (delta>TOL) && (k<MAX_ITER) ){
for(i = 0; i < n; i++){
x_store = x[i];
sum = 0;
/*Sum for j<i*/
for(j = 0;(j < i); j++){
sum += A[i*n +j]*x[j];
}
/*Sum for i>j*/
for((j=i+1);j<n;j++){
sum += A[i*n +j]*x[j];
}
//Determine X value for current iteration
x[i] = (b[i]- sum)/A[i*n + i];
/*Find the residual difference using L1-norm*/
if((k>0) && (delta>((fabs(x[i] - x_store)/fabs(x[i]))))){
delta = fabs(x[i] - x_store)/fabs(x[i]);
}
}
k++;
}
/*Print Number of iterations*/
printf("\nNumber of iterations: %d using a tolerance of %f \n",k,TOL);
}
void position_solve(int n,int k,double X[], double x[],double order[])
{
int j, position;
double length = 0;
for (j = 0; j < n; j++) {
//printf("%f ", X[j]);
position = (int)(order[k*n +j]);
length += X[j] + x[position];
printf("Bungee Jumper %i: %lf meters\n",position,length);
/*Reset X vector to zero*/
X[j] = 0;
printf("\n");
}
}
void inverse(int n, double A[],double X[],double b[])
{
int i,j;
double *Inv_A;
ALLOCATE(Inv_A, double, n * n);
for(i=0;i<n;i++){
for(j=0;j<n;j++){
if(i==j){
b[i]=1;
}
else{
b[i]=0;
}
}
iter_solve(n,A,b,X);
for(j=0;j<n;j++){
Inv_A[i*n +j] = X[j];
}
}
printf("\nInverse A = [\n");
for(i=0;i<n;i++){
for(j=0;j<n;j++){
printf(" %lf ",A[i*n +j]);
}
printf("\n");
}
printf(" ]\n");
FREE(Inv_A);
}
void swap(double *p1,double *p2)
{ double temp;
temp = *p1;
*p1 = *p2;
*p2 = temp;
}
int noofpermutations(int n)
{ int permutations=1,i;
for(i=1;i<=n;i++)
permutations=permutations*i;
return permutations;
}
void next(int n,double a[])
{ int i;
for(i=0;i<n;i++){
if(count < noofpermutations(n)){
a[(count+1)*n + i] = a[count*n +i];
}
}
count++;
}
void permute(int n, double a[])
{ int j;
while(count<noofpermutations(n)){
for(j=0;j<n-1;j++)
{ swap(&a[count*n + j],&a[(count*n) + (j+1)]);
next(n,a);
}
swap(&a[(count*n)],&a[(count*n) + 1]);
next(n,a);
for(j=n-1;j>0;j--)
{ swap(&a[(count*n)+ j],&a[(count*n) + (j-1)]);
next(n,a);
}
swap(&a[(count*n) + (n-1)],&a[(count*n) + (n-2)]);
next(n,a);
}
}
void permutation(int n,double a[])
{
permute(n,a);
count = 0;
allocate.h
/*
* allocate.h
*
* Dynamic memory allocation macros
*/
#ifndef _allocate_h_
#define _allocate_h_
#include <stdio.h>
#include <stdlib.h>
#define ALLOCATE(VAR,TYPE,SIZE) \
{ \
(VAR) = (TYPE *) calloc ((SIZE), sizeof(TYPE)); \
if ((VAR) == NULL) { \
fprintf (stderr, "ALLOCATE: Memory allocation failed (%s:%d) [%d]\n", __FILE__, __LINE__, (SIZE)); \
exit (EXIT_FAILURE); \
} \
}
#define FREE(VAR) \
{ \
free ((VAR)); \
(VAR) = NULL; \
}
#endif
/*
* iter.h
*
* Routine for solving square systems of linear equations with
* multiple right-hand sides AX=B using Gauss-Seidel iterative methods
*/
/* Zero tolerance for double precision */
#define ZERO 1.0E-12
/* Tolerance for iteration relative change */
#define TOL 0.01
/* Maximum number of iterations */
#define MAX_ITER 500
void iter_solve(int n, double A[], double b[], double x[]);
/*
* Iterative solver, x = (b - LU * xp) / D
* Input:
* n = size of matrix A
* A = factorised A matrix, (nxn) stored by row
* b = right-hand side vector, (nx1)
* Output:
* x = solution vector, (nx1)
* Failure scenarios:
* Division by "zero"
*/
When his error occurs in the debugger, it should tell you where you are in the program that it occurs - hopefully this will let you identify which memory location is being corrupted.
Note that address, restart the program in the debugger, set a breakpoint for after the allocations occurs, then set a data breakpoint on that memory location and run to see who's trashing it.
dlls may cause heap corruption if the runtime library for linking of your project differs from the library's