This question might be simple but I never use raw pointers or arrays in C++ so...
I need to use a library function which looks like this:
void f(double a[3][3], double b[3], double c[3]);
a and b are used for input and the result is stored in c.
The computation of a is a bit complex but does never change so it makes sense to calculate it only once and save the result. In my program, I can link it to an object of type X.
class X{
public:
X(){
a = {{1,2,3},
{4,5,6},
{7,8,9}};
}
private:
double a[3][3];
}
How can I write a getter for X::a which can be used in function f?
This is how I would like to call function f:
#include "X.h"
int main(int argc, char *argv[]){
X o = X(); //create object
double a[3][3] = o.getA(); // I want to get a somehow
double b[3] = {1,2,3}; // create dummy b
double c[3] = {}; // create empty c
f(a,b,c); // call funktion to populate c
for(int i=0; i<3; ++i){
std::cout << c[i] << endl;
}
}
You know std::vector is the way to go for 2D arrays in C++, but if you can't bypass the obstacle you are facing, then it would be possible to pass the matrix as a parameter to the getter function, like this:
#include <iostream>
class X {
public:
void getA(double (&array)[3][3]) {
for (int i = 0; i < 3; ++i)
for (int j = 0; j < 3; ++j)
array[i][j] = a[i][j];
}
private:
double a[3][3] = {{1,2,3},
{4,5,6},
{7,8,9}};
};
int main(void) {
X o = X();
double a[3][3];
o.getA(a);
for(int i = 0; i < 3; ++i)
for(int j = 0; j < 3; ++j)
std::cout << a[i][j] << std::endl;
return 0;
}
This snippet should serve your purpose.
#include <iostream>
#include <string>
using namespace std;
class X {
public:
X() {
}
typedef double (*ptr_matrix)[3];
ptr_matrix getA(){
return a;
}
private:
double a[3][3] = {{ 1,2,3},
{4,5,6},
{7,8,9}};
};
void f(double a[3][3], double b[3], double c[3])
{
cout<<"Inside f function";
for(auto i = 0; i < 3;i++) {
cout<<endl;
for(auto j = 0 ; j < 3;j++)
cout<<a[i][j];
}
}
int main()
{
X o = X(); //create object
double (*a)[3] = NULL;
a = o.getA(); // I want to get a somehow
double b[3] = {0};
double c[3] = {0};
f(a,b,c);
}
Related
I have a problem with assigning variables to an array from different functions. I have two functions that produce different numbers. I then want to assign those numbers to a private array in the same class. When I do this the array returns large negative numbers.
// Array.h
class Array {
private:
int W = A;
int Q = B;
int sum[2] = {W, Q};
public:
int A;
int B;
int num1();
int num2();
int add();
};
// Array.cpp
#include<iostream>
using namespace std;
#include "Array.h"
int Array::num1()
{
int x = 3;
int y = 4;
A = x + y;
cout << A << endl;
return A;
}
int Array::num2()
{
int x = 2;
int y = 5;
B = x + y;
cout << B << endl;
return B;
}
int Array::add()
{
for(int i = 0; i < 2; i++)
{
cout << sum[i] << endl;
}
return 0;
}
// main.cpp
#include <iostream>
#include "Array.h"
int main() {
Array sumTotal;
sumTotal.num1();
sumTotal.num2();
sumTotal.add();
return 0;
}
Problem is here:
int W = A;
int Q = B;
int sum[2] = { W, Q };
You are just coping value from A and B to W and Q.
And later when you set A and B, those changes are not reflected to W or Q.
Thus leaving W and Q uninitialized.
Note: consider researching more about C++ topic in field of arrays, pointers and references.
This is modified code that works ok:
#include <iostream>
using namespace std;
class Array {
private:
int sum[2];
public:
int num1();
int num2();
int add();
};
int Array::num1()
{
int x = 3;
int y = 4;
sum[0] = x + y;
cout << sum[0] << endl;
return sum[0];
}
int Array::num2()
{
int x = 2;
int y = 5;
sum[1] = x + y;
cout << sum[1] << endl;
return sum[1];
}
int Array::add()
{
for (int i = 0; i < 2; i++)
{
cout << sum[i] << endl;
}
return 0;
}
int main(int argc, char** argv)
{
Array sumTotal;
sumTotal.num1();
sumTotal.num2();
sumTotal.add();
return 0;
}
The reason you are getting garbage values (large negative numbers, in your case) is that you are not initializing A or B to any meaningful values, and then you are not updating sum when you call num1, or num2.
You should initialize A and B to something meaningful in the class, or at least default initialize it.
Then you need to update sum in num1, like this:
int Array::num1()
{
int x = 3;
int y = 4;
A = x + y;
sum[0] = A; // <- add this
cout << A << endl;
return A;
}
and do a similar thing inside num2.
You also have 2 variables W, and Q inside your class which don't seem to serve any purpose. Apart from the issue with initializing them incorrectly with garbage values, you don't even need them; you could just use A, and B instead.
The problem occurs in foo() (in the commented lines), and is that foo2() should return the result of a matrix multiplication repeated process in it's first parameter. It is working in the first case and failing right after.
B and B_tmp arrays should have the same values at the end of foo() and that's not happening
T is 1x6 matrix, A is 6x3 matrix, B is 200x3 matrix
foo3() multiplies TxA and store the result (1x3 matrix) at the end of B
What foo2() does at the beginning with B_t1_t2 is not relevant, it just prepares the 1x6 matrix, changing the order in some way
I must try to solve this without changing any function declaration
I'm new to c++ and have been searching for too long now, I'm desperated
#include <stdio.h>
#include <iostream>
#include <random>
#include <thread>
using namespace std;
double fRand(const double & min, const double & max) {
thread_local std::mt19937 generator(std::random_device{}());
std::uniform_real_distribution<double> distribution(min, max);
return distribution(generator);
}
int iRand(const int & min, const int & max) {
thread_local std::mt19937 generator(std::random_device{}());
std::uniform_int_distribution<int> distribution(min, max);
return distribution(generator);
}
void foo3(double T[6], double A[18], double *B)
{
for(int i = 0; i < 3; i++) {
double r = 0;
for(int j = 0; j < 6; j++) {
r += T[j] * A[i*3+j];
}
*B = r; B++;
}
}
void foo2(double *B, double *A, int from, int to)
{
for (int i=from; i < to; i++) { //This is not relevant but I leave it just in case
double B_t1_t2[6];
for (int x = 0; x < 3; x++)
B_t1_t2[x] = B[(i-1)*3 + x];
for (int x = 0; x < 3; x++)
B_t1_t2[x+3] = B[(i-2)*3 + x];
foo3(B_t1_t2, A, &B[i*3]);
}
}
void foo(double *A, double *B)
{
for (int i = 0; i < 18; i++)
A[i] = fRand(1, 2);
foo2(B, A, 2, 200);
cout << "\nB" << endl;
for (int i = 0; i < 600; i++)
cout << B[i] << " "; // HERE IS WORKING, B DOES NOT CONTAIN GARBAGE
cout << endl;
double B_tmp[600];
foo2(B_tmp, A, 2, 200);
cout << "\nB_tmp" << endl;
for (int i = 0; i < 600; i++)
cout << B_tmp[i] << " "; // WHY NOT WORKING HERE?
cout << endl;
}
int main()
{
double A[18], B[600];
for(int i = 0; i<6; i++)
B[i] = 1;
foo(A, B);
}
Why the second cout in foo() is showing garbage?
Also, if declarations must change, what would be the best way?
Im trying to use stack memory as much as I can.
Before calling foo(A, B); first 6 elements of B array were filled (all are set to 1). In foo function you call foo2 function twice. In first call you pass B array into foo2 function, and it works because B is filled. In second call of foo2 in foo you pass B_tmp array but all items of this array have garbage value, you didn't initialize them. So do
double B_tmp[600];
for (int i = 0; i < 6; ++i)
B_tmp[i] = 1;
foo2(B_tmp, A, 2, 200);
So I have my program here:
#include <iostream>
#include <string>
#include <pthread.h>
#include <unistd.h>
#include <math.h>
#include <stdlib.h>
using namespace std;
int const size = 3;
struct Arguments{
int array[];
float result1[];
float result2[];
};
//void calc(int arr[], float rarr1[], float rarr2[], int size);
void* calc(void *param);
int main(int argc, char *argv[]){
time_t t;
srand((unsigned) time(&t));
int arr[size][size] = {};
float rarr1[size][size-1] = {};
float rarr2[size][size-1] = {};
for(int x = 0; x < size; x++){
for(int y = 0; y < size; y++){
int number = rand()%10;
arr[x][y] = number;
}
}
for(int x = 0; x < size; x++){
for(int y = 0; y < size; y++){
cout << arr[x][y] << " ";
}
cout << endl;
}
cout << endl;
/////////////////////////////////////////
pthread_t child;
struct Arguments input;
for(int i = 0; i < size; i++){
input.array[i] = arr[0][i];
}
pthread_create(&child, NULL, calc, (void*)&input);
pthread_join(child, NULL);
//calc(&input);
for(int i = 0; i < size-1; i++){
rarr1[0][i] = input.result1[i];
cout << "Test: " << rarr1[0][i] << endl;
}
//////////////////////////////////
return 0;
}
//void calc(int arr[], float rarr1[], float rarr2[], int size){
void* calc(void *param){
struct Arguments *input = (struct Arguments*)param;
int arr1[] = {};
float rarr1[] = {};
float rarr2[] = {};
for(int i = 0; i < size; i++){
arr1[i] = input->array[i];
}
for(int i = 0; i < size; i++){
int a = arr1[i];
int b = arr1[i+1];
int difference = a-b;
if(difference < 0){
difference = difference * -1;
}
float euc = 1 + pow(difference, 2);
euc = sqrt(euc);
rarr1[i] = euc;
}
for(int i = 0; i <size-1; i++){
input->result1[i] = rarr1[i];
}
for(int i = 0; i <size-1; i++){
int a = arr1[i];
int b = arr1[i+1];
int difference = a-b;
if(difference < 0){
difference = difference * -1;
}
float apar = (difference/rarr1[i]);
float result = asin(apar);
result = result*(180/3.14);
rarr2[i] = result;
}
return NULL;
}
The important part that causes the trouble is between ////// lines but I left the rest of the code for the context, since it might be useful.
So I have the function calc(param); that does the important calculation in the program.
It is working just fine as long as I call it myself (by actually including the function call in the code) and the test loop right after it gives the correct results.
However, when I try to use pthread_create(); to create a new thread that will take care of executing that function, the test loop spits out nonsense and some random huge numbers different each time.
It's kinda weird because the code compiles either way, and literally the only thing that I change is these 2 lines.
What am I doing wrong and why the function spits out garbage when started by the Pthread? Is there a way to fix it?
Ok so if anyone's having a similar problem:
Declare the size of arrays no matter what. It turns out that my program didn't work properly because I initialized my result arrays as float result1[]; instead of float result1[size];
I have a function:
void computeC(array3D fp, double& C) {
C = 0.0;
for (int x = 0; x < M; ++x) {
for (int y = 0; y < N; ++y) {
for (int i = 0; i < 5; ++i) {
C += fp[x][y][i];
}
}
}
}
here the variable fp and C are defined as:
typedef std::vector<double> array1D;
typedef std::vector<array1D> array2D;
typedef std::vector<array2D> array3D;
array2D C(M, array1D(N, 0));
array3D fp(M, array2D(N, array1D(5, 0.0)));
The function is a called as:
computeC(fp, C);
When I execute the main code, following error appears:
vect.cpp:9:22: error: invalid initialization of reference of type 'double&'
from expression of type 'array2D {aka std::vector<std::vector<double> >}'
and
vect.hpp:130:6: error: in passing argument 2 of 'void computeRho(array3D, double&)'
How can I solve this?
The compiler message is quite clear. The type of the second parameter that you try to pass to the function does match with the type the parameter is declared to have. The type of the parameter is double& but you try pass an array2D. array2D is not a double, so you may not pass it to the function.
To solve this, define C to be a double.
But array2D is a vector of vector of doubles. how can I again define C as double?
You can do this by removing the definition array2D C(M, array1D(N, 0)); and replacing it with double C = 0.0;
Any other idea of function definition with vectors as input and output arguments?
Yes, that's another possible approach. Instead of defining a function that takes a double& as a parameter, you could instead implement a function that does take an array2D& parameter. You could then pass C to such function.
(Edit: Answer updated after comments from OP)
Is this what you are looking for:
typedef std::vector<double> array1D;
typedef std::vector<array1D> array2D;
typedef std::vector<array2D> array3D;
void computeC(array3D& fp, array2D& C) {
double tmp = 0.0;
// Calculate sum of element in 3D array
for (int x = 0; x < M; ++x) {
for (int y = 0; y < N; ++y) {
for (int i = 0; i < 5; ++i) {
tmp += fp[x][y][i];
}
}
}
// Update the 2D array
for (int x = 0; x < M; ++x) {
for (int y = 0; y < N; ++y) {
C[x][y] = tmp;
}
}
}
int main()
{
array2D C(M, array1D(N, 0));
array3D fp(M, array2D(N, array1D(5, 0.0)));
computeC(fp, C);
return 0;
}
or
typedef std::vector<double> array1D;
typedef std::vector<array1D> array2D;
typedef std::vector<array2D> array3D;
void computeC(array3D& fp, array2D& C) {
for (int x = 0; x < M; ++x) {
for (int y = 0; y < N; ++y) {
for (int i = 0; i < 5; ++i) {
C[x][y] += fp[x][y][i];
}
}
}
}
int main()
{
array2D C(M, array1D(N, 0));
array3D fp(M, array2D(N, array1D(5, 0.0)));
computeC(fp, C);
return 0;
}
I think that the answer of StillLearning is the best fit to your question.
Maybe you can get rid of global variables and divide that function into two more basic functionality, like sumOfElements and setElements:
#include <iostream>
#include <vector>
typedef std::vector<double> array1D;
typedef std::vector<array1D> array2D;
typedef std::vector<array2D> array3D;
template< typename T>
double sumOfElements (T & a) {
double sum = 0.0;
for ( auto i : a) sum += sumOfElements(i);
return sum;
}
template<>
double sumOfElements<array1D> (array1D & a) {
double sum = 0.0;
for ( auto i : a) sum += i;
return sum;
}
template< typename T >
void setElements ( double val, T & a) {
for ( auto & i : a) setElements(val,i);
}
template<>
void setElements<array1D> ( double val, array1D & a) {
for ( auto & i : a) i = val;
}
int main() {
double d;
array2D b(4,array1D(5,0.1));
array3D c(3,array2D(4,array1D(5,2.0)));
d = sumOfElements(c);
std::cout << "Sum of elements: " << d << std::endl;
setElements(d,b);
std::cout << "Now all the elements of the array2D are: " << b[2][3] << std::endl;;
return 0;
}
Finally, I get the results and the functions is working perfect as desired. Thanks for the help. Working function is:
void computeC(array3D& fp, array2D& C) {
for (int x = 0; x < M; ++x) {
for (int y = 0; y < N; ++y) {
C[x][y] = 0.0
for (int i = 0; i < 5; ++i) {
C[x][y] += fp[x][y][i];
}
}
}
}
Assume I have a class A that has say 3 methods. So the first methods assigns some values to the first array and the rest of the methods in order modify what is computed by the previous method. Since I wanted to avoid designing the methods that return an array (pointer to local variable) I picked 3 data member and store the intermediate result in each of them. Please note that this simple code is used for illustration.
class A
{
public: // for now how the class members should be accessed isn't important
int * a, *b, *c;
A(int size)
{
a = new int [size];
b = new int [size];
c = new int [size];
}
void func_a()
{
int j = 1;
for int(i = 0; i < size; i++)
a[i] = j++; // assign different values
}
void func_b()
{
int k = 6;
for (int i = 0; i < size; i++)
b[i] = a[i] * (k++);
}
void func_c()
{
int p = 6;
for int (i = 0; i < size; i++)
c[i] = b[i] * (p++);
}
};
Clearly, if I have more methods I have to have more data members.
** I'd like to know how I can re-design the class (having methods that return some values and) at the same time, the class does not have the any of two issues (returning pointers and have many data member to store the intermediate values)
There are two possibilities. If you want each function to return a new array of values, you can write the following:
std::vector<int> func_a(std::vector<int> vec){
int j = 1;
for (auto& e : vec) {
e = j++;
}
return vec;
}
std::vector<int> func_b(std::vector<int> vec){
int j = 6;
for (auto& e : vec) {
e *= j++;
}
return vec;
}
std::vector<int> func_c(std::vector<int> vec){
//same as func_b
}
int main() {
std::vector<int> vec(10);
auto a=func_a(vec);
auto b=func_b(a);
auto c=func_c(b);
//or in one line
auto r = func_c(func_b(func_a(std::vector<int>(10))));
}
Or you can apply each function to the same vector:
void apply_func_a(std::vector<int>& vec){
int j = 1;
for (auto& e : vec) {
e = j++;
}
}
void apply_func_b(std::vector<int>& vec){
int j = 6;
for (auto& e : vec) {
e *= j++;
}
}
void apply_func_c(std::vector<int>& vec){
// same as apply_func_b
}
int main() {
std::vector<int> vec(10);
apply_func_a(vec);
apply_func_b(vec);
apply_func_c(vec);
}
I'm not a big fan of the third version (passing the input parameter as the output):
std::vector<int>& func_a(std::vector<int>& vec)
Most importantly, try to avoid C-style arrays and use std::vector or std::array, and don't use new, but std::make_unique and std::make_shared
I'm assuming you want to be able to modify a single array with no class-level attributes and without returning any pointers. Your above code can be modified to be a single function, but I've kept it as 3 to more closely match your code.
void func_a(int[] arr, int size){
for(int i = 0; i < size; i++)
arr[i] = i+1;
}
void func_b(int[] arr, int size){
int k = 6;
for(int i = 0; i < size; i++)
arr[i] *= (k+i);
}
//this function is exactly like func_b so it is really unnecessary
void func_c(int[] arr, int size){
int p = 6;
for(int i = 0; i < size; i++)
arr[i] *= (p+i);
}
But if you just want a single function:
void func(int[] arr, int size){
int j = 6;
for(int i = 0; i < size; i++)
arr[i] = (i+1) * (j+i) * (j+i);
}
This solution in other answers is better, if you are going to allocate memory then do it like this (and test it!) also if you are not using the default constructor and copy constructor then hide them, this will prevent calling them by accident
class A{
private:
A(const &A){}
A() {}//either define these or hide them as private
public:
int * a, *b, *c;
int size;
A(int sz) {
size = sz;
a = new int[size];
b = new int[size];
c = new int[size];
}
~A()
{
delete[]a;
delete[]b;
delete[]c;
}
//...
};