如何将 .csv 文件数据导入 C++ 中的 gsl_vectors?

How can I import .csv file data into gsl_vectors in C++?

我有一个 .csv 文件,如下所示:

X,Y,Z
0,0,0
0,0,0
-0.00624347,-0.0182673,1.00063
-0.00845628,-0.0374925,1.00058
-0.00494793,-0.0295639,0.927447
-0.00285682,-0.0926582,0.885783
-0.00832563,-0.02957,0.697834

而且我想把它分成三个gsl_vectors(来自GSL:https://www.gnu.org/software/gsl/doc/html/vectors.html) corresponding to the column X, column Y and column Z respectively. The reason why I want to do this is because I later want to use the functions that are implemented in the GNU Scientific Library这个数据。我想强调的是这些功能只能在 gsl_vectors 而不是 std:vectors.

上工作

我的方法:

  1. 将 .csv 中的数据放入 std:vectors,然后将这些向量转换为 gsl_vectors。那没有用。

  2. 将.csv文件中的数据直接放入gsl_vectors:

    #include <iostream>
    #include <fstream>
    #include <istream>
    #include <string>
    #include <sstream>
    #include <algorithm>
    #include <gsl/gsl_linalg.h>
    #include <gsl/gsl_vector.h>
    
    struct acceleration {
        gsl_vector AccX;
        gsl_vector AccY;
        gsl_vector AccZ;
    };
    
    // Function prototypes
    acceleration read_csv(acceleration& A);
    // End function prototypes
    
    int main(void)
    {
        // ==================READ THE CSV=========================
        acceleration data;
        data = read_csv(data);
        printf("/n");
        gsl_vector_fprintf(stdout, &data.AccX, "%lf");
    
        return 0;
    }
    
    acceleration read_csv(acceleration& SA)
    {
        std::string buffer; /* Declare a buffer for the data that will be read */
        std::string bacx, bacy, bacz;
        std::ifstream inputfile;
        inputfile.open("buffer.csv"); /* Open file for reading */
        if (!inputfile.is_open())
        {
            std::cout << "Error opening file" << std::endl;
        }
    
        std::stringstream aux(buffer);
        getline(aux, bacx, ',');
        getline(aux, bacy, ',');
        getline(aux, bacz, ',');
        size_t i{ 0 };
    
        while (getline(inputfile, buffer))
        {
            std::stringstream aux(buffer);
    
            getline(aux, bacx, ',');
            if (bacx.compare("AX") != 0)
                gsl_vector_set(&SA.AccX, i, stod(bacx));
    
            getline(aux, bacy, ',');
            if (bacy.compare("AY") != 0)
                gsl_vector_set(&SA.AccY, i, stod(bacy));
    
            getline(aux, bacz, ',');
            if (bacz.compare("AZ") != 0)
                gsl_vector_set(&SA.AccZ, i, stod(bacz));
            i++;
        }
        inputfile.close();
        return (SA);
    
    }
    

    这在控制台上没有输出,如果我调试它,函数 gsl_vector_set 会抛出异常:

    Exception thrown at 0x7A5EED1A (gsld.dll) in progr.exe: 0xC0000005: Access violation writing location 0x3333332

    gsl_set_vector 的行:v->data[i * v->stride] = x;

  3. 将.csv数据放入gsl_block,然后切片成gsl_vectors。在这里,我在尝试将数据放入块时遇到异常。然后,为了将块切成向量,我假设我必须使用 gsl_vector_alloc_from_block() 函数,但我没有找到任何关于如何使用此函数的示例。我确实需要了解其他人通常如何使用函数,因为我是 C++ 的新手。 这是我到目前为止对这个想法的看法:

    #include <iostream>
    #include <fstream>
    #include <gsl/gsl_linalg.h>
    #include <gsl/gsl_vector.h>
    
    // Function prototypes
    gsl_block read_csv(void);
    // End function prototypes
    
    int main(void)
    {
        // ================== READ THE CSV INTO A BLOCK =========================
        gsl_block data;
        data = read_csv();
        // ================= NOW SLICE THE BLOCK: HOW? ==========================
        // Use gsl_vector_alloc_from_block(), but how?
        return 0;
    }
    
    // Function declarations
    gsl_block read_csv(void)
    {
        FILE* inputfile;
        fopen_s(&inputfile, "buffer.csv", "r"); /* Open file for reading */
        if (inputfile == NULL)
            std::cout << "file does not exist \n";
        fseek(inputfile, 0L, SEEK_END); // Go until the end
        int file_size = ftell(inputfile); // In order to tell the size of the file
        gsl_block* b = gsl_block_alloc(file_size);
        if(inputfile)
            gsl_block_fscanf(inputfile, b);
    
        fclose(inputfile);
    
        return *b;
    
    }
    // End function declarations
    

    如果我 运行 我得到:

    Debug Error! abort() has been called

    并且在控制台上显示:

    gsl: C:\DEV\vcpkg\buildtrees\gsl\src\gsl-2-fb511965d5.clean\block\fprintf_source.c:90: ERROR: fscanf failed Default GSL error handler invoked.

    如果我对此进行调试,gsl_error 函数会抛出异常:

    progr.exe has triggered a breakpoint.

    abort ();

综上所述,我其实是想把.csv文件读入gsl_vectors。如果我的做法不行,也可以理解。

您可以通过以下方式将 CSV 文件读入 gsl 向量:

#include <stdio.h>
#include <string>
#include <iostream>
#include <fstream>
#include <sstream>
#include <gsl/gsl_vector.h>

int main ()
{
  int i = 0, rows = 7;

  // Allocate vectors
  gsl_vector *X = gsl_vector_alloc (rows);
  gsl_vector *Y = gsl_vector_alloc (rows);
  gsl_vector *Z = gsl_vector_alloc (rows);

  // Open the file
  std::ifstream openfile("data.csv");
  openfile.ignore(10000, '\n'); // Ignore the header
  std::string line;

  while (getline(openfile, line, '\n'))
  {
    std::string a, b, c;
    std::stringstream iss(line);
    getline(getline(getline (iss, a, ','), b, ','), c, ',');
    // std::cout << a << ' ' << b << ' ' << c << std::endl;

    // Set vectors
    gsl_vector_set (X, i, std::stod(a));
    gsl_vector_set (Y, i, std::stod(b));
    gsl_vector_set (Z, i, std::stod(c));

    i += 1;
  }

  // Close the file
  openfile.close();

  for(i = 0; i < rows; ++i)
  {
      // Get vectors
      std::cout << gsl_vector_get (X, i) << "\t";
      std::cout << gsl_vector_get (Y, i) << "\t";
      std::cout << gsl_vector_get (Z, i) << "\n";
  }

  // Do some processing with the vectors

  // Free allocated memory at the end
  gsl_vector_free (X);
  gsl_vector_free (Y);
  gsl_vector_free (Z);

  return 0;
}

首先,我使用 ifstream 打开 data.csv 并将每一行读入三个变量(用逗号分隔)。其次,我将它们转换为 double 并将它们存储在 gsl 向量中。最后打印出来验证一下。