unexpected value return by array variable - c++

I am trying to pass array to function (*getcreditcurve). I am expecting function (*getcreditcurve) to return an array. Main function is expected to send several such array to function (*getcreditcurve), pointer function is expected to return a array to main function for different array using the logic given in pointer function (*getcreditcurve). I am not getting error but I don’t get correct value. I expect I+1 to be 3 * 0.0039 = 0.0117 and I+2 to be 4 *0.0060 = 0.0024 however I get following in excel output
'00D4F844 00D4F84C'
Even if I change the print statement to
'print << *(I1+1) << '\t' << *(I2+2) << endl;'
I get following excel out put
-9.26E+61 -9.26E+61
Can somebody help in trouble shooting please? Sorry I went through other post/question in this site but not able to get simplest way to solve this issue. I am going to use this logic to build other projects so simplified the question just to resolve main issue.
#include<iostream>
#include<cmath>
#include<fstream>
typedef double S1[5];
using namespace std;
double *getcreditcurve(double *);
int main()
{
S1 C1 = { 0.0029, 0.0039, 0.0046, 0.0052, 0.0057 };
S1 C2 = { 0.0020, 0.0050, 0.0060, 0.0070, 0.0080 };
typedef double *issuer;
issuer I1 = getcreditcurve(C1);
issuer I2 = getcreditcurve(C2);
ofstream print;
print.open("result1.xls");
print << (I1+1) << '\t' << (I2+2) << endl;
print.close();
return 0;
}
double *getcreditcurve(S1 ptr)
{
const int cp = 5;
typedef double curve[cp];
curve h;
h[0] = 2 * ptr[0];
h[1] = 3 * ptr[1];
h[2] = 4 * ptr[2];
h[3] = 5 * ptr[3];
h[4] = 6 * ptr[4];
return h;
}

If you want getcreditcurve to return an array, then try this:
const int cp = 5;
typedef double curve[cp];
curve getcreditcurve(S1 ptr) {
But that gives an error error: ‘foo’ declared as function returning an array. Functions can't return C arrays. But the good news is that if you fully embrace C++ you can return std::array instead.
#include<array>
const int cp = 5;
typedef curve std::array<double,cp>;
curve getcreditcurve(S1 ptr) {
But really, std::vector is probably much better as you have more flexibility about the size.
#include<vector>
std::vector<double> getcreditcurve(std::vector<double> ptr)
{
std::vector<double> h;
h.push_back(2 * ptr.at(0));
h.push_back(3 * ptr.at(1));
h.push_back(4 * ptr.at(2));
h.push_back(5 * ptr.at(3));
h.push_back(6 * ptr.at(4));
return h;
}
In fact, pretty much all problems with C arrays can be solved by std::vector. Then, in special situations, you can use std::array. But focus on std::vector for now.

It's not possible to return a C array from a function. There are other things you can return, such as std::vector or std::array. You should consider redesigning your application around those two instead.
But if you really need to use C arrays in C++, I suggest that instead of trying to return an array from getcreditcurve, you pass an extra array into getcreditcurve which will be used to store the result. This is called an output parameter.
void getcreditcurve(double*, double *);
This would solve the "scope" problem. The caller (main) would then create the array before calling getcreditcurve and would then pass that to getcreditcurve. As a result, getcreditcurve does not have to take responsibility for creating (or destroying) any object.
double I1[5];
getcreditcurve(I1, C1); // will store its result on `I1`.
This might be the easiest option if you really really need to get this working as soon as possible.
If you are willing to make some further changes, you can make a much safer program. The short term goal is to abolish all uses of * (except to use it for multiplication).
C arrays cannot be passed by value, in particular they cannot be returned. There are other funky things you can do (passing special pointers), but the best thing to do with C arrays is to pass them by reference. In C++, reference-passing behaviour is quite consistent and works well.
// http://stackoverflow.com/questions/31362360/unexpected-value-return-by-array-variable
#include<iostream>
#include<cmath>
#include<fstream>
typedef double S1[5];
using namespace std;
/* In the following declaration, the two parameters
* are taken by reference (note the '&').
* This is almost always the best way to pass arrays.
*
* Also, this is a template where N is automatically
* set to the correct number of parameters. This nice
* automatic behaviour is possible only because the
* array is taken by reference.
*
* Finally, note that the second reference, for 'input',
* has 'const'. This is to emphasize that 'input' is for input,
* that getcreditcurve will not be allowed to modify the input argument.
*/
template<size_t N>
void getcreditcurve(double (&output)[N],const double (&input)[N]);
int main()
{
/* S1 is the type - array of five doubles */
/* Here declare and initialize C1 and C2 as two variables
* of this type */
S1 C1 = { 0.0029, 0.0039, 0.0046, 0.0052, 0.0057 };
S1 C2 = { 0.0020, 0.0050, 0.0060, 0.0070, 0.0080 };
// create the two output arrays first, within main
S1 I1;
S1 I2;
// call getcreditcurve, passing in the output and input arrays
getcreditcurve(I1,C1);
getcreditcurve(I2,C2);
ofstream print;
/* you can't create Excel(.xls) files in C++ easily
* Better to just create a .csv file instead
* csv = comma-separated values
*/
print.open("result1.csv");
print << I1[0] << ',' << I2[3] << endl;
print.close();
return 0;
}
template<size_t N>
void getcreditcurve(double (&output)[N],const double (&input)[N])
{
output[0] = 2 * input[0];
output[1] = 3 * input[1];
output[2] = 4 * input[2];
output[3] = 5 * input[3];
output[4] = 6 * input[4];
}
But seriously, you really should just ditch C arrays entirely. This is C++, not C. Use std::vector<double> instead.

Related

Comparing strings in qsort

Whenever I am comparing string in qsort, the order is completely wrong. For example, the input is
45 4 9 22 2
but my output is
22 45 4 9 2
here is my comparing function
int cmpString(const void *a, const void *b) {
const Node *a1 = *(const Node **)a;
const Node *b1 = *(const Node **)b;
return a1->s.c_str() - b1->s.c_str();
}
and dont tell me to use sort(), I can't for this assignment
This line is your code's major problem.
return a1->s.c_str() - b1->s.c_str();
The reason behind this is that you are subtracting two pointers here which is not what comparator is supposed to do in this case. Comparator does the comparison on the basis of content.
Instead, try this:
int length1 = a1->s.size();
int length2 = b1->s.size();
for (int i = 0; i < min(length1, length2); i++) {
if (a1->s[i] != b1->s[i]) { // if characters are not same, return difference of their ASCII values.
return a1->s[i] - b1->s[i];
}
}
return length1 - length2; // if they are same till now, then shorter string should appear first. That's why it is required.
Suggestion:
If you are coding in C++, then please use STL. There is a nice function sort() given by <algorithm> which allows you to do the same thing without using void *
Update:
As rightly suggested by user4581301, you may use std::string::compare directly.
Like this:
return (a1->s).compare(b1->s);

Variable size array in C++

This is interesting. I want to make a 2D array where one of the dimensions is a variable. Here is my code:
int main(void) {
const int rows = numlines("health.txt");
float data[rows][5] = {0};
readIntoArray(data, 5, rows, "health.txt");
return 0;
}
Line 3 "rows" is underlined with an error. It says: "Expression must have a constant value." Apparently it works for other people to use const in these situations. But mine might work differently because my variable is defined by a function. Here is that function:
int numlines(string filename) {
int number_of_lines = 0;
ifstream fin(filename);
string line;
while (getline(fin, line)) {
++number_of_lines;
}
return number_of_lines;
}
I have tried following other suggestions and making my code follow this format:
(Replace lines 2 & 3 of the first code block with this.)
int rows = numlines("health.txt");
float **data;
data = new float*[rows]; //The height is defined by the function
for (int i = 0; i < rows; i++) {
data[i] = new float[5]; //The width is 5
}
But then that causes an error on "data" in line 4 of the first codeblock. The error is Argument of type "float**" is incompatible with parameter of type "float (*)[5]". Here is the first line of the relevant function:
void readIntoArray(float data[][MAXCOLUMNS], int arrayX, int arrayY, string filename)
MAXCOLUMNS is #defined as 5.
How do I pass the 2D array into the function without creating an error?
I am not the most experienced in c++, so I might be missing something obvious.
There is a difference between:
const int rows = numlines("health.txt");
and
const int rows = 20;
In both cases the value of the variable cannot modified once it is initialzed. The difference is that in the first case, the value won't be known until run time while in the second case, the value is known at compile time.
In C++, an array can be declared using a variable only if its value is known at compile time.
That explains why you cannot use:
const int rows = numlines("health.txt");
float data[rows][5] = {0};
but you can use:
const int rows = 20;
float data[rows][5] = {0};
You can easily get around that issue by using an std::vector of std::vectors.
const int rows = numlines("health.txt");
std::vector<std::vector<float>> data(rows, std::vector<float>(5));
Since you know the size of the inner array, you can also you std::array. It will make the declaration a little simpler.
std::vector<std::array<float, 5>> data(rows);
In C++,you can use "std::vector< T >" to save your data as a variable size array.
Just learn how to use STL,it would simplify your works.
You can use alloca to implement the equivalent of a variable length array:
float (*data)[5] = (float (*)[5]) _alloca(rows * 5 * sizeof(float));
This will allocate local (stack) space and set data to point to the first row (with 5 columns) of a matrix of floats. The 5 can be replaced with a constant. You can then use data like a normal local matrix, data[ i ][ j ] ... . Depending on the compiler, the name may be alloca() instead of _alloca(), and the cast (float (*)[5]) may not be needed.
Since this is a local allocation, it's automatically freed when the function exits.

Return an array of a struct in c++, and pass this array to another method?

I need to return an array of structs and then pass this array to another method for printing.
Here is my .h file:
#include <string>
#include "COMMON_TYPES.h"
#pragma once
#pragma pack(push, 1)
class ARS_HR_LINE_1
{
public:
struct ARS_HR_LINE_1_ALL
{
//Countre
int Counter
float Inner_Rate_FB_Fine;
float Inner_Rate_FB_Cross;
float Inner_Rate_FB_Roll;
float IMU_Yaw;
};
u16 img [1][616];
//Methods
ARS_HR_LINE_1::ARS_HR_LINE_1_ALL *Process_HR_ARS_Line_1();
void Print_HR_Line_1(FILE* fptr, int counter, ARS_HR_LINE_1::ARS_HR_LINE_1_ALL* h); // Print High Rate Line 1
};
#pragma pack(pop)
The .cpp file:
#include <iostream>
#include "ARS_HR_LINE_1.h"
#include "COMMON_TYPES.h"
using namespace std;
ARS_HR_LINE_1::ARS_HR_LINE_1_ALL * ARS_HR_LINE_1::Process_HR_ARS_Line_1()
{
ARS_HR_LINE_1::ARS_HR_LINE_1_ALL h[60];
for(int i=0;i<60;++i)
{
h[i].Counter = (ARS_HR_LINE_1::img[0][i*10 + 0] << 16) + ARS_HR_LINE_1::img[0][i*10 + 1];
u32 inner_rate_fb_fine = (ARS_HR_LINE_1::img[0][i*10 + 2] << 16) + ARS_HR_LINE_1::img[0][i*10+3];
h[i].Inner_Rate_FB_Fine =*reinterpret_cast<float*>(&inner_rate_fb_fine);
u32 inner_rate_fb_cross = (ARS_HR_LINE_1::img[0][i*10+4] << 16) + ARS_HR_LINE_1::img[0][i*10+5];
h[i].Inner_Rate_FB_Cross =*reinterpret_cast<float*>(&inner_rate_fb_cross);
u32 inner_rate_fb_roll = (ARS_HR_LINE_1::img[0][i*10+6] << 16) + ARS_HR_LINE_1::img[0][i*10+7];
h[i].Inner_Rate_FB_Roll =*reinterpret_cast<float*>(&inner_rate_fb_roll);
u32 imu_yaw = (ARS_HR_LINE_1::img[0][i*10+8] << 16) + ARS_HR_LINE_1::img[0][i*10+9];
h[i].IMU_Yaw =*reinterpret_cast<float*>(&imu_yaw);
}
return h;
}
void ARS_HR_LINE_1::Print_HR_Line_1(FILE* fptr, int counter, ARS_HR_LINE_1::ARS_HR_LINE_1_ALL *h)
{
ARS_HR_LINE_1::ARS_HR_LINE_1_ALL temp;
temp.Counter = 0;
temp.Inner_Rate_FB_Fine = 0;
temp.Inner_Rate_FB_Cross = 0;
temp.Inner_Rate_FB_Roll = 0;
temp.IMU_Yaw = 0;
//tempArr[i] = *(h+i);
fprintf(fptr, "************************************************************\n");
fprintf(fptr, "******************IMAGE NUMBER %d ***************************\n", counter);
fprintf(fptr, "*********************LINE 1**********************************\n");
for(int i=0;i<60;++i)
{
temp = *(h+i);
//Counter and Filler - 4 bytes
fprintf(fptr, "Counter[%d] : %u\n", temp.Counter, i);
//Rate FB
fprintf(fptr, "Inner_Rate_FB_Fine[%d] : %12.20f\n", temp.Inner_Rate_FB_Fine, i);
fprintf(fptr, "Inner_Rate_FB_Cross[%d] : %12.20f\n", temp.Inner_Rate_FB_Cross, i);
fprintf(fptr, "Inner_Rate_FB_Roll[%d] : %12.20f\n", temp.Inner_Rate_FB_Roll, i);
//IMU_Yaw
fprintf(fptr, "IMU_Yaw[%d] : %12.20f\n", temp.IMU_Yaw, i);
}
}
and then in the main I use the following:
ARS_HR_LINE_1::ARS_HR_LINE_1_ALL* h;
ARS_HR_LINE_2::ARS_HR_LINE_2_ALL* h2;
h = ARS_HR_DEBUG_DATA.Process_HR_ARS_Line_1();
h2 = ARS_HR_DEBUG_DATA2.Process_HR_ARS_Line_2();
ARS_HR_DEBUG_DATA.Print_HR_Line_1(tassTxtFptr, i, h);
ARS_HR_DEBUG_DATA2.Print_HR_Line_2(tassTxtFptr, i, h2);
where tassTxtFptr is a pointer to a text file.
my Process_HR_ARS_Line_1 seems to be working properly, and when I bring up the array in visual studio, prior to returning it, all of the values look correct. When I go to print my information, I get a lot of gibberish, mixed with the correct values. Any idea what I am doing wrong?
The array h ceases to exist when the Process function ends, so the pointer points to where it used to be (and who knows what info is there now?). I would suggest declaring the array in main and passing it to the function to be filled, or using one of the STL containers like vector.
Your declaration ARS_HR_LINE_1::ARS_HR_LINE_1_ALL h[60]; (a local variable) is allocating the space for your array within the stack frame of the call to Process_HR_ARS_Line_1(). After your program leaves that method, the memory allocated on the stack for that array is no longer valid. Accessing this memory is undefined behavior.
By returning h, that array decays to a pointer and you are effectively returning a pointer to the invalid memory space on the stack.
How do you get around this? Use std::vector. Alternatively you could allocate the array on the heap using new, but since this is C++ you should use the facilities available to you to simplify your memory management.
ARS_HR_LINE_1::ARS_HR_LINE_1_ALL h[60];
return h;
You are returning a pointer to a local variable. It gets destroyed when function exits. You should create the array using new, and taking care to delete the pointer after using it
You're allocating the array h on the stack. When you return from the function, the h leaves scope and is freed from the stack. You return a pointer to h which is no longer valid!
Either use new to allocate space on the heap that will exist outside the function (don't forget to delete it later!) or use STL vector.
You are allocating the array inside the method on the stack, which means that it is going to go out of scope as soon as your method is finished (thats why it is filled with carbage). Try allocating it on the heap instead, or if you still want to allocate it on the stack try using call-by-reference.
Call-by-reference can be achieved by changing your code as follows:
void Process_HR_ARS_Line_1(ARS_HR_LINE_1_ALL* h);
Your main can now look like this:
ARS_HR_LINE_1::ARS_HR_LINE_1_ALL h[60];
ARS_HR_DEBUG_DATA.Process_HR_ARS_Line_1(&h);
ARS_HR_DEBUG_DATA.Print_HR_Line_1(tassTxtFptr, i, &h);
To allocate your list on the heap you can do as follows (Its allways important to remember to use delete[] when you allocate something on the heap):
ARS_HR_LINE_1::ARS_HR_LINE_1_ALL* h = new ARS_HR_LINE_1::ARS_HR_LINE_1_ALL[60];
delete[] h;

ctypes: Initialize array of arrays and pass to C function

I've been fooling with ctypes and have come across two problems:
Problem 1. I would like to build a cellComplex using double* arrays, but I want new_cellComplex to accept an array of double*'s (along with a size_t argument) rather than a fixed number of double*'s. With a fixed number the code looks like this (and it runs fine):
extern "C" {
void * new_cellComplex(double* p_x, double* p_y, double* p_z) {
std::vector< std::pair<double,double> > point;
point.push_back( std::make_pair(p_x[0],p_x[1]));
point.push_back( std::make_pair(p_x[0],p_x[1]));
point.push_back( std::make_pair(p_x[0],p_x[1]));
cellComplex<double>* cmplx = new cellComplex<double>(point);
return cmplx;
}
with Python code:
import ctypes
cellComplex_lib = ctypes.cdll.LoadLibrary('./cellComplex_lib.so')
cellComplex_lib.new_cellComplex.restype = ctypes.c_void_p
cellComplex_lib.new_cellComplex.argtypes = [ctypes.c_double*2,
ctypes.c_double*2,
ctypes.c_double*2]
p_x = (ctypes.c_double*2)(0.0,1.0)
p_y = (ctypes.c_double*2)(0.0,1.0)
p_z = (ctypes.c_double*2)(0.0,1.0)
cmplx = cellComplex_lib.new_cellComplex(p_x,p_y,p_z)
I would rather have the following (which segfaults):
extern "C" {
void * new_cellComplex(double** p, size_t dim) {
std::vector< std::pair<double,double> > point;
for (size_t i=0; i<dim; ++i) {
point.push_back( std::make_pair(p[i][0],p[i][1]));
}
cellComplex<double>* cmplx = new cellComplex<double>(point);
return cmplx;
}
}
With Python code:
import ctypes
dim = 3
cellComplex_lib = ctypes.cdll.LoadLibrary('./cellComplex_lib.so')
cellComplex_lib.new_cellComplex.restype = ctypes.c_void_p
cellComplex_lib.new_cellComplex.argtypes = [(ctypes.c_double*2)*dim,
ctypes.c_size_t]
p_x = (ctypes.c_double*2)(0.0,1.0)
p_y = (ctypes.c_double*2)(0.0,1.0)
p_z = (ctypes.c_double*2)(0.0,1.0)
p = ((ctypes.c_double*2)*dim)(p_x,p_y,p_z)
cmplx = cellComplex_lib.new_cellComplex(p,dim)
^This doesn't work and I don't know why.
Problem 2. (Included here because it's glaring in Problem 1) I am returning an essentially anonymous pointer from my C code! This just feels, well, dirty, and there must be a better way to return a custom data type and deal with it back in Python. For the record, I am extremely grateful for this stackoverflow answer where I learned such sorcery - but I'm not going to be able to sleep at night as long as it's in my code...
Instead of double **, use double [][2]. You're passing a contiguous C array that you want to access as a pointer to a row of 2 items. The first index is the row index.
Declaring the array as a double ** is a pointer to a double pointer, so p[i] is a pointer, and p[i][0] dereferences it again. But p[i] is a NULL pointer by chance according to your data.
Refer to the comp.lang.c FAQ, question
6.18: My compiler complained when I passed a two-dimensional array to a function expecting a
pointer to a pointer.
For the return type, you can subclass c_void_p, or use the hooks from_param and _as_parameter_ per the last paragraph of section 15.17.1.7 in the ctypes docs.

Simple question regarding an equation inside of a function

Hey, so basically I have this issue, where I'm trying to put an equation inside of a function however it doesn't seem to set the value to the function and instead doesn't change it at all.
This is a predator prey simulation and I have this code inside of a for loop.
wolves[i+1] = ((1 - wBr) * wolves[i] + I * S * rabbits[i] * wolves[i]);
rabbits[i+1] = (1 + rBr) * rabbits[i] - I * rabbits[i] * wolves[i];
When I execute this, it works as intended and changes the value of both of these arrays appropriately, however when I try to put it inside of a function,
int calcRabbits(int R, int rBr, int I, int W)
{
int x = (1 + rBr) * R - I * R * W;
return x;
}
int calcWolves(int wBr, int W, int I, int S, int R)
{
int x = ((1 - wBr) * W + I * S * R * R);
return x;
}
And set the values as such
rabbits[i+1] = calcRabbits ( rabbits[i], rBr, I, wolves[i]);
wolves[i+1] = calcWolves(wBr, wolves[i], I, S, rabbits[i]);
The values remain the same as they were when they were initialized and it doesn't seem to work at all, and I have no idea why. I have been at this for a good few hours and it's probably something that I'm missing, but I can't figure it out.
Any and all help is appreciated.
Edit: I realized the parameters were wrong, but I tried it before with the correct parameters and it still didnt work, just accidentally changed it to the wrong parameters (Compiler mouse-over was showing the old version of the parameters)
Edit2: The entire section of code is this
days = getDays(); // Runs function to get Number of days to run the simulation for
dayCycle = getCycle(); // Runs the function get Cycle to get the # of days to mod by
int wolves[days]; // Creates array wolves[] the size of the amount of days
int rabbits[days]; // Creates array rabbits [] the size of the amount of days
wolves[0] = W; // Sets the value of the starting number of wolves
rabbits[0] = R; // sets starting value of rabbits
for(int i = 0; i < days; i++) // For loop runs the simulation for the number of days
{
// rabbits[i+1] = calcRabbits ( rabbits[i], rBr, I, wolves[i]);
// // //This is the code to change the value of both of these using the function
// wolves[i+1] = calcWolves(wBr, wolves[i], I, S, rabbits[i]);
// This is the code that works and correctly sets the value for wolves[i+1]
wolves[i+1] = calcWolves(wBr, wolves[i], I, S, rabbits[i]);
rabbits[i+1] = (1 + rBr) * rabbits[i] - I * rabbits[i] * wolves[i];
}
Edit: I realized my mistake, I was putting rBr and wBr in as ints, and they were floats which were numbers that were below 1, so they were being automatically converted to be 0. Thanks sje
Phil I cannot see anything evidently wrong in your code.
My hunch is that your are messing up the parameters.
Using gdb at this point would be an over kill. I recommend you put print outs in calcRabbits and calcWolves. Print out all the parameters, the new value, and the iteration number. That will give you a good idea of what is going on and will help trace the problem.
Do you have the full code with initialization we could try to test and run?
I'm not sure this is the problem, but this is bad:
int wolves[days]; // Creates array wolves[] the size of the amount of days
int rabbits[days]; // Creates array rabbits [] the size of the amount of days
days is determined at runtime. This is nonstandard in c++ (and for large number of days could destroy your stack) you should only be using constants in array sizes. You can dynamically size a vector to workaround this limitation (or heap allocate the array).
Change to this:
std::vector<int> wolves(days);
std::vector<int> rabbits(days);
Or to this:
int *wolves = new int[days];
int *rabbits = new int[days];
// all your code goes here
delete [] wolves; // when you're done
delete [] rabbits; // when you're done
Which will dynamically allocate the array on the heap. The rest of the code should work the same.
Don't forget to #include <vector>, if you use the vector approach.
If you're still having problems, I would cout << "Days: " << days << endl; to make sure you're getting the right number back from getDays(). If you got zero, it would seem to manifest itself in "the loop not working".
I was using an integer as an argument for a double.