I am a Python developer for the most part, but recently I have needed to solve a few problems using C and, honestly, it makes me suffer.
func.c
#define _CRT_SECURE_NO_WARNINGS
#define M_PI 3.1415926535897932384626433832795028841971693993751058209
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include <math.h>
#include "Point.h"
bool point_on_line(struct Point p1, struct Point p2, struct Point point) {
double min_x = min(p1.x, p2.x);
double max_x = max(p1.x, p2.x);
double min_y = min(p1.y, p2.y);
double max_y = max(p1.y, p2.y);
if (p2.y - p1.y == 0) {
return point.y == p2.y && point.x >= min_x && point.x <= max_x && point.y >= min_y && point.y <= max_y;
}
if (p2.x - p1.x == 0) {
return point.x == p2.x && point.x <= max_x && point.x >= min_x && point.y >= min_y && point.y <= max_y;
}
double k = (p2.y - p1.y) / (p2.x - p1.x);
double b = (p2.x * p1.y - p1.x * p2.y) / (p2.x - p1.x);
return point.y == (k * point.x + b) && point.x >= min_x && point.x <= max_x && point.y >= min_y && point.y <= max_y;
}
double calculate_angle(struct Point p1, struct Point p2) {
double dot_product = p1.x * p2.x + p1.y * p2.y;
double lenp1 = sqrt(p1.x * p1.x + p1.y * p1.y);
double lenp2 = sqrt(p2.x * p2.x + p2.y * p2.y);
double orientation = p1.x * p2.y - p1.y * p2.x;
int sign;
if (orientation > 0) {
sign = 1;
}
else {
sign = -1;
}
return sign * acos(dot_product / (lenp1 * lenp2));
}
bool check_border(struct Point p, struct Point points[], int size) {
for (int i = 0; i < size - 1; i++) {
if (point_on_line(points[i], points[i + 1], p)) {
return true;
}
}
return false;
}
bool calc_angle_sum(struct Point p1, struct Point points[], int size) {
struct Point* vectors = malloc(size * sizeof(struct Point));
for (int i = 0; i < size; i++) {
struct Point temp = { points[i].x - p1.x,points[i].y - p1.y };
vectors[i] = temp;
}
double total_sum = 0;
for (int i = 0; i < size - 1; i++) {
total_sum += calculate_angle(vectors[i], vectors[i + 1]);
}
bool res = (fabs(total_sum - 2 * M_PI)) < 0.00005;
printf("TOTAL SUM %.100f\n", total_sum);
printf("DIFFERENCE SMALL %d\n", fabs(total_sum - 2 * M_PI) < 0.00005);
return fabs(total_sum - 2 * M_PI) < 0.00005;
//return res;
}
Source.c
#define _CRT_SECURE_NO_WARNINGS
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "Point.h"
int main() {
int length = 5;
struct Point p1 = { 1,2 };
struct Point p2 = { 5,0 };
struct Point p3 = { 7,4 };
struct Point p4 = { 5,6 };
struct Point p5 = { 2,5 };
struct Point p6 = { 1,2 };
struct Point points_test[6] = {p1,p2,p3,p4,p5,p6};
struct Point point_test = {7,3};
//bool result = calc_angle_sum(point, points, length + 1);
//printf("%s", result ? "true\n" : "false\n");
if (check_border(point_test, points_test, length + 1)) {
printf("BORDER");
return 0;
}
else if (calc_angle_sum(point_test, points_test, length + 1)) {
printf("INSIDE");
return 0;
}
else {
printf("OUTSIDE");
return 0;
}
}
Point.h
#pragma once
struct Point {
double x, y;
};
coordinates.txt
1 2 5 0 7 4 5 6 2 5
lap.txt (the first number is the number of rectangle vertices, the second and third - the coordinates of the point.
5 7 3
This algorithm determines whether a point is inside/outside/on an edge of a given polygon using the winding number method.
The point (7,3) (the second and third numbers inside lap.txt) lies outside the polygon so the correct answer is "OUTSIDE/FALSE". Nevertheless, the output differs depending on Debug/Release and the way I return from calc_angle_sum function.
When I return this way:
return fabs(total_sum - 2 * M_PI) < 0.00005;
I get inconsistent results depending on debug/release mode.
The following way, however, seems to work fine:
bool res = (fabs(total_sum - 2 * M_PI)) < 0.00005
return res
Below is the part inside Source.c that calls the method:
else if (calc_angle_sum(point, points, length + 1)) {
printf("INSIDE");
return 0;
}
There is something I cannot understand about how expressions are evaluated in C.
In Python, I am used to returning like return <some_expression> and expect it to get converted to True/False. In C, however, this doesn't seem to be true, or else there is some other error.
One obvious problem is that of implicit function declarations.
Neither
bool calc_angle_sum(struct Point p1, struct Point points[], int size)
and
bool check_border(struct Point p, struct Point points[], int size)
are not declared in the translation unit source.c. Therefore the compiler assumes that the functions are of type
int calc_angle_sum()
int check_border()
Were the return type of the functions int, they could be called compatibly in this manner - with these arguments. But because the actual return type of the functions is bool, the behaviour of the function calls is undefined.
C99 removed implicit function definitions. A compliant C99, C11, C17 compiler must complain about these function calls in your source.c.But the substandard MSVC compiler barely meets the long obsolete C89 specification...
Thus, try declaring
bool calc_angle_sum(struct Point p1, struct Point points[], int size);
bool check_border(struct Point p, struct Point points[], int size);
in Point.h.
Related
Currently on one of the cs50x problem sets 'Cash', which is a simple 'ask for how much change is owed, then calculate how many coins are required' task, so not here asking for a solution but, I don't understand why this won't work.
While it does ask for an input, when I type in a float such as 5.96, it simply hangs. No returns, no errors whatsoever. I have to force it shut. The other thing is the while loop doing the same when set to 0, which is the intended way of doing things in order to get the exact number of coins.
I know how inefficient this code is and there are simpler ways of doing things. I just wish to understand the whys in order to avoid making the same mistakes moving on. Thanks.
#include <stdio.h>
#include <cs50.h>
#include <math.h>
int main(void)
{
// changes and other containers
int p = 1;
int n = 5;
int d = 10;
int q = 25;
int x = 0;
float c;
// get how much change is owed in float
do
{
c = get_float("Change owed: ");
}
while (c < 0);
// int conversion to avoid imprecision
int a = round(c * 100);
// 1 because 0 spits out an unknown error
while (a >= 1)
{
// if the converted amount is bigger than a quarter
if (a >= q)
{
// x = number of coins, a = amount left
x = a / q;
a = a % q;
}
else if (a >= d)
{
x = x + a / d;
a = a - a % d;
}
else if (a >= n)
{
x = x + a / n;
a = a - a % n;
}
else
{
x = x + a / p;
a = a - a % p;
}
}
printf("%i\n", x);
printf("%i\n", a);
}
Thanks to WhozCraig, I figured out that my logic was at fault.
#include <stdio.h>
#include <cs50.h>
#include <math.h>
int main(void)
{
// changes and other containers
int p = 1;
int n = 5;
int d = 10;
int q = 25;
int x = 0;
float c;
// get how much change is owed in float
do
{
c = get_float("Change owed: ");
}
while (c < 0);
// int conversion to avoid imprecision
int a = round(c * 100);
// 1 because 0 spits out an unknown error
while (a >= 1)
{
// if the converted amount is bigger than a quarter
if (a >= q)
{
// x = number of coins, a = amount left
x = a / q;
a = a % q;
}
else if (a >= d)
{
x = x + a / d;
a = a % d;
}
else if (a >= n)
{
x = x + a / n;
a = a % n;
}
else
{
x = x + a / p;
a = a % p;
}
}
printf("%i\n", x);
printf("%i\n", a);
}
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 2 years ago.
Improve this question
I have to develop these 4 functions:
double distance (const point_t * a, const point_t * b)
double perimeter (const polygon_t * poly)
polygon_t create_triangle (point_t p0, double base, double height)
polygon_t create_square (point_t p0, double side)
The rest of the body of the program was already defined, but I can't figure out how to develop the last two functions, I would need someone to point me in the correct way.
My idea was to initialize the vector to then be able to make the square and the triangle from this but I have a difficulty in developing the function.
Can you help me?
P.S. I leave you below the delivery of the exercise and what I wrote myself:
"The program represents polygons of any number of sides using dynamic arrays of points. Triangles and squares, as notable polygons, can be conveniently constructed using the create_triangle() and create_square() shortcuts.
To construct other polygons it is necessary to manually populate the struct polygon_t through the appropriate assignments.
The main () constructs a triangle and a square and calculates the perimeter by calling the perimeter () function. The types polygon_t and point_t and the print_polygon () function are already implemented, they are located at the top of the source and are not editable.
Implement the following functions so that main() compiles and the program is complete:
the function polygon_t create_triangle (point_t p0, double base, double height) so that it returns by value a structure of type polygon_t suitably populated with the points that form an isosceles triangle having point of origin (bottom left point) in p0, base base length and height length height;
the function polygon_t create_square (point_t p0, double side) so that it returns by value a structure of the polygon_t type suitably populated with the points that form a square having a point of origin (bottom left point) in p0, and side length side ;
the function double perimeter (const polygon_t * poly) so that it calculates the perimeter of the polygon passed as an argument: use the distance() function between all the pairs of contiguous points and calculate the sum of the sides;
do not make assumptions about the number of sides: the data structure can represent any polygons;
the function double distance (const point_t * a, const point_t * b) which calculates the Euclidean distance between the two data points.
Example: the following program constructs a square with side 2 and a triangle with base 1 and height 0.86602; then calculate the perimeter of both."
#include <assert.h>
#include <ctype.h>
#include <limits.h>
#include <math.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>
char* readline();
char* ltrim(char*);
char* rtrim(char*);
double parse_double(char*);
typedef struct {
double x, y;
} point_t;
typedef struct {
size_t len;
point_t* points;
} polygon_t;
void print_polygon(const polygon_t* poly) {
size_t i;
printf("polygon_t(%ld)[", poly->len);
for (i = 0; i < poly->len; ++i) {
printf("(%g, %g) ", poly->points[i].x, poly->points[i].y);
}
printf("\b]");
}
/* da implementare */
double distance(const point_t* a, const point_t* b) {
float dist;
point_t* x = (point_t*) a;
point_t* y = (point_t*) b;
dist= sqrt((a->x - b->x) + (a->y - b->y));
return dist;
}
/* da implementare: deve usare distance() */
double perimeter(const polygon_t* poly) {
float per_tr= distance(poly->points, poly->points) + distance(poly->points, poly->points) +
distance(poly->points, poly->points);
float per_sq= distance(poly->points, poly->points) * 4;
return per_sq && per_tr;
}
/* da implementare */
polygon_t create_triangle(point_t p0, double base, double height) {
size_t i;
point_t p2;
polygon_t p1;
for (i = 0; i < p1.len; ++i)
p1.points[i].x= 0;
//base= distance(p1.points, p1.points);
//height= sqrt(pow(distance(p1.points, p1.points),2) - (pow(base,2)/4.0)) ;
p1.len[p1.points].x= 0;
return p1;
}
/* da implementare */
polygon_t create_square(point_t p0, double side) {
polygon_t p2;
size_t i;
p0.x = 0;
p0.y = 0;
for (i = 0; i < p2.len; ++i)
p2.points[i].x= 0;
}
p2.len[p2.points]= p2.points[side * 4,0];
// side= distance(p2.points, p2.points);
return p2;
}
int main()
{
FILE* fptr = fopen(getenv("OUTPUT_PATH"), "w");
double x = parse_double(ltrim(rtrim(readline())));
double y = parse_double(ltrim(rtrim(readline())));
double l = parse_double(ltrim(rtrim(readline())));
double b = parse_double(ltrim(rtrim(readline())));
double h = parse_double(ltrim(rtrim(readline())));
point_t origin;
polygon_t sq;
polygon_t tr;
origin.x = x; /* input riga #1 */
origin.y = y; /* input riga #2 */
sq = create_square(origin, l); /* input riga #3 */
tr = create_triangle(origin, b, h); /* input riga #4, #5 */
double p1 = perimeter(&sq);
double p2 = perimeter(&tr);
fprintf(fptr, "%.2f\n", p1); /* output riga #1 */
fprintf(fptr, "%.2f\n", p2); /* output riga #2 */
fclose(fptr);
return 0;
}
char* readline() {
size_t alloc_length = 1024;
size_t data_length = 0;
char* data = malloc(alloc_length);
while (true) {
char* cursor = data + data_length;
char* line = fgets(cursor, alloc_length - data_length, stdin);
if (!line) {
break;
}
data_length += strlen(cursor);
if (data_length < alloc_length - 1 || data[data_length - 1] == '\n') {
break;
}
alloc_length <<= 1;
data = realloc(data, alloc_length);
if (!data) {
data = '\0';
break;
}
}
if (data[data_length - 1] == '\n') {
data[data_length - 1] = '\0';
data = realloc(data, data_length);
if (!data) {
data = '\0';
}
} else {
data = realloc(data, data_length + 1);
if (!data) {
data = '\0';
} else {
data[data_length] = '\0';
}
}
return data;
}
char* ltrim(char* str) {
if (!str) {
return '\0';
}
if (!*str) {
return str;
}
while (*str != '\0' && isspace(*str)) {
str++;
}
return str;
}
char* rtrim(char* str) {
if (!str) {
return '\0';
}
if (!*str) {
return str;
}
char* end = str + strlen(str) - 1;
while (end >= str && isspace(*end)) {
end--;
}
*(end + 1) = '\0';
return str;
}
double parse_double(char* str) {
char* endptr;
double value = strtod(str, &endptr);
if (endptr == str || *endptr != '\0') {
exit(EXIT_FAILURE);
}
return value;
}
First need to fix distance:
#define pow2(a) ((a) * (a))
/* da implementare */
double distance(const point_t* a, const point_t* b) {
return sqrt(pow2(a->x - b->x) + pow2(a->y - b->y));
}
For perimeter, you need distance between all points and between last and first:
/* da implementare: deve usare distance() */
double perimeter(const polygon_t* poly) {
double res = 0;
for (int i = 0; i < poly->len - 1; i++) {
res += distance(&poly->points[i], &poly->points[i+1]);
}
res += distance(&poly->points[poly->len - 1], &poly->points[0]);
return res;
}
Then you need to malloc points array to store some point_t
For triangle:
|\
| \
h| \
|___\
p0 base
/* da implementare */
polygon_t create_triangle(point_t p0, double base, double height) {
polygon_t p;
p.len = 3;
p.points = malloc(3 * sizeof(point_t));
p.points[0] = p0;
p.points[1].x = p0.x + base;
p.points[1].y = p0.y;
p.points[2].x = p0.x;
p.points[2].y = p0.y + height;
return p;
}
For square
+------+
| |
| |
+------+
p0
/* da implementare */
polygon_t create_square(point_t p0, double side) {
polygon_t p;
p.len = 4;
p.points = malloc(4 * sizeof(point_t));
p.points[0] = p0;
p.points[1].x = p0.x;
p.points[1].y = p0.y + side;
p.points[2].x = p0.x + side;
p.points[2].y = p0.y + side;
p.points[3].x = p0.x + side;
p.points[3].y = p0.y;
return p;
}
You need to free p.points
Incorrect algorithms aside, the syntax of your implementation will not compile. All of the issues below can be identified in your compile output if it is set to show all warnings. Regardless of that, some of the mistakes result in errors, and failure to compile.
Issue 1 - uninitialized variables:
size_t i;
point_t p2;
polygon_t p1;
for (i = 0; i < p1.len; ++i)
^^^^^^ uninitialized
p1.len is not initialized at time of first use. It can be any value at run-time possibly invoking undefined behavior
And there are more potentially uninitialized variables :
Build Status (so.prj - Debug)
s0_15.c - 9 warnings
60, 20 warning: variable 'p1.len' may be ***uninitialized***when used here
57, 4 note: variable 'p1' is declared here
61, 7 warning: variable 'p1.points' may be ***uninitialized***when used here
57, 4 note: variable 'p1' is declared here
64, 14 warning: variable 'p1.points' may be ***uninitialized***when used here
57, 4 note: variable 'p1' is declared here
77, 21 warning: variable 'p2.len' may be ***uninitialized***when used here
72, 5 note: variable 'p2' is declared here
79, 8 warning: variable 'p2.points' may be ***uninitialized***when used here
72, 5 note: variable 'p2' is declared here
83, 24 warning: variable 'p2' may be ******uninitialized****** when used here
72, 5 note: variable 'p2' is declared here
Note: actual locations will vary in your output.
Issue 2 - missing curly brace and out of scope object:
polygon_t create_square(point_t p0, double side) {
polygon_t p2;//has block scope!
size_t i;
p0.x = 0;
p0.y = 0;
for (i = 0; i < p2.len; ++i)
p2.points[i].x= 0;
}
p2.len[p2.points]= p2.points[side * 4,0];
p2 is not defined here, only within {...} above.
It is because this statement:
for (i = 0; i < p2.len; ++i)
p2.points[i].x= 0;
}
Is missing a opening curly brace {
for (i = 0; i < p2.len; ++i)
{//add this curly
p2.points[i].x= 0;
}
I'm having trouble calculating integrals for the centre of mass of a torus, which should return (2.4076, 0.16210, 0.0).
The program works for an estimation of pi/4 however I think there is an issue when I try to overwrite existing points using the setRandomDomain() function.
Here is my code:
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#define DIM 1000000
double random_double() {
static const int a = 16807;
static const int c = 0;
static const long long m = 2147483647;
static long long seed = 1;
seed = (a * seed + c) % m;
return ((double) seed) / m;
}
typedef struct Domain_t {
double *x;
double *y;
double *z;
} Domain;
void constructDomain(Domain (**p_domain)) {
*p_domain = malloc(sizeof(Domain));
if(p_domain == NULL) {
printf("ERROR: Memory allocation failed\n");
}
(*p_domain)->x = malloc(DIM * sizeof(double));
if ((*p_domain)->x == NULL) {
printf("ERROR: Memory allocation failed\n");
}
(*p_domain)->y = malloc(DIM * sizeof(double));
if ((*p_domain)->y == NULL) {
printf("ERROR: Memory allocation failed\n");
}
(*p_domain)->z = malloc(DIM * sizeof(double));
if((*p_domain)->z == NULL) {
printf("ERROR: Memory allocation failed\n");
}
}
void delDomain (Domain (**p_domain)) {
if (p_domain != NULL) {
free ((*p_domain)->z);
free ((*p_domain)->y);
free ((*p_domain)->x);
free (*p_domain);
}
}
double radiusFunc(double point_x, double point_y) {
return sqrt(pow(point_x,2)+pow(point_y,2));
}
double G(double point_x, double point_y, double point_z, int R) {
return pow(point_z,2)+pow(radiusFunc(point_x,point_y)-(double)R,2);
}
typedef struct Volume_t {
int R;
int r;
int lower_x;
int upper_x;
int lower_y;
int upper_y;
int lower_z;
int upper_z;
int V;
} Volume;
void setVolume(Volume (*p_volume), int R, int r, int x1, int x2, int y1, int y2, int z1, int z2) {
p_volume->R = R;
p_volume->r = r;
p_volume->lower_x = x1;
p_volume->upper_x = x2;
p_volume->lower_y = y1;
p_volume->upper_y = y2;
p_volume->lower_z = z1;
p_volume->upper_z = z2;
if(z1 == 0 && z2 == 0)
p_volume->V = (x2-x1)*(y2-y1);
else if(y1 == 0 && y2 == 0)
p_volume->V = (x2-x1)*(z2-z1);
else if(x1 == 0 && x2 == 0)
p_volume->V = (y2-y1)*(z2-z1);
else
p_volume->V = (x2-x1)*(y2-y1)*(z2-z1);
}
void setInitialDomain(Domain (**p_domain)) {
int i;
for(i=0;i<DIM;i++) {
(*p_domain)->x[i] = random_double();
(*p_domain)->y[i] = random_double();
(*p_domain)->z[i] = random_double();
}
}
void setRandomDomain(Domain (*p_domain), Domain (**p_new_domain), Volume (*p_volume)) {
int i;
for(i=0;i<DIM;i++) {
(*p_new_domain)->x[i] = p_domain->x[i]*(double)(p_volume->upper_x - p_volume->lower_x) + (double)p_volume->lower_x;
(*p_new_domain)->y[i] = p_domain->y[i]*(double)(p_volume->upper_y - p_volume->lower_y) + (double)p_volume->lower_y;
(*p_new_domain)->z[i] = p_domain->z[i]*(double)(p_volume->upper_z - p_volume->lower_z) + (double)p_volume->lower_z;
}
}
double setIntegrand(Domain (*p_domain), char c) {
double *p_x = p_domain->x;
double *p_y = p_domain->y;
double *p_z = p_domain->z;
if(c=='x')
return *p_x;
else if(c=='y')
return *p_y;
else if(c=='z')
return *p_z;
else
return 1.;
}
double calculateIntegral(Domain (*p_domain), Volume (*p_volume), char c) {
int i;
double F = 0.;
for(i=0;i<DIM;i++) {
if(G(p_domain->x[i], p_domain->y[i], p_domain->z[i], p_volume->R)<=(double)p_volume->r) {
F += setIntegrand(p_domain, c);
}
}
return F*(double)p_volume->V/(double)DIM;
}
int main() {
Domain *p_initial_domain;
Domain *p_random_domain;
constructDomain(&p_initial_domain);
printf("Point 1: successful\n");
constructDomain(&p_random_domain);
printf("Point 2: successful\n");
setInitialDomain(&p_initial_domain);
Volume circle, *p_circle;
p_circle = &circle;
setVolume(p_circle,0,1,0,1,0,1,0,0);
setRandomDomain(p_initial_domain, &p_random_domain, p_circle);
printf("PI/4 is approximately %f\n", calculateIntegral(p_random_domain, p_circle, 'p'));
Volume torus, *p_torus;
p_torus = &torus;
setVolume(p_torus,3,1,1,4,-3,4,-1,1);
setRandomDomain(p_initial_domain, &p_random_domain, p_torus);
double M = calculateIntegral(p_random_domain, p_torus, 'p');
double X = calculateIntegral(p_random_domain, p_torus, 'x');
double Y = calculateIntegral(p_random_domain, p_torus, 'y');
double Z = calculateIntegral(p_random_domain, p_torus, 'z');
printf("rho integral is approximately %f\n", M);
printf("x integral is approximately %f\n", X);
printf("y integral is approximately %f\n", Y);
printf("z integral is approximately %f\n", Z);
printf("Centre of mass is approximately (%f, %f, %f)\n", X/M, Y/M, Z/M);
delDomain(&p_initial_domain);
delDomain(&p_random_domain);
// return pointers??
// array of structs??
return 0;
}
Currently outputs:
PI/4 is approximately 0.785436
rho integral is approximately 22.101282
x integral is approximately 22.101801
y integral is approximately -45.953770
z integral is approximately 11.298411
Centre of mass is approximately (1.000023, -2.079235, 0.511211)
Any ideas how to solve this?
Also, please can someone explain how I would use functions returning pointers and why it may be better to create an array of structs instead of a struct of arrays?
Your problem is that you call setIntegrand in a loop over all points, but you always take the first point:
double *p_x = p_domain->x;
// ...
return *p_x;
This returns the first double in your array. Remember that *x is equivalent to x[0]. Pass the index to the function:
double setIntegrand(Domain (*p_domain), char c, int i)
{
if (c == 'x') return p_domain->x[i];
if (c == 'y') return p_domain->y[i];
if (c == 'z') return p_domain->z[i];
return 1.;
}
and then call it with that index.
for (i = 0; i < DIM; i++) {
if (G(...) <= p_volume->r) {
F += setIntegrand(p_domain, c, i);
}
}
As to your additional questions: Using an array of structs keeps the things that go together (here, the three coordinates of the points) nearby. You can also easily just pass a point to a function with a single argument.
If you have a constructor, that is a function that creates a new thing by allocating on the heap and initialising the new memory, returning a pointer is a useful idiom. (I find it more idiomatic than passing a point to a pointer, but whoever designed to fopen_s function didn't think so.)
Let's put both changes together:
typedef struct Point Point;
typedef struct Domain Domain;
struct Point {
double x;
double y;
double z;
};
struct Domain {
size_t length;
Point *point;
};
Domain *constructDomain(size_t length)
{
Domain *dom = malloc(sizeof(*dom));
if (dom) {
dom->length = length;
dom->point = calloc(length, sizeof(*dom->point));
// check success
}
return dom;
}
First note, when possible it generally best to reduce the number of heap allocations and leave variables on the stack, less room for error. I'd say if you want 1M x 3 x sizeof(double) bytes, arround 24M, it is best to dynamically allocate it on the heap. We can leave the structure that holds these on the stack.
Another thing is when you create a variable, you don't need to create another variable to point to it, just use the original variable.
Last note is commenting, I personally comment every line of code but that may be to much here. I find it helpful to write out what exactly you are trying to do with each line of code to help find bugs.
You don't need to return pointers anywhere here i don't think, perhaps when you were passing pointer to a pointer it would have been better to just return a pointer. An array of structures is another way of doing it, it means only one malloc and one free but alignment could cause extra memory to be used (padding) which could be considerable when using 1M points, there likely won't be any padding here tho because you are using double floating points. I think your arrays are fine.
I made some changes with the way you are using pointers, this likely won't solve your problem but it at least cleans things up a bit.
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#define DIM 1000000
typedef struct Domain_t {
double *x;
double *y;
double *z;
} Domain;
typedef struct Volume_t {
int R;
int r;
int lower_x;
int upper_x;
int lower_y;
int upper_y;
int lower_z;
int upper_z;
int V;
} Volume;
double random_double() {
static const int a = 16807;
static const int c = 0;
static const long long m = 2147483647;
static long long seed = 1;
seed = (a * seed + c) % m;
return ((double) seed) / m;
}
void constructDomain(Domain *p_domain) {
p_domain->x = malloc(DIM * sizeof(double));
if (p_domain->x == NULL) {
printf("ERROR: Memory allocation failed\n");
}
p_domain->y = malloc(DIM * sizeof(double));
if (p_domain->y == NULL) {
printf("ERROR: Memory allocation failed\n");
}
p_domain->z = malloc(DIM * sizeof(double));
if(p_domain->z == NULL) {
printf("ERROR: Memory allocation failed\n");
}
}
void delDomain (Domain *p_domain) {
if (p_domain != NULL) {
free (p_domain->z);
free (p_domain->y);
free (p_domain->x);
}
}
double radiusFunc(double point_x, double point_y) {
return sqrt(pow(point_x,2)+pow(point_y,2));
}
double G(double point_x, double point_y, double point_z, int R) {
return pow(point_z,2)+pow(radiusFunc(point_x,point_y)-(double)R,2);
}
void setVolume(Volume *p_volume, int R, int r, int x1, int x2, int y1, int y2, int z1, int z2) {
p_volume->R = R;
p_volume->r = r;
p_volume->lower_x = x1;
p_volume->upper_x = x2;
p_volume->lower_y = y1;
p_volume->upper_y = y2;
p_volume->lower_z = z1;
p_volume->upper_z = z2;
if(z1 == 0 && z2 == 0)
p_volume->V = (x2-x1)*(y2-y1);
else if(y1 == 0 && y2 == 0)
p_volume->V = (x2-x1)*(z2-z1);
else if(x1 == 0 && x2 == 0)
p_volume->V = (y2-y1)*(z2-z1);
else
p_volume->V = (x2-x1)*(y2-y1)*(z2-z1);
}
void setInitialDomain(Domain *p_domain) {
int i;
for(i=0;i<DIM;i++) {
p_domain->x[i] = random_double();
p_domain->y[i] = random_double();
p_domain->z[i] = random_double();
}
}
void setRandomDomain(Domain *p_domain, Domain *p_new_domain, Volume *p_volume) {
int i;
for(i=0;i<DIM;i++) {
p_new_domain->x[i] = p_domain->x[i] * (double) (p_volume->upper_x - p_volume->lower_x) + (double) p_volume->lower_x;
p_new_domain->y[i] = p_domain->y[i] * (double) (p_volume->upper_y - p_volume->lower_y) + (double) p_volume->lower_y;
p_new_domain->z[i] = p_domain->z[i] * (double) (p_volume->upper_z - p_volume->lower_z) + (double) p_volume->lower_z;
}
}
double setIntegrand(Domain (*p_domain), char c) {
double *p_x = p_domain->x;
double *p_y = p_domain->y;
double *p_z = p_domain->z;
if(c=='x')
return *p_x;
else if(c=='y')
return *p_y;
else if(c=='z')
return *p_z;
else
return 1.0;
}
double calculateIntegral(Domain *p_domain, Volume *p_volume, char c) {
int i;
double F = 0.0;
for(i=0;i<DIM;i++) {
if(G(p_domain->x[i], p_domain->y[i], p_domain->z[i], p_volume->R)<=(double)p_volume->r) {
F += setIntegrand(p_domain, c);
}
}
return F * (double) p_volume->V / (double)DIM;
}
int main() {
Domain initial_domain;
Domain random_domain;
Volume circle;
Volume torus;
/* memory allocation */
constructDomain(&initial_domain);
constructDomain(&random_domain);
/* initialization */
setInitialDomain(&initial_domain);
/* volume */
setVolume(&circle,0,1,0,1,0,1,0,0);
setRandomDomain(&initial_domain, &random_domain, &circle);
/* integral */
printf("PI/4 is approximately %f\n", calculateIntegral(&random_domain, &circle, 'p'));
setVolume(&torus,3,1,1,4,-3,4,-1,1);
setRandomDomain(&initial_domain, &random_domain, &torus);
double M = calculateIntegral(&random_domain, &torus, 'p');
double X = calculateIntegral(&random_domain, &torus, 'x');
double Y = calculateIntegral(&random_domain, &torus, 'y');
double Z = calculateIntegral(&random_domain, &torus, 'z');
printf("rho integral is approximately %f\n", M);
printf("x integral is approximately %f\n", X);
printf("y integral is approximately %f\n", Y);
printf("z integral is approximately %f\n", Z);
printf("Centre of mass is approximately (%f, %f, %f)\n", X/M, Y/M, Z/M);
delDomain(&initial_domain);
delDomain(&random_domain);
return 0;
}
I need to find closest pair of four points C program. This code for three points. I need this solution for four point.
I tried this. This solution for three input.
When I entering the three points then I will get the closest but I need the closest point of four points.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
struct Point
{
int x, y ;
};
double getDistanceAB(struct Point a, struct Point b)
{
double distanceAB;
distanceAB = sqrt((a.x - b.x) * (a.x - b.x) + (a.y-b.y) *(a.y-b.y));
return distanceAB;
}
double getDistanceBC(struct Point b, struct Point c)
{
double distanceBC;
distanceBC = sqrt((b.x - c.x) * (b.x - c.x) + (b.y-c.y) *(b.y-c.y));
return distanceBC;
}
double getDistanceAC(struct Point a, struct Point c)
{
double distanceAC;
distanceAC = sqrt((a.x - c.x) * (a.x - c.x) + (a.y-c.y) *(a.y-c.y));
return distanceAC;
}
int main()
{
struct Point a, b, c;
printf("Enter coordinate of points a: ");
scanf("%d %d", &a.x, &a.y);
printf("Enter coordinate of points b: ");
scanf("%d %d", &b.x, &b.y);
printf("Enter coordinate of points c: ");
scanf("%d %d", &c.x, &c.y);
if((getDistanceAB(a,b))>(getDistanceBC(b,c)) && (getDistanceAB(a,b))>(getDistanceBC(a,c)))
{
printf("Point A and B are closest.");
}
else if((getDistanceBC(b,c))>(getDistanceAC(a,c)) && (getDistanceBC(b,c))>(getDistanceAC(a,b)))
{
printf("Point B and C are closest.");
}
else if((getDistanceBC(a,c))>(getDistanceAC(a,b)) && (getDistanceBC(a,c))>(getDistanceAC(b,c)))
{
printf("Point A and C are closest.");
}
else
{
printf("All point are same.");
}
}
First, change this:
double getDistanceAB(struct Point a, struct Point b)
{
double distanceAB;
distanceAB = sqrt((a.x - b.x) * (a.x - b.x) + (a.y-b.y) *(a.y-b.y));
return distanceAB;
}
double getDistanceBC(struct Point b, struct Point c)
{
double distanceBC;
distanceBC = sqrt((b.x - c.x) * (b.x - c.x) + (b.y-c.y) *(b.y-c.y));
return distanceBC;
}
double getDistanceAC(struct Point a, struct Point c)
{
double distanceAC;
distanceAC = sqrt((a.x - c.x) * (a.x - c.x) + (a.y-c.y) *(a.y-c.y));
return distanceAC;
}
to just this:
double getDistance(struct Point a, struct Point b)
{
double distance;
distance = sqrt((a.x - b.x) * (a.x - b.x) + (a.y-b.y) * (a.y-b.y));
return distance;
}
One of the main points of functions is that you don't have to repeat code.
Now all you have to do is create your four points by adding one more scan for the fourth point and add that to the decision tree.
Keep in mind this for the decision tree that you made... If you check if point 'a' is not the closest using the same logic you used in your original post, you don't have to compare point 'a' again.
I would reduce the number of functions to just double getDistance(struct Point p, struct Point o)
and keep your points in a list so you can allow the program to run through the points dynamically instead of programming each condition.
Once you have your points in a list, you can run a loop that checks each pair in the list for their distance and check that against the currently shortest distance; and if the distance of the pair checked is closer you change the currently shortest distance to the checked pair and which pair of points have that distance.
That way you can expand it to work for arbitrarily large number of points.
I'm not used to the syntax of C, but for the checking of points in the list you'll need a double for loop, in which the first goes through each point in the list, and the second checks the distance from/to that first point to all points later in the list.
for i = 0, i++, length(listOfPoints) {
for j = i+1, j++, length(listOfPoints) {
getDistance(listOfPoints[i], listOfPoints[j]
}
}
Hope this helps some.
This is how I'd solve that,
#include <stdio.h>
typedef struct
{
int x;
int y;
} Point;
int square(int x) { return x * x; }
int distanceSq(Point *a, Point *b)
{
return square(a->x - b->x) + square(a->y - b->y);
}
int main(int argc, char const *argv[])
{
int n = 4;
Point a[4];
for (int i = 0; i < n; i++)
{
printf("Enter Point %d <as x y>: ", i + 1);
scanf("%d %d", &a[i].x, &a[i].y);
}
int distance = __INT_MAX__;
int p1 = -1, p2 = -1;
for (int i = 0; i < n - 1; i++)
for (int j = i + 1; j < n; j++)
{
int current = distanceSq(&a[i], &a[j]);
if (current < distance)
{
p1 = i;
p2 = j;
distance = current;
}
}
printf("The closest points are [%d %d] and [%d %d]", a[p1].x, a[p1].y, a[p2].x, a[p2].y);
return 0;
}
Note:
This can be extended for n number of points
Gives us the first pair closest points
we do not need to take square roots since if the square is large the square root will be proportionally large( in case of a large number(n) of points it might save computation time)
Here you go, a solution for any number of points.
Just change MAX_POINTS to anything you might need.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <stdbool.h>
#define MAX_POINTS (4U)
struct Point
{
int x;
int y;
};
struct PointPair
{
struct Point a;
struct Point b;
};
double getDistance(const struct PointPair pair)
{
return sqrt((pair.a.x - pair.b.x) * (pair.a.x - pair.b.x) +
(pair.a.y - pair.b.y) * (pair.a.y - pair.b.y));
}
void readPoints(struct Point points[const])
{
for (unsigned i = 0; i < MAX_POINTS; i++)
{
printf("Enter coordinate of point %u: ", i);
scanf("%d %d", &(points[i].x), &(points[i].y));
}
}
bool checkForShorterDistance(const struct PointPair pair, double *const p_minDistance)
{
double tempDistance = getDistance(pair);
if (tempDistance < *p_minDistance)
{
*p_minDistance = tempDistance;
return true;
}
return false;
}
struct PointPair getClosestPair(const struct Point points[const])
{
struct PointPair result =
{
.a = points[0],
.b = points[1]
};
double minDistance = getDistance(result);
struct PointPair tempPair;
unsigned i, j;
for (i = 0; i < MAX_POINTS; i++)
{
tempPair.a = points[i];
for (j = 0; j < MAX_POINTS; j++)
{
if (i == j)
{
continue;
}
tempPair.b = points[j];
if (checkForShorterDistance(tempPair, &minDistance))
{
result = tempPair;
}
}
}
return result;
}
int main(void)
{
struct Point points[MAX_POINTS];
readPoints(points);
struct PointPair pair = getClosestPair(points);
printf("Closest pair is (%d, %d) and (%d, %d)\n",
pair.a.x,
pair.a.y,
pair.b.x,
pair.b.y);
return 0;
}
This question already exists:
Closed 11 years ago.
Possible Duplicate:
Is this C-program correct(pointers and arrays)?
My program crashes when I free the mallocated array in the end. Why?
Also, I'm not 100% on how to allocate it in the first place. The program works as intended though, ecept for the crash when I free the pointer.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
/* Approximates a solution to a differential equation on the form:
y'(t) + ay(t) = x(t)
y(0) = b
*/
double* runge_kutta_2nd_order(double stepSize, double a, double b, double (*x) (double), double upto)
{
int resultSize = ((int) (upto / stepSize)) + 1;
double yt = b;
double time;
double k1,k2,ystar1,ystar2;
int index = 1;
double *results = (double*) malloc(resultSize * (sizeof(double)));
if(results == NULL)
exit(0);
results[0] = b;
for(time = 0; time <= upto; time += stepSize)
{
k1 = x(time) - a * yt;
ystar1 = yt + stepSize * k1;
k2 = x(time + stepSize) - a * ystar1;
ystar2 = yt + (k1 + k2) / 2 * stepSize;
yt = ystar2;
results[index] = ystar2;
index++;
}
return results;
}
void free_results(double *r)
{
free(r);
r = NULL;
}
double insignal(double t)
{
return exp(t/2)*(sin(5*t) - 10*cos(5*t));
}
int main(void)
{
int i;
double *res = runge_kutta_2nd_order(0.01,-1,0,&insignal,10);
printf("\nRunge Kutta 2nd order approximation of the differential equation:");
printf("\ny'(t) - y(t) = e^(t/2) * (sin(5t) - 10cos(5t))");
printf("\ny(0) = 0");
printf("\n0 <= t <= 10");
for(i=0; i<1001; i++){
printf("\ni = %lf => y = ", 0.01*i);
printf("%lf", res[i]);
}
printf("\n");
free_results(res);
return 0;
}
You have a heap overflow in runge_kutta_2nd_order. Carefully check the loop to ensure that index < resultSize always holds.