简体   繁体   中英

How to create a C++ array with variable elements?

I have this C++ program:

#include <iostream>
#include <vector>
#include <string>
#include <fstream>
#include <cmath>

using namespace std;

double dx2(int t, int x, int dx)
{
    return (-9.8*cos(x));
}

int square(int x) 
{
    return (x*x);
}

double RK4(float t, float x, float dx, float h)
{
    double k1, k2, k3, k4, l1, l2, l3, l4, diff1, diff2;
    k1 = h*dx2(t,x,dx);
    l1 = h*k1;
    k2 = h*dx2(t+h/2,x+l1/2,dx+k1/2);
    l2 = h*k2;
    k3 = h*dx2(t+h/2,x+l2/2,dx+k2/2);
    l3 = h*k3;
    k4 = h*dx2(t+h,x+l3,dx+k3);
    l4 = h*k4;
    diff1 = (l1+2*l2+2*l3+l4)/float(6);
    diff2 = (k1+2*k2+2*k3+k4)/float(6);
    double OUT[] = {diff1, diff2};
    return OUT;
}

int main()
{
    double diff, t, t0, t1, x, x0, dx, dx0, h, N;
    N = 1000;
    t0 = 0;
    t  = t0;
    t1 = 10;
    x0 = 0;
    x  = x0;
    dx0 = 0;
    dx  = dx0;
    h = (t1 - t0) / float(N);

    for(int i = 1; i<=N; i++) {
        diff = RK4(t,x,dx,h);
        x = x + diff;
        t = t + h;
    }
    cout << diff;
    return 0;
}

As you can see in this program I am solving the 2nd-order differential equation (if there is a way to insert LaTeX equations into my question please tell me):

d2x/dt2= -9.8 cos(x)

which is an example of the simple pendulum's equations of motion. The problem lines are 33 and 34. In it I am attempting to define the first element of the OUT array as diff1 and the second element as diff2. Whenever I compile this program (named example.cpp ) I get the error:

g++ -Wall -o "example" "example.cpp" (in directory: /home/fusion809/Documents/CodeLite/firstExample)
example.cpp: In function ‘double RK4(float, float, float, float)’:
example.cpp:33:9: error: cannot convert ‘double*’ to ‘double’ in return
  return OUT;
         ^~~
Compilation failed.

Exactly, since you're returning an array of double 's, that decays to double* , but the function is defined to return double . An array of type T and the type T are different types in C++, and they can't be converted between, generally speaking.

In this case, you might be better off with a std::pair<T1, T2> ( #include <utility> ) since you're using C++ and the standard library, or a structure with two fields of type double . Look up std::pair<> and std::tie<> , the former being used to make pairs of elements of different types, and the latter being used to make tuples of different types of arbitrary size.

When you write the std::pair 's elements to std::cout , use the first , second members to access the pair's fields. A std::pair can't be directly output using the overloaded stream operator for std::cout .

Edit:

#include <utility>

std::pair<double, double> RK4(float t, float x, float dx, float h)
{
    /* snip */
    diff1 = (l1+2*l2+2*l3+l4)/float(6);
    diff2 = (k1+2*k2+2*k3+k4)/float(6);
    return {diff1, diff2};
}

int main()
{
    double x, dx;
    /* snip */
    for(int i = 1; i<=N; i++) {
        std::pair<double, double> diff = RK4(t,x,dx,h);
        // or use with C++11 and above for brevity
        auto diff = RK4(t,x,dx,h);
        x = x + diff.first;
        dx = dx + diff.second;
        t = t + h;
    }
    cout << x << " " << dx << "\n" ;
    return 0;
}

The return type of your RK4 function is double , which is a single value, but you're trying to return an array of two of them. That won't work. You could change the return type to double* and use new double[2] to allocate an array, but it'd be simpler and safer to use std::pair<double, double> as the return type. Then you can just do return { diff1, diff2 }; .

To return several values from function you have several choice:

  • as all you returned type are identical, you may return array:

     std::array<double, 2> RK4(float t, float x, float dx, float h) { // ... return {{diff1, diff2}}; } 

    or std::vector

     std::vector<double> RK4(float t, float x, float dx, float h) { // ... return {{diff1, diff2}}; } 
  • You may return std::tuple or std::pair (limited to 2 elements):

     std::pair<double, double> RK4(float t, float x, float dx, float h) { // ... return {{diff1, diff2}}; } 

    or

     std::tuple<double, double> RK4(float t, float x, float dx, float h) { // ... return {{diff1, diff2}}; } 
  • You may also create a custom class

     struct RK4Result { double diff1; double diff2; }; RK4Result RK4(float t, float x, float dx, float h) { // ... return {diff1, diff2}; } 
  • And for type expensive to move, you may use any previous method, but by out parameters:

     struct RK4Result { double diff1; double diff2; }; void RK4(float t, float x, float dx, float h, RK4Result& res) { // ... res = {diff1, diff2}; } 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM