I'm converting C++ code to C for an exercise (we are just learning c++ now), and I am lost at this part.
First, the c++ code:
Point()
{
x = y = 0;
}
main()
{
const int N = 200;
Point *A = new Point[N], sum;
}
Here's my C version of it:
struct Point //constructor
{
int x;
int y;
} Point;
main()
{
int N = 200;
Point* A = malloc(N * sizeof(*Point[]));
}
That should give you an idea of what I'm trying to do. Questions:
Is sum in the C++ code the C++ sum function, or is it aPointstruct`?
For allocating the memory in C, I don't think my method works. Should I do a for loop where it mallocs each index of A[]? (A should be an array of Point structs).
Any assistance would be greatly appreciated.
EDIT: Got asked for the context of the code.
Here's the whole C++ program:
#include <iostream>
// a point on the integer grid
struct Point
{
// constructor
Point()
{
x = y = 0;
}
// add point componentwise
void add(const Point &p)
{
x += p.x;
y += p.y;
}
// print to standard output
void print() const
{
std::cout << "[" << x << "," << y << "]" << std::endl;
}
// data
int x, y;
};
int main()
{
const int N = 200;
Point *A = new Point[N], sum;
for (int i=0; i < N; ++i) {
sum.print();
A[i].x = i; A[i].y = -i;
sum.add(A[i]);
}
sum.print();
delete [] A;
}
Ultimately, I have to emulate that in C. Currently stuck at the question I asked: re: what does that line do. I have since figured out that I need to make a struct of Point called sum, and print that after running the add function on all its members.
In your C version:
struct Point //constructor
{
int x;
int y;
} Point;
should be:
typedef struct //constructor
{
int x;
int y;
} Point;
Because in your case, you defined a global variable named Point.
And, the C programming language has the const keyword as C++ as well, so you can do this in the C language:
const int N = 200;
And the C++ code:
Point *A = new Point[N], sum;
In C version, should be:
Point *A = malloc(N * sizeof(Point)), sum;
But in this version, the memory isn't initialized by zero.
You can use the calloc function instead of the malloc to allocate memory and initialize it with zero:
Point *A = calloc(N, sizeof(Point)), sum;
Then back to your question:
Is sum in the c++ code the c++ sum function, or is it a Point struct?
It is a Point type variable.
For allocating the memory in C, I don't think my method works. Should I do a for loop where it mallocs each index of A[]? (A should be an array of Point structs).
No, there's no necessary to write a for loop. The malloc function will do exactly what you want.
Is sum in the c++ code the c++ sum function, or is it a Point struct?
In your case, it is a Point struct.
Point *A = new Point[N], sum;
is equivalent to:
Point *A = new Point[N];
Point sum; //I have no idea why naming is sum
If you need Point* for sum, you should write it in the following way:
Point *A = new Point[N], *sum;
For allocating the memory in C, I don't think my method works
It does not work, syntax is wrong. Try:
EDIT: thanks to #mch, you should not use cast for malloc.
typedef struct Point Point;
Point* A = malloc(N * sizeof(Point));
Related
I dunno why I have segmentation error when I'm trying to set or get any element from created array!!
Here it is in line with A[0][0] = 1;
I'm using g++ 9.3.0. What do I do wrong?
#include <iostream>
#define SIMULATIONS 30
using namespace std;
void init_matrixes(int a_rows, int b_cols, int vec_len, double **A, double **B, double **C)
{
A = new double *[a_rows];
B = new double *[vec_len];
C = new double *[a_rows];
for (int i = 0; i < a_rows; i++)
{
A[i] = new double[vec_len];
C[i] = new double[b_cols];
}
for (int i = 0; i < vec_len; i++)
B[i] = new double[b_cols];
}
int main()
{
double s;
int t1, t2, a_rows, b_cols, vec_len;
for (auto v : {50, 100})
{
a_rows = v;
b_cols = v;
vec_len = v;
for (int i = 0; i < SIMULATIONS; i++)
{
double **A, **B, **C;
init_matrixes(a_rows, b_cols, vec_len, A, B, C);
A[0][0] = 1; // error here
}
std::cout << "size = " << v<< " time = " << s / SIMULATIONS << endl;
}
return 0;
}
TL;DR version
Use std::vector or a matrix class like the one described here. This will eliminate the need for special allocation and deallocation functions thanks to the magic of RAII.
What went wrong?
A pointer is just another variable, but one that can contain the location of another object. Like any other variable, the pointer will be will be passed by value into a function and copied by default. The object pointed at is passed by reference (by way of pointer), but the pointer itself is passed by value.
double **A defines A as a pointer to a pointer to a double that is a copy of the pointer provided by the caller.
A = new double *[a_rows];
updates the copy and the caller is none-the-wiser. As a result all of the memory allocated is leaked at the end of the function because the local A goes out of scope.
So How do I fix it?
Pass the pointers by reference.
void init_matrixes(int a_rows,
int b_cols,
int vec_len,
double ** & A,
double ** & B,
double ** & C)
A, B, and C, are passed by reference (references this time) and are no longer copies.
A = new double *[a_rows];
Updates the pointer provided by the caller, and the caller now has a pointer pointing to valid storage.
struct zone {
int a;
double b;
};
zone *abc() {
static zone r[10];
for (int i = 0; i < 10; i++) {
r[i].a = 2 * i;
[r[i].b=0.5*i;
cout << r[i].a << " " << r[i].b << endl;
}
return r;
}
int main() {
zone *PP;
zone P[10];
PP = abc();
for (int i = 0; i < 10; i++) {
P[i] = (PP + i);
cout << "work" << P[i].a << endl;
}
getch();
}
I need to return an array of structs that is formed in a function called by main. I managed to retrieve an array with a pointer, but with struct it doesn't work.
How do I return a struct array?
You are assigning a value of variable with a pointer:
P[i] = (PP + i);
To get a copy of internal value, you need access struct:
P[i] = PP[i];
Would be like this:
#include <iostream>
using namespace std;
struct zone {
int a;
double b;
};
zone *abc() {
static zone r[10];
for (int i = 0; i < 10; i++) {
r[i].a = 2 * i;
r[i].b=0.5*i;
cout << r[i].a << " " << r[i].b << endl;
}
return r;
}
int main() {
zone *PP;
zone P[10];
PP = abc();
for (int i = 0; i < 10; i++) {
P[i] = PP[i];
cout << "work" << P[i].a << endl;
}
}
Your struct contains just digits, however, if it contains strings or pointer, you will need make a deep copy.
Well fairly simple - by using another struct to encapsulate the returned array in order to get over 'C' language limitations.
struct zone {
int a;
double b;
};
struct zone_array_of_10 {
zone arr[10];
};
zone_array_of_10 abc() {
zone_array_of_10 r;
for (int i = 0; i < 10; i++) {
r.arr[i].a = 2 * i;
r.arr[i].b=0.5*i;
cout << r.arr[i].a << " " << r.arr[i].b << endl;
}
return r;
}
int main() {
zone_array_of_10 PP;
PP = abc();
for (int i = 0; i < 10; i++) {
cout << "work" << PP.arr[i].a << endl;
}
getch();
}
It's fact that in 'C' language arrays can't be passed by value. However structures can. So whenever you want to pass the actual content of some array without much hassle - just encapsulate it in a structure.
A cool feature of C++ is the use of references. The best part of references is that they allow you to pass data in an out of a function without copying the data (you are using the same data inside and pass back out). So if you make a function.
Another method is to use a pointer to a pointer. You can pass a pointer pointer or address of a pointer and malloc within the function.
structure* a;
funct(&a);
printf("%s\n", a[0].printfunction());
printf("%s\n", a[1].printfunction());
...
void funct(structure** a, int size){
*a = (structure*)malloc(sizeof(structure) * size);
(*a)[0] = ...
(*a)[1] = ..
(*a)[ size-1] = ...
}
You can access the array outside of the function. Just be sure to free/delete anything you call with malloc/new. The above code can use new I'm just better with c. You can easily pull the malloc outside of the function and just pass in a pointer to the array.
In C, a function can't take or return an array. This is annoying, and I've never heard a good reason given for it. Anyway, C++ fixed this a long time ago, but it never really caught on, for reasons that will become plain in a moment.
Obligatory "for anything larger than a toy application you should strongly reconsider using naked pointers and/or raw arrays!"
C++ introduced references. They are really just syntactic sugar around pointers, but aren't all variables just syntactic sugar around pointers? In C++, a function can take and/or return a reference to an array. Like so:
int takes (char (&arr)[10])
{
std::cout << sizeof(arr); // 10
}
int (&returns())[10]
{
return some_array; // Not a pointer!
}
int (&takes_and_returns (int (&arr)[10])) [10]
{
return arr;
}
Of course, I don't have to tell you that this is extremely ugly and difficult to read. Modern C++ to the rescue!
template <size_t n, typename T>
using array<n,t> = T[n];
int takes (array<10,int>& arr);
array<10,int>& returns();
array<10,int>& takes_and_returns (array<10,int>& arr);
Note, however, that due to the way new works, it is an ordeal to properly construct and then return a reference to a dynamic array. This is how I did it, but I'm not even sure if this is correct; there might lurk some UB:
int (&returns())[10]
{
int* x = new int[10];
return *(int(*)[10]) x;
}
Of course, we can tidy this up a bit:
using arr10 = int[10];
arr10& returns()
{
int* x = new int[10];
return *(arr10*) x;
}
And then, at the call site, you'd assign it to a reference like so:
int (&my_array)[10] = returns();
// doing stuff ...
delete[] &my_array;
As you can see, at the end of the day, getting all this to work correctly and to interoperate with existing features is a bit of an ordeal. If you need a function to take or return an array, this is how you do it. But for most purposes, it is better (easier, safer) to use standard library containers.
I keep getting the error message, exc_bad_access code=1 for my line
asize = *(***(y) + **(y + 1));
in the summation function. I dont quite understand what to do with this error, but i know that it is not a memory leak.
I am trying to get the values stored in the y pointer array, add them, and store it in the variable asize.
void allocArr (int **&x, int ***&y, int **&q, int ****&z)
{
x = new int *[2];
y = new int **(&*x);
q = &*x;
z = new int ***(&q);
}
void putArr(int **&x, int &size1, int &size2)
{
*(x) = *new int* [size1];
*(x + 1) = *new int* [size2];
}
void Input (int **&x, int *&arr, int &size1,int &size2, int a, int b)
{
cout << "Please enter 2 non-negative integer values: "<< endl;
checkVal(size1, a);
checkVal(size2, b);
putArr(x, size1, size2);
arr[0] = size1;
arr[1] = size2;
cout << x[0];
}
void summation(int ***&y, int *&arr)
{
int asize = 0;
asize = *(***(y) + **(y + 1));
**y[2] = *new int [asize];
*(arr + 2) = asize;
}
int main()
{
int size1, size2;
int a = 1, b = 2;
int** x;
int*** y;
int** q;
int**** z;
int *arr = new int [2];
allocArr(x, y, q, z);
Input(x, arr, size1, size2, a, b);
summation(y, arr);
display(z);
}
Thank you for the help. Im really struggling here...
Not sure how you got started with the code. The code can be simplified quite a bit to help you, and readers of your code, understand what's going on.
Function allocArr
The lines
y = new int **(&*x);
q = &*x;
can be
y = new int **(x); // &*x == x
q = x;
Function putArr
You have the function declaration as:
void putArr(int **&x, int &size1, int &size2)
It can be changed to:
void putArr(int **x, int size1, int size2)
without changing how you are using the variables.
Your code in the function seems strange. Did you mean for x[0] and x[1] to point to an array of size1 and size2 ints, respectively? If you did, the code would be:
x[0] = new int[size1];
x[1] = new int[size2];
If you don't mean the above, it's hard to figure out what you are trying to do with your code.
Function Input
You have the function declaration as:
void Input (int **&x, int *&arr, int &size1,int &size2, int a, int b)
It can be changed to:
void Input (int **x, int *arr, int &size1,int &size2, int a, int b)
without changing how you are using the variables.
You are calling a function checkVal, but your posted code doesn't have that function. It's not clear what that function is doing. You have the line
cout << "Please enter 2 non-negative integer values: "<< endl;
just before the calls to checkVal. Presumably, checkVal reads the input and stores them in size1 in the first call and size2 in the second call. It's not clear how the second argument to checkVal is used.
And then, you have the line:
cout << x[0];
It's not clear what you wish to accomplish from printing an int* to cout. Perhaps it was part of your debugging code. The line doesn't change anything else in the program. It's just strange to see it there.
Function summation
You have the function declaration as:
void summation(int ***&y, int *&arr)
It can be changed to:
void summation(int ***y, int *arr)
without changing how you are using the variables.
In this function, you have the expression:
asize = *(***(y) + **(y + 1));
What do you get when you evaluate ***(y)?
***(y) = **(*y) = **(x) = *(*x) = *(x[0]) = uninitialized value from the line:
x[0] = new int[size1];
You will get unpredictable behavior when you use an uninitialized value.
The second term of the line, **(y + 1) is the worse culprit.
You allocated memory for y as:
y = new int **(&*x);
It's a pointer to a single object of type int**, not an array. y+1 is not a valid pointer. Dereferencing (y+1) leads to undefined behavior. In your case, you are seeing exc_bad_access, which makes sense now since you are accessing memory that is out of bounds.
Since I don't know what you are trying to compute in that expression, it's hard for me to suggest something useful. I hope you have enough to take it from here.
I'm just a beginner in the learning stage.
I am supposed to arrange a struct of point (x,y,z) so that structure p[n] has the point with the greatest x stored in it. Is my method correct? If not, are there any simper methods to do this?
struct point
{
float x;
float y;
} p[1000];
void sortptx(struct point *t, int ctr);
int main()
{
int n = 100;
sortptx(&p, n);
return 0;
}
void sortptx(struct point *t, int ctr)
{
float temp;
int i;
for(i = 0; i < ctr-1; i++)
{
if (t[ctr]->x < t[i]->x)
{
temp = t[ctr]->x;
t[ctr]->x = t[i]->x;
t[i]->x = temp;
}
}
}
There are at least a few bugs here:
As mentioned in the comments, struct point *t is either a pointer to a single struct point, or an array of points. It is not a pointer to an array of pointers to struct point. So t[i]->x should be t[i].x.
If ctr is intended to be the length of an array of points, t[ctr] will run off the end of the array, and could access uninitialized memory. In that case, t[ctr-1] would be the last element of the array.
Rather than swapping entire points, you are just swapping the x coordinates.
From what I understand you don't want to sort it, but find point with maximum x and make sure it is stored at p[n-1].
struct point
{
float x;
float y;
} p[1000];
This is how it could look like:
void max(struct point *t, int ctr)
{
struct point temp;
int i;
for(i = 0; i < (ctr - 1); i++)
{
if (t[ctr - 1].x < t[i].x)
{
temp = t[ctr - 1];
t[ctr - 1] = t[i];
t[i] = temp;
}
}
}
This function takes struct point *t as an argument, which is pointer to first point just like p is. t[i] is struct point at index i (not pointer to struct point), so you use . instead of -> when you access its members. And since you are indexing from zero, last element of an array of size n has index n-1, which is place where the struct point with the highest x will be stored.
Example:
int main ()
{
for(int i = 0; i < 99; i++)
{
p[i].x = 1;
p[i].y = 3;
}
p[4].x = 7;
int n = 100;
max(p, n);
cout << p[n - 1].x;
return 0;
}
output: 7
int M=7;
int N=6;
int i=0;
int x=N*M;
int val3[x] = {};
for(int i=0;i<x;i++)
{
//some calculations
if (my condition)
{
//if this condition ok, change value of val[i]
}
cout << i << " " << val[i] << endl;
}
I want to initialize a zero array(val), I used above codes, but I got an error which says variable size object may not be initialized. is it not possible to initialize zero array? need your help....thanks
C++ does not include variable-length arrays; int val3[ x ] with x non-constant is a feature of C99. Not all C99 features are part of C++. Try using std::vector.
#include <vector>
// contains an array of length x, automatically filled with zeroes
std::vector< int > val3( x );
int val3[x] = {};
C++ doesn't allow arrays to be initialized with a variable that isn't a compile-time constant. Use a const int for all the variables (except i).
Btw, you don't use that first int i (outside the loop).
Alternatively to the std::vector suggested above, you could also do:
int M=7;
int N=6;
int x=N*M;
int* val3 = new int[x];
memset(val3, 0, x * sizeof (int));
for (int i = 0; i < x; i++)
{
// ...
}
// ...
delete [] val3;