将C代码转换为C ++,将double *转换为矢量,将2D矢量转换为double *

时间:2018-08-13 17:37:59

标签: c++ c

我试图将一些我不认识的人用C编写的与研究相关的代码转换为C ++,而且绝对没有文档。 基本上将T *和T **对象转换为矢量和更加用户友好的容器。

Atm我有两个变量,

double* data
double* references

我在SO上看到了一个技巧,可以使正则向量易于分配给double *,如下所示:

references = &(*m_DataMaxPoints)[0];

没关系。

但是,应该从std::vector<std::vector<double>>* m_Data;

设置数据*

我不知道该如何分配。 我尝试过&(*m_Data)[0][0];,但我真的不知道该怎么办。 任何提示都将受到欢迎..:(

编辑1:C程序中数据的原始处理*

double *数据在main()中声明

int main(int argc, char *argv[])
{
    FILE *infile;

    int verbose_flag = FALSE;


    double *data = NULL, *reference = NULL, *maximum = NULL;
    int *cumsizes = NULL;
    int nobj = 0, nruns = 0;
    int k;
    double volume = 0;
    double time_elapsed;

read_input(stdin, "stdin", &data, &nobj, &cumsizes, &nruns);

read_input将文本文件中的数字解析为数组。

#define PAGE_SIZE 4096          // allocate one page at a time    
#define DATA_INC (PAGE_SIZE/sizeof(double))
#define SET_INC 128     // assume 128 datasets (can grow)  

int read_input(FILE *infile, const char *filename, double **datap, int *ncolsp, int **cumsizesp, int *nrunsp)
{
    char b[2];
    double number;

    int newline;                // last input was newline
    int datai;                  // the current element of (*datap)
    int col;                    // the column being read
    int set = *nrunsp;          // the current data set
    int ncols = *ncolsp;        // the number of columns

    int datasize;
    int setsize;

    datai = (set == 0) 
        ? 0 
        : ncols * (*cumsizesp)[set-1];

    setsize = (set == 0) 
        ? 0 
        : ((set-1) / SET_INC + 1) * SET_INC;

    *cumsizesp = realloc(*cumsizesp, setsize * sizeof(int));

    datasize = (datai == 0) 
        ? 0 
        : ((datai - 1) / DATA_INC + 1) * DATA_INC;

    *datap = realloc(*datap, datasize * sizeof(double));

    // remove leading whitespace
    fscanf (infile, "%*[ \t\n]");

    if (feof(infile)) {
        warnprintf("%s: file is empty.", filename);
        return -1;
    }

    do {
        newline = 0;
        if (set == setsize) {
            setsize += SET_INC;
            *cumsizesp = realloc(*cumsizesp,  setsize * sizeof(int));
        }

        (*cumsizesp)[set] = (set == 0) ? 0 : (*cumsizesp)[set-1];       // beginning of data set

        while (newline == 0) {
        col = 0;        // beginning of row
            while (newline == 0) {
        if (fscanf(infile, "%lf", &number) != 1) {
                    char buffer[64];

                    fscanf(infile, "%60s", buffer);
                    errprintf(
                        "could not convert string `%s' to double, exiting...", 
                        buffer);
                }

                if (datai == datasize) {
                    datasize += DATA_INC;
                    *datap = realloc(*datap,  datasize * sizeof(double));
                }
                (*datap)[datai++] = number;

#if DEBUG > 2
                fprintf(stderr, "set %d, row %d, column %d, x = %g\n", 
                        set, (*cumsizesp)[set], col, number);
#endif
                col++;    // new column

                fscanf(infile, "%*[ \t]");
                newline = fscanf(infile, "%1[\n]", b); 
            }

            if (!ncols) 
                ncols = col;
            else if (col != ncols) {
                if ((*cumsizesp)[0] == 0) 
                    errprintf ("reference point has dimension %d"
                               " while input has dimension %d",
                               ncols, col);
                else
                    errprintf("row %d has different length (%d)"
                              " than previous rows (%d), exiting...",
                              (*cumsizesp)[set], col, ncols);
            }

            (*cumsizesp)[set]++;

            fscanf (infile, "%*[ \t]"); 
        newline = fscanf (infile, "%1[\n]", b); 
    }
#if DEBUG > 1
        fprintf (stderr, "Set %d, %d rows in total\n", set, (*cumsizesp)[set]);
#endif
    set++; // new data set

        fscanf (infile, "%*[ \t\n]");

    } while (!feof(infile)); 

    *ncolsp = ncols;
    *nrunsp = set;

    return 0;
}

我想做的是通过为此接口创建包装器类,将尽可能少的转换为C ++,以使其更易于使用并将其实现为更大的项目。

因此,文件解析和数据分配是通过向量完成的(它们不需要成为指针)。

解析之后,我希望将向量转换为C样式的数组,这样我就可以调用原始代码的函数,而不必添加向量来支持所有这些,因为我不知道如何读取它在纯C语言中实现(多目标进化算法的实现)。

原始代码最终会调用:

volume =  hv(data, nobj, cumsizes[nruns-1], reference);

我想这样做:

double* data = &(*m_Data)[0][0]; // my 2d vector<double>
double* references = &(*m_DataMaxPoints)[0]; // 1d vector<double>
int cumsizes = m_Data->at(0).size(); 
m_Volume = hv(data, Objectives(), cumsizes, references);

2 个答案:

答案 0 :(得分:2)

在向量上使用指针不是必需的必不可少的方法,如您的问题迭代器的评论中所述,但这将是一个不错的选择。无论如何,如果您真的想使用指针,请按以下步骤操作:

vector< vector<double> >* vec = new vector< vector<double> >(16);

for (size_t i = 0; i < 16; ++i) {
    (*vec)[i].resize(16);
}

(*vec)[4][2] = 6.66;

这段代码创建了一个指针(vec),该指针指向未初始化的double型向量(尺寸为16x16),向量在位置[4] [2]处的值为6.66,我认为您现在就获得了合奏。

答案 1 :(得分:0)

std::vector用于处理所有内存分配。它不需要mallocreallocnew。如果不重写很多代码,就无法有效地实现这一点。

如果您希望C代码在C ++中进行编译,则需要进行一些细微的更改,例如强制转换:

*datap = (double*)realloc(*datap, datasize * sizeof(double));

此外,您可以通过引用传递C ++对象,因此不需要指针。通过参考传递矢量。

最简单的方法来保留现有的C代码,然后将数据从datap复制到vec。示例:

void foo(std::vector<std::vector<double>> &vec)
{
    //copy from datap to vec:

    //add a new row:
    vec.push_back(std::vector<double>{});

    //add coloumns
    vec.back().push_back(11.0f);
    vec.back().push_back(12.0f);
    vec.back().push_back(13.0f);

    //add another row:
    vec.push_back(std::vector<double>{});

    //add coloumns
    vec.back().push_back(21.0f);
    vec.back().push_back(22.0f);
    vec.back().push_back(23.0f);
}

int main()
{
    std::vector<std::vector<double>> vec;
    foo(vec);
    for(size_t row = 0; row < vec.size(); row++)
    {
        for(size_t col = 0; col < vec[row].size(); col++)
            printf("%3.0f, ", vec[row][col]);
        printf("\n");
    }
    return 0;
}

或者您也可以用C ++重写整个代码。示例:

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

void read_matrix(std::vector<std::vector<double>> &vec)
{
    std::ifstream fin("file.txt");
    if(!fin)
        return;

    std::string line;
    while(std::getline(fin, line))
    {
        //add a new row:
        vec.push_back(std::vector<double>{});

        //add columns
        std::stringstream ss(line);
        double value;
        while(ss >> value)
            vec.back().push_back(value);
    }
}

int main()
{
    std::vector<std::vector<double>> vec;
    read_matrix(vec);
    ...
    return 0;
}