I'm trying to populate an array from a .txt that I am reading. I am using this code that I am using as a function to read the file:
double* read_text(const char *fileName, int sizeR, int sizeC)
{
double* data = new double[sizeR*sizeC];
int i = 0;
ifstream myfile(fileName);
if (myfile.is_open())
{
while (myfile.good())
{
if (i > sizeR*sizeC - 1) break;
myfile >> *(data + i);
//cout << *(data + i) << ' '; // Displays converted data.
i++;
}
myfile.close();
}
else cout << "Unable to open file";
//cout << i;
return data;
}
Now when I read the file I am trying to take the elements from the 1D data array and store them into a 2D array.
I've tried to create an array in a public class, however I have no idea on how to move the data that I am reading to a 2D array.
I know it's not very clear but basically I'm doing the nearest neighbour search algorithm to compare 2 images. I have taken one image and converted it into the values using this bit of code above. However now I am trying to store the data that I am reading into a 2D public array?
Here is a more compact version of reading in a 2D matrix:
int quantity = sizeR * sizeC;
double * matrix = new double [quantity];
double value = 0.0;
double * p_cell = matrix;
//...
while ((myfile >> value) && (quantity > 0))
{
*p_cell++ = value;
--quantity;
}
In the above code snippet, a pointer is used to point to the next slot or cell of the matrix (2D array). The pointer is incremented after each read.
The quantity is decremented as a safety check to prevent buffer overrun.
Assuming every double returned represents a pixel. You can define a function that retrieves pixels like so:
double get_pixel(int x, int y, double* data, int sizeC)
{
return data[x + y*sizeC];
}
Where sizeC is the width of the image (number of columns).
You can then use the function above to fill your 2D array like so:
for(int i = 0; i < sizeC; i++)
for(int j = 0; j < sizeR; j++)
my2Darray[i][j] = get_pixel(i, j, data, sizeC);
But then notice how unnecessary this is. You don't really need a 2D array :) keep it simple and efficient.
The function above could be a part of a struct that represents the Image where you'd have sizeC, sizeR and data defined as members.
struct Image
{
int sizeC;
int sizeR;
double* data;
get_pixel(int x, int y)
{
return data[x + y*sizeC];
}
};
Then to access the image pixels you can simply do:
Image img;
// read image data and stuff
double p = img.get_pixel(4, 2);
You can even make it look prettier by overriding the operator() instead of get_pixel so retrieving the pixel would look something like:
double p = img(4, 2);
Related
I am trying to write a function to extract a slice from a given matrix, where the input is 1D and the slice can be 1D or 2D.
I am trying to use the push_back function for this purpose but for some reasons the push_back does not work.
I receive an error in my line OutPut.push_back(DumyValue);
Can anyone help me why I am receiving this error?
Also, it would be appreciated if you can tell me how to solve this issue.
Also, if the first part becomes clear, can anyone tell me how I should use the push_back for inserting an integer in a specific location so I can use it for extracting a 2D slice?
If you remove the line OutPut.push_back(DumyValue); the code should work.
#include<iostream>
#include<vector>
using namespace std;
int MatrixSlice(vector<vector<int>> Input, int Row1, int Row2, int Col1, int Col2) {
//define the slice size, if it is iD or 2D
if (abs(Row1-Row2)>1 && abs(Col1-Col2)>1){
vector<vector<int>> OutPut;
}else{
vector<int> OutPut;
}
int i2;
int j2;
for (int i = Row1; i <= Row2; i++) {
i2=0;
for (int j = Col1; j <= Col2; j++) {
int DumyValue=Input[i][j];
OutPut.push_back(DumyValue);
i2++;
//cout << Input[i][j] << endl;
}
j2++;
}
return 0;
}
int main() {
//Define a matrix for test:
vector<vector<int>> Matrix2(4, vector<int>(5, 1));
int R = 4;
int C = 4;
vector<vector<int>> MatrixInput(R, vector<int>(C, 1));;
for (int i = 0; i < MatrixInput.size(); i++) {
for (int j = 0; j < MatrixInput[0].size(); j++) {
int temp;
temp = i^2+j^2;
MatrixInput[i][j] = temp;
}
}
MatrixSlice(MatrixInput, 0, 3, 1, 1);
printf("\n");
return 0;
}
Matrix slice has a couple problems:
It is impossible define a variable with two possible types and have both active in the same scope.
The return type of int makes little sense. The matrix is sliced up, but then what? It can't be handed back to the caller to do anything with it.
This can be fixed with a union, but yikes! The bookkeeping on that will be a Smurfing nightmare. Don't do it!
The next is to always use a vector of vectors, but I don't like that idea for a couple reasons I'll get into below.
Instead I pitch a simple wrapper object around a single vector. This is done for two reasons:
It preserves the ability to back a 1 dimensional matrix with a 1 dimensional container. If you have many rows of one column, all of the row data remains contiguous and cache friendly.
It tends to be much faster. The data of one vector is contiguous in memory and reaps the rewards of cache friendliness. A vector of vectors is basically a list of pointers to arrays of data, sending the poor CPU on an odyssey of pointer-chasing through memory to find the columns. If the columns are short, this can really, really hurt performance.
Here we go:
template<class TYPE>
class Matrix
{
private:
size_t mNrRows; // note size_t. This is unsigned because there is no reason
// for a matrix with a negative size. size_t is also guaranteed
// to fit anything you can throw at it.
size_t mNrColumns;
std::vector<TYPE> mVec;
public:
// make a default-initialized matrix
Matrix(size_t nrRows, size_t nrColumns) :
mNrRows(nrRows), mNrColumns(nrColumns), mVec(mNrRows * mNrColumns)
{
}
// make a def-initialized matrix
Matrix(size_t nrRows, size_t nrColumns, TYPE def) :
mNrRows(nrRows), mNrColumns(nrColumns), mVec(mNrRows * mNrColumns,
def)
{
}
// gimme a value and allow it to be changed
TYPE & operator()(size_t row, size_t column)
{
// could check for out of bounds and throw an exception here
return mVec[row * mNrColumns + column];
}
//gimme a value and do not allow it to be changed
TYPE operator()(size_t row, size_t column) const
{
return mVec[row * mNrColumns + column];
}
// gimme the number of rows
size_t getRows() const
{
return mNrRows;
}
// gimmie the number of columns.
size_t getColumns() const
{
return mNrColumns;
}
// printing convenience
friend std::ostream & operator<<(std::ostream & out, const Matrix & mat)
{
int count = 0;
for (TYPE val: mat.mVec)
{
out << val;
if (++count == mat.mNrColumns)
{
out << '\n';
count = 0;
}
else
{
out << ' ';
}
}
return out;
}
};
The vector member handles all of the heavy lifting so the Rule of Zero recommends leaving the copy and move constructors, assignment operators, and destructor up to the compiler.
What does this do to MatrixSlice? Well, first it now received and returns a Matrix instead of vector<vector> and int. The insides use Matrix and the confusion about 1D or 2D is just plain gone, resulting in a simpler function.
Matrix<int> MatrixSlice(const Matrix<int> & Input,
int Row1,
int Row2,
int Col1,
int Col2)
{
Matrix<int> OutPut(Row2-Row1 + 1,
Col2-Col1 + 1); // but what if Row1 > Row2?
int i2;
int j2= 0; // definitely need to initialize this sucker.
for (int i = Row1; i <= Row2; i++) // logical problem here: What if Row2 >= input.getRows()?
{
i2 = 0;
for (int j = Col1; j <= Col2; j++) // similar problem here
{
int DumyValue = Input(i, j);
OutPut(j2, i2) = DumyValue;
i2++;
}
j2++;
}
return OutPut;
}
Not that this completely ignores the very logical option of making slice a Matrix method. While it makes sense, it doesn't need to be a method and the stock recommendation is to prefer a free function. One good improvement is to make the function a template so that it can handle all sorts of Matrix in addition to Matrix<int>.
And finally, what happens to main?
int main()
{
//Define a matrix for test:
Matrix<int> Matrix2(4, 5, 1); // initialize matrix to all 1s
int R = 4;
int C = 4;
Matrix<int> MatrixInput(R, C); // default initialize the matrix
for (int i = 0; i < MatrixInput.getRows(); i++)
{
for (int j = 0; j < MatrixInput.getColumns(); j++)
{
int temp;
temp = i ^ 2 + j ^ 2;
// WARNING: ^ is XOR, not exponent. Maybe OP wants i XOR 2, but not
// likely. But if XOR is the desired operation, there is a lurking
// order of operation bug that needs to be addressed
MatrixInput(i, j) = temp;
}
}
std::cout << MatrixInput << '\n';
std::cout << MatrixSlice(MatrixInput, 0, 3, 1, 1);
return 0;
}
In your code
if (abs(Row1-Row2)>1 && abs(Col1-Col2)>1){
vector<vector<int> > OutPut;
// OutPut dies here
}else{
vector<int> OutPut;
// OutPut dies here
}
// here is no OutPut
OutPut lives only to the end of IF statement.
You either use it without the if statement or you add all code that uses it to the if statement.
So I have looked through some online questions to figure out how to setup and fill a dynamic multidimensional array and I thought I had it down but for some reason my function will not access the anything past the first(0) column. For my test I put in a 2X2 array:
2 2 (part of another function that gives the size of the matrix)
1 2
3 4
When I debug it I only get
1 random# from initializing the array
3 random# from initializing the array
I'm not sure what I am doing wrong with this piece of code, I am also new to C++.
double* matrix_read(const int m, const int n)
{
double **mat = new double*[m];
for (int j = 0; j < m; ++j) {
mat[j] = new double[n];
}
for (int i = 0; i < m; ++i) {
for (int j = 0; j < n; ++j) {
cin >> mat[i][j];
}
}
double debug = mat[2][2];
return *mat;
}
Inside the main function this is what I send to the function.
int x, y, m, n;
cin >> x;
cin >> y;
double *mat_a = matrix_read(x, y);
cin >> m; //2nd matrix read in
cin >> n;
double *mat_b = matrix_read(m, n);
Your matrix is represented as an array of pointers, each pointer in the array points, in turn, to an array of doubles. Each of these arrays are contiguous in memory, but not among themselves. This means that, mat[0][0] is right before mat[0][1] in memory. But mat[1][0] may be in a completely different location.
By returning only the first line of your matrix, *mat (the same as mat[0]), you will lose information. All you have access to is the first line.
You should return the whole matrix.
double** matrix_read(...) {
...
return mat;
}
(Edit: Besides, someone will have to delete the matrix later.. and they have to delete several arrays, ugh. You should make a structure wrapper for matrices, or use a single array, or use a vector of vectors)
How can I pass a 2D array into a function and use it like myArray[i][j] but without knowing the size of that array inside that function?
I can know the size inside the main.
I want to use it like this:
TGraph *myGraph = new TGraph(nValues, myArray[0][j], myArray[1][j]);
// I'll not use a loop for j, since TGraph receives all the values in the array,
like "x values" and "y values"
If I do it like this it works, but I would have to pass to the function Col1 and Col2 that are two 1D arrays:
main() {
...
graphWaveTransmittance("a", nValues, Col1, Col2,
" Au ", "Evaporated", "thickness 5nm", kGreen+1);
...
}
void graphWaveTransmittance(char *n, int nValues, float Param1[], float Param2[],
char *title, char *header, char *entry, Color_t color) {
TGraph *myGraph = new TGraph(nValues, Param1, Param2);
...
}
The Array:
float valuesArray[nCol][nValues];
for(int y=0; y<nValues; y++){
for (int i=0; i<nCol; i++) {
valuesArray[i][y] = values[i][y];
}
i=0;
}
Note: I've made it like this because values[ ][ ] is an array with values that are read from a text file. Before read the file I don't know how many lines are going to be necessary. With this second array (valuesArray[ ][ ]) I can make it to have just the size of the number of values that are read.
Firstly, I've put all the values in values[ ][ ] with "-1" and it's size very large. Then I've counted the number of lines and just used that value for valuesArray[ ][ ]. This is the first array with values (the large one):
const int nCol = countCols;
float values[nCol][nLin];
// reads file to end of *file*, not line
while(!inFile.eof()) {
for(int y=0; y<nLin; y++){
for (int i=0; i<nCol; i++) {
inFile >> values[i][y];
}
i=0;
}
}
One other question, I've seen that "while(!inFile.eof())" shouldn't be used. What can I use instead? (I don't know the total number of lines from the .txt file at this point)
Importing values in columns in a .txt, till now I have:
vector<vector<float> > vecValues; // your entire data-set of values
vector<float> line(nCol, -1.0); // create one line of nCol size and fill with -1
bool done = false;
while (!done)
{
for (int i = 0; !done && i < nCol; i++)
{
done = !(inFile2 >> line[i]);
}
vecValues.push_back(line);
}
The problem of this is that the values are like vecValues[value][column number from .txt]
I want to have vecValues[column number from .txt][value].
How can I change it?
I'm reading from the file like this:
main() {
...
vector < vector <float> > vecValues; // 2d array as a vector of vectors
vector <float> rowVector(nCol); // vector to add into 'array' (represents a row)
int row = 0; // Row counter
// Dynamically store data into array
while (!inFile2.eof()) { // ... and while there are no errors,
vecValues.push_back(rowVector); // add a new row,
for (int col=0; col<nCol; col++) {
inFile2 >> vecValues[row][col]; // fill the row with col elements
}
row++; // Keep track of actual row
}
graphWaveTransmittance("a", nValues, vecValues, " Au ",
"Evaporated", "thickness 5nm", kGreen+1);
// nValues is the number of lines of .txt file
...
}
//****** Function *******//
void graphWaveTransmittance(char *n, int nValues,
const vector<vector <float> > & Param, char *title, char *header,
char *entry, Color_t color) {
// like this the graph is not good
TGraph *gr_WTransm = new TGraph(nValues, &Param[0][0], &Param[1][0]);
// or like this
TGraph *gr_WTransm = new TGraph(Param[0].size(), &Param[0][0], &Param[1][0]);
Note: TGraph can accept floats, my previous arrays were floats
Do you know why the graph is not appearing correctly?
Thank you
I ran into a similar problem recently. I ended up using two dimensional vectors, which don't need to know the inner dimension when passed to a function.
Declare vectors like this
vector< vector<int> > vec(xRange, vector<int>(yRange, initialValue));
While replacing xRange with your size in the x dimension, yRange with your size in the y direction, and initialValue with what you want to initialize your 2d vector with.
At this point, you can access or update vector contents using
vec[x][y]
To pass this to a function, use this
void myFunc(std::vector< std::vector<int> >& vec) {
Be sure to
#include <vector>
You can use vectors to sove this problem as Michael Parker already mentioned. To make it work in root with graphs, note that TGraph expects two arrays of double or float as parameters.
Therefore you have to use
std::vector<std::vector<double> >
or
std::vector<std::vector<float> >
in your case.
Then your function looks like:
void drawGraph(const std::vector<std::vector<double> > & data)
{
TGraph* graph = new TGraph(data[0].size(), &data[0][0], &data[1][0]);
//...
}
The &data[0][0] "converts" the vectors to arrays as needed by TGraph.
Concerning your second question, instead of using !inFile.eof(), I typically directly ask whether the reading process was succesful, i.e. in your case:
if(!(inFile >> values[i][y]))
{
//at end of file
}
I prefer to use this in a while loop but thats a matter of taste.
By the way, by using vectors you no longer need to run though the whole file in advance to count the number of lines, just use push_back(...).
If you do not know the number of lines nor the number of columns, you can use getline to read out the file and to determine the number of columns:
std::vector<std::vector<float> > data;
std::string buffer;
getline(infile,buffer)//I do not check that the file has at least one line here
istringstream firstLine(buffer);
float value;
while(firstline >> value)
{
data.push_back(std::vector<float>(1,value));
}
while(getline(infile,buffer))
{
istringstream line(buffer);
float value;
unsigned int counter = 0;
while(line >> value)
{
data[counter].push_back(value));
counter++;
}
}
Note that this requires:
#include<sstream>
and that this assumes that the number of columns does not change over the file size.
I have read columns from a .txt file (the file has at the beginning the number of columns (nCol)) and put the values into an array (float values[nCol][nLin]).
Now, I want to copy the values (ex.: values[0][nLin], values[1][nLin]...) into different float arrays depending on the number of columns.
How can I crate float arrays for each column if the number of columns my change depending on the file I am reading?
//------ Declares Array for values ------//
const int nCol = countCols;
float values[nCol][nLin];
// Fill Array with '-1'
for(int c=0; c<nCol; c++){
for(int l=0; l<nLin; l++) {
values[c][l] = -1;
}
}
//------ Skips the reading of line of values file ------//
getline(inFile, dummyLine);
// reads file to end of *file*, not line
while(!inFile.eof()) {
for(int y=0; y<nLin; y++){
for (int i=0; i<nCol; i++) {
inFile >> values[i][y];
}
i=0;
}
}
const int nValues = countLines;
float Col1[nValues]=-1,
Col2[nValues]=-1,
Col3[nValues]=-1,
Col4[nValues]=-1,
Col5[nValues]=-1;
//------ Put values in specific Arrays ------//
for(int v=0; v<nValues; v++) {
Col1[v] = values[0][v];
Col2[v] = values[1][v];
Col3[v] = values[2][v];
Col4[v] = values[3][v];
Col5[v] = values[4][v];
}
cout << endl;
I want that float Col1[] to be from 1 to nCol, the last one to be float ColnCol[]
The best way IMO would be to use std::vector< std::vector<float> >
You do not need to make different 1D columns as you can manipulate this vector of vector as you want.
Instead you should use std::vector. It is a better choice for dynamic size allocation of a data type.
I got a problem. I'm trying to create a dll which can calculate the distance between 2 points when i send in 2 different sets of values.
However, when I send in my 2nd set of values in, I realise my first set of values have gone missing in the array ( the array is used to store the values)
Below is my code:
int click = 0; //click is used to measure the number of times i have clicked, ie to say the number of times im injecting new (a,b) points into the function below.
double MeasureDistance(double a, double b)
{
/******* Create Array to Store The Points ********/
/** Initializing the array **/
double xDistance =0;
double yDistance =0;
double TDistance = 0;
static double **Array;
int column = 0; //used to toggle the column number
int width = 100;
int height = 100;
Array = new double *[width];
for (int i=0; i <width; i++)
{
Array [i] = new double [height];
}
/*** Now a and b are stored inside the Array[0][0] ***/
for (column =0; column <2; column ++)
{
if ((column % 2)==0)
{
Array [click][column] = a; //storing at [0,0]
}
else
{
Array [click][column] = b; //storing at [0,1]
}
}
for (int row = 2; row < click; row ++)
{
for (column = 0; column <2; column ++)
{
if ((column % 2) == 0)
{
xDistance = Array [0][column] - Array [row][column];
}
else
{
yDistance = Array [0][column] - Array [row][column];
}
}
TDistance = sqrt((xDistance * xDistance) + (yDistance * yDistance));
}
/*** Clearing up of array ***/
for (int i = 0; i < width; i++)
{
delete[] Array[i];
}
delete[] Array;
click++;
return TDistance ;
}
I realise that when I inject my 2nd set of a and b values in, my values in array [0][0] and [0][1] goes missing but my 2nd set of values are stored in [1][0] and [1][1]. Any idea how i can run this script without losing the previous values?
Thanks loads in advance. Code edited to clear some queries.
With the line Array = new double *[width]; you are initialising your array in every function call. If you need to store values (I very much doubt) it is better to use an static initialised vector. But generaly it is a very bad idea to let the result of a function depend on former calls. If you realy need to accumulate state, think about creating a function object for this purpose.
Edit:
With a function object you can change the behavior of the algorithm with changing operator() and the datastructure to hold your data via member variables.
2nd Edit:
You probably want something like this:
struct MeasureDistance {
double last_x;
double last_y;
MeasureDistance() : last_x(0), last_y(0) {}
double operator()(double new_x, double new_y) {
double diff_x=last_x-new_x;
double diff_y=last_y-new_y;
double result=sqrt(diff_x*diff_x,diff_y*_diff_y);
last_x=new_x;
last_y=new_y;
return result;
};
MeasureDistance md;
cout
<< md(0.0, 1.0) << '\n' //prints 1
<< md(2.0, 1.0) << '\n' //prints 2
;