Reputation: 248
I'm used to Java but learning C++ and as an experiment I'm trying to create a library that will read a CSV file into a 2d array with user defined import specs, print the array to the console, and then write the array to a separate file.
I'm stuck on how to determine the number of rows (y-axis) to loop through in the 2d array when creating the array, printing the array, and writing the array. I've got the x-axis value, and I've been fiddling around with this:
int y = sizeof(arr) / sizeof(arr[0]);
to try to get it. It got the correct number of rows when I tested the code all in one compiled cpp main, but now that I've moved the functions to an included library it's assigning 0 to y!
Why the difference, and how can I resolve it? In the example below I'm testing a matrix with 6 fields and 4 records, so I'm expecting 4 as the value assigned to y.
Since I've narrowed the problem to this variable, here is a (hopefully) SSCCE of how I'm getting y.
The header file:
#ifndef CSV_IO_H
#define CSV_IO_H
#include <string>
using namespace std;
class csv_io
{
public:
static void csv_to_dbl_arr(string, double arr[][6], char, char);
static void print_dbl_arr(double arr[][6]);
};
#endif
The included library:
#include "csv_io.h"
#include <stdlib.h>
#include <iostream>
#include <fstream>
#include <sstream>
#include <iomanip>
using namespace std;
void csv_io::csv_to_dbl_arr(string inf, double arr[][6], char dlm, char sep)
{
ifstream ifs;
string row, col, val;
int i = 0;
int j = 0;
ifs.open(inf.c_str());
if(ifs.is_open())
{
while(ifs.good())
{
getline(ifs, row, sep);
stringstream col(row);
while(col.good())
{
getline(col, val, dlm);
arr[i][j] = atof(val.c_str());
j++;
}
j = 0;
i++;
}
}
ifs.close();
}
void csv_io::print_dbl_arr(double arr[][6])
{
int x = sizeof(arr[0]) / sizeof(double);
int y = sizeof(arr) / sizeof(arr[0]);
cout << "x: " << x << endl << "y: " << y << endl;
}
The main.cpp:
#include "csv_io.h"
#include "csv_io.cpp"
#include <stdlib.h>
using namespace std;
int main()
{
double d_arr[4][6];
string inf = "file_i.txt";
char in_dlm = ',';
char in_sep = '\n';
csv_io::csv_to_dbl_arr(inf, d_arr, in_dlm, in_sep);
csv_io::print_dbl_arr(d_arr);
return 0;
}
file_i.txt:
1,1,1,1,1,1
2,2,2,2,2,2
3,3,3,3,3,3
4,4,4,4,4,4
I know I could make a counter & track the number of rows in csv_to_dbl_arr but I want to figure out the expression I'm using for y so I can use it on the fly without having to declare it in the main.
Upvotes: 1
Views: 188
Reputation: 3870
When you are passing a integer/float/double array to a function, it means you are passing only the base address of the array (because array name represents base address)
In the following function:
void csv_io::print_dbl_arr(double arr[][6])
{
int x = sizeof(arr[0]) / sizeof(double); // here you are dividing sizeof(address of array) with sizeof(double)
// because arr and arr[0] both represents the base address of the array in 2D array
int y = sizeof(arr) / sizeof(arr[0]); // Its indirectly means that dividing the size of base addresses
cout << "x: " << x << endl << "y: " << y << endl;
}
To avoid this type error whenever you are passing a 1D array to a function you should pass the total no of elements in that array. For 2D array you need to pass the row and column value to the function with array base address.
Hope this will help you!
Upvotes: 1
Reputation: 217135
void print_dbl_arr(double arr[][6])
is equivalent to
void print_dbl_arr(double (*arr)[6])
so
sizeof(arr)
is the size of a pointersizeof(arr[0])
is the size of double (&)[6]
so 6 * sizeof double
.You may use template and passing array by reference to get the size as the following:
template <std::size_t N, std::size_t M>
void print_dbl_arr(double (&arr)[N][M]);
Using std::vector
/std::array
is more intuitive.
Upvotes: 1
Reputation: 14505
double d_arr[4][6];
void csv_io::print_dbl_arr(double arr[][6])
{
int x = sizeof(arr[0]) / sizeof(double);
int y = sizeof(arr) / sizeof(arr[0]);
cout << "x: " << x << endl << "y: " << y << endl;
}
csv_io::print_dbl_arr(d_arr);
When you pass the array d_arr
to print_dbl_arr
, it's decayed into a pointer (double (*arr)[6]
). So sizeof(arr)
is 4 on 32-bit platforms. And arr[0]
is an 1D array of six doubles which has size 48 (assumes sizeof(double)
is 8). The result of the integral division 4/48
is zero.
The same thing happens to an 1D array (in both cases []
specified for the highest dimension). That's why we need pass the number of elements of the array as the other parameter so that the callee can know it.
int arr[4];
void f(int arr[], int n)
{
// The wrong way
// arr is decayed to a pointer, int *arr.
// for (size_t i = 0; i < sizeof(arr); ++i)
// {
// // iterate over the array
// }
// The correct way
for (size_t i = 0; i < n; ++i)
{
// iterate over the array
}
}
Upvotes: 1