Reading arbitrary array of any size - c++

The following code works fine when reading two .txt files containing two 5X5 array.
#include <iostream>
#include <string>
#include <fstream>
#include <sstream>
#include <stdio.h>
#include <vector>
#include <sstream>
using namespace std;
int main()
{
string myFile, mysecondFile, mystring;
string DIR;
string extension;
int total = 0;
int number_of_lines = 0;
string line;
extension = ".txt";
DIR = "H:\\Year2\\EE273\\EE273\\Week6\\";
cout << "Enter the name of the file: \t";
cin >> myFile;
cout << "Enter the name of the second file: \t";
cin >> mysecondFile;
myFile = DIR + myFile + extension;
mysecondFile = DIR + mysecondFile + extension;
ifstream inFile;
ifstream inFile2;
int i=5;
int j=5;
int i2=5;
int j2=5;
int i3=5;
int j3=5;
int k;
int l;
int Array[5][5];
int Array2[5][5];
int Array3[5][5];
string attempt1,attempt2;
int row = 0;
int col = 0;
int row2 = 0;
int col2 = 0;//i = row
//y = column
inFile.open(myFile.c_str());
if (!inFile) {
cout <<"Error opening file"<<myFile<<endl;
return -1;
}
while (!inFile.eof())
{
getline(inFile, attempt1);
stringstream iss( attempt1 );
string result;
col = 0;
while (getline( iss, result, ','))
{
//cout << result << endl;
Array[row][col] = atoi(result.c_str());
//j = j + 1;
col = col + 1;
}
row = row + 1;
}
inFile.close();
inFile2.open(mysecondFile.c_str());
if (!inFile2) {
cout <<"Error opening file"<<mysecondFile<<endl;
return -1;
}
while (!inFile2.eof())
{
getline(inFile2, attempt2);
stringstream iss( attempt2 );
string result2;
col2 = 0;
while (getline( iss, result2, ','))
{
//cout << result2 << endl;
Array2[row2][col2] = atoi(result2.c_str());
col2 = col2 + 1;
}
row2 = row2 + 1;
}
inFile2.close();
/*for (int i=0;i<5;i++){
for (int j=0; j<5; j++){
cout<<Array[i][j]<<endl;}}
for (int i2=0;i2<5;i2++){
for (int j2=0; j2<5; j2++){
cout<<Array2[i2][j2]<<endl;
}}
Here I am carrying out the multiplication between the two matrices and writing the resulting values to a third matrix.
int Total=0;
i=0;
j2=0;
j=0;
j3=0;
for (i3=0; i3<5; i3++) {
while(j3<5){
while (j<5){
for (i2=0;i2<5;i2++){
Total += Array[i][j]*Array2[i2][j2];
j++;
Array3[i3][j3]=Total;
}}
j=0;
j2++;
j3++;
Total=0;
}
i++;
j=0;
j2=0;
j3=0;
Total=0;
}
My question is: what is the easiest way to modify the code so that it can read two .txt files containing an array of any size and then carry out the multiplication successfully?
EDIT I have to do this using arrays only, I can't use vectors unfortunately.
Am I correct in thinking the new operator is involved?

The "easiest" way would be to do something naive, like reading the file once fully to get the number of rows/cols, then reading the file again to actually store the values in the matrix:
unsigned int rows = 0;
unsigned int cols = 0;
std::string line;
while (std::getline(inFile, line)) {
rows++;
std::stringstream ss(line);
std::string col;
while (std::getline(ss, col, ',')) {
cols++;
}
}
// Now allocate the rows*cols matrix
int** matrix = new int*[rows];
for (int i = 0; i < rows; i++) {
matrix[i] = new int[cols];
}
// and read your values into the matrix ...
// matrix[m][n] = xxx
It's pretty inefficient to read a file twice; and there are other ways to obtain the size beforehand. For example you could have a convention in your input file to include the matrix width/height before the data:
[infile.txt]
3,3
1,2,3
4,5,6
7,8,9
Now you can read the first line of the file, and you'll know that the rest of this file contains a 3x3 matrix. Allocate your matrix with new (similar to above example), then continue to read the rest of the file into it.
Remember to clean up your dynamically allocated matrices with delete[]. There should be 1 call to delete for every call to new.
for (int i = 0; i < rows; i++) {
delete[] matrix[i];
}
delete[] matrix;

Use std::vector instead of raw arrays. E.g. you can push_back an item on a vector. And more crucially, you can create it with a size known only at run-time, e.g. from information in a file.

The easiest approach requires the file to contain the size of the matrix as its first entries. With that, you can fallback to using C (C++ does not tolerate matrices of dynamic size) and do the following:
Read the dimension of the matrix into variables width and heigh.
Allocate the matrix using
int (*dynamicMatrix)[width] = malloc(height*sizeof(*dynamicMatrix));
Reuse your code to fill the matrix.
If you can't fall back to C, and can't use std::vector<>, the only thing left to you is to use a double pointer:
int**dynamicMatrix = new int*[height];
for(size_t i = width; i--; ) dynamicMatrix[i] = new int[width];
Again, this is easiest if you can define the first two numbers in a file to contain the width and height of the matrix in the file. If you can't code these two numbers into your file, you have to grow your dynamic arrays as you go:
size_t lines = 0, allocatedLines = 8;
int** dynamicMatrix = new int*[allocatedLines];
while(/* can read a line */) {
if(lines == allocatedLines) {
int** temp = new int*[allocatedLines *= 2];
for(size_t i = lines; i--; ) temp[i] = dynamicMatrix[i];
delete[] dynamicMatrix;
dynamicMatrix = temp;
}
//add one line
size_t curLineLength = 0, allocatedLineLength = 8;
dynamicMatrix[lines++] = new int[allocatedLineLength];
//fill the line
...
}
A similar block for reallocating a line would need to go into the loop where you read the elements of a single line. This is tedious; but the only way to get better is to use stuff that you are not allowed to use.
Btw: even the reallocating stuff is easier in C, since it provides the realloc() function:
size_t lines = 0, allocatedLines = 8;
int** dynamicMatrix = malloc(allocatedLines * sizeof(*dynamicMatrix));
while(/* can read a line */) {
if(lines == allocatedLines) {
//realloc takes care of copying the data to a new location (if that is necessary):
allocatedLines *= 2;
dynamicMatrix = realloc(dynamicMatrix, allocatedLines * sizeof(*dynamicMatrix));
}
//add one line
size_t curLineLength = 0, allocatedLineLength = 8;
dynamicMatrix[lines++] = malloc(allocatedLineLength * sizeof(**dynamicMatrix));
//fill the line
...
}
Since there is no equivalent to realloc() to work with new/delete, you are required to either use std::vector<> in C++, or to do the copying yourself as above.

Related

How do I read from a file into a 2d array?

I'm working on a program that plays a matching game with the user. The code compiles but when I try to run it, the table that appears has garbage values in it.
My input files look like this:
//p4data1.dat
A
F
B
D
C
E
F
B
D
E
A
C
//p4data2.dat
F
B
D
C
A
F
E
A
C
D
B
E
and my current code is:
void fileAndRandom(char letArr[][COLUMN], int rows, int columns) {
int random = rand() % 2 + 1;
ifstream readFile;
if(random == 1) {
readFile.open("p4data1.dat");
for(int i = 0; i < rows; i++) {
for(int k = 0; k < columns; k++) {
readFile >> letArr[i][k];
}
}
}else if(random == 2) {
readFile.open("p4data2.dat");
for(int b = 0; b < rows; b++) {
for(int a = 0; a < columns; a++) {
readFile >> letArr[b][a];
}
}
}
readFile.close();
}
I'm stuck on how to read it in. Also i can't use vectors because I haven't been taught to do so yet.
You should use std::vector instead of array because std::vector is a variable size container and you don't always know how many elements the input.txt file contains. The complete working program below shows how to read from a text file and store that information in a 2D std::vector
#include <iostream>
#include <vector>
#include <string>
#include <sstream>
#include<fstream>
int main() {
std::string line, word;
std::ifstream inFile("input.txt");
//create/use a std::vector instead of builit in array
std::vector<std::vector<std::string>> vec;
if(inFile)
{
while(getline(inFile, line, '\n'))
{
//create a temporary vector that will contain all the columns
std::vector<std::string> tempVec;
std::istringstream ss(line);
//read word by word
while(ss >> word)
{
//std::cout<<"word:"<<word<<std::endl;
//add the word to the temporary vector
tempVec.push_back(word);
}
//now all the words from the current line has been added to the temporary vector
vec.emplace_back(tempVec);
}
}
else
{
std::cout<<"file cannot be opened"<<std::endl;
}
inFile.close();
//lets check out the elements of the 2D vector so the we can confirm if it contains all the right elements(rows and columns)
for(std::vector<std::string> &newvec: vec)
{
for(const std::string &elem: newvec)
{
std::cout<<elem<<" ";
}
std::cout<<std::endl;
}
/*another way to print out the elements of the 2D vector would be as below
for(int row = 0; row < vec.size(); ++row)
{
for(int col = 0; col < vec.at(row).size(); ++col)
{
std::cout<<vec.at(row).at(col)<<" ";
}
std::cout<<std::endl;
}
*/
return 0;
}
The output of the above program can be seen here. At the end of my program i have printed out the elements of the 2d vector so that we can confirm if it contains all the elements correctly.
The advantage of using std::vector is that you don't have to know the number of rows and columns beforehand in your input file and there is no need to pass(or allocate memory for) row and column.

HW Help - Reading from file character by character C++

For a project I am currently working on, I have to read from a file and depending on the certain character in the file, output either a 1 or 0 to an array.
So here is an example of file input:
* * *
* * *
** ** **
*** *
And here is the function I have written to handle this:
void input (int cellGrid[][MAX]) //takes info from a .txt and puts it into an array
{
ifstream infile; //declare a file variable
int row;
int column;
int number;
infile.open("life.txt"); //open a file
while(infile>>row>>column) { //inserts bacteria places into array
cout << row << " " << column << endl;
cellGrid[row][column]=1; //makes it equal one if bacteria is present
}
infile.close(); //closes file
}
My thinking was that the function needs to see if there is a character that exists and if so, place a 1 in its respective position ([row][column]) in the array. However with this current code, nothing is input into my array.
Generally in C++ use std::vector wherever possible.
Array example:
You have to go through the file and record position of each *. Then set it to 1 for that position. Something like the following (we use getline and i as counter for rows, then we loop through the line using j as counter for columns):
#include <fstream>
#include <string>
using namespace std;
void input(int cellGrid[][100]) {
ifstream infile;
infile.open("life.txt");
int i = 0;
for (string line; getline(infile, line); ++i)
{
for (size_t j = 0; j < line.size(); ++j) {
if (line[j] == '*') {
cellGrid[i][j] = 1;
}
}
}
infile.close();
}
Vector example #1:
Here you can find a solution using std::vector. It will be always in a size rows x columns. One thing it requires is to pass default constructed vector and not constructed with vector(size_type count); c-tor. You can write your own version that doesn't have this problem:
#include <fstream>
#include <string>
#include <vector>
using namespace std;
void input(vector<vector<int>> &cellGrid) {
ifstream infile;
infile.open("life.txt");
int i = 0;
for (string line; getline(infile, line); ++i)
{
cellGrid.push_back(vector<int>(line.size()));
for (size_t j = 0; j < line.size(); ++j) {
if (line[j] == '*') {
cellGrid[i][j] = 1;
}
}
}
infile.close();
}
int main() {
vector<vector<int>> cellGrid;
vector<vector<int>> cellGrid2(100);
input(cellGrid);
//input(cellGrid2); - THIS WILL THROW AN EXCEPTION
return 0;
}
Vector example #2:
It would be even better for you function to return a newly created and populated vector:
#include <fstream>
#include <string>
#include <vector>
using namespace std;
vector<vector<int>> input() {
ifstream infile;
infile.open("life.txt");
vector<vector<int>> cell_grid;
int i = 0;
for (string line; getline(infile, line); ++i)
{
cell_grid.push_back(vector<int>(line.size()));
for (size_t j = 0; j < line.size(); ++j) {
if (line[j] == '*') {
cell_grid[i][j] = 1;
}
}
}
infile.close();
return cell_grid;
}
int main() {
auto vec = input();
return 0;
}
My thinking goes like this:
set row to 0
while can read a line from file
set column to 0
for each character on line
if character is '*'
set cellGrid(row,column) to 1
else
set cellGrid(row,column) to 0
increment column
increment row
You may want additional logic to trap row or column trying to go out of bounds or characters that aren't ' ' or '*'.

How do I fit in a comma separated number matrix into a dynamically allocated array in C++?

I have a file that stores a number matrix of unknown shape in format like
-1,4,12,5.7
2.1,3,-10,3.3
7.1,1.11,12,10
I attempt to store the matrix in a dynamically allocated array because I cannot hard code the number of row and column. For this part, I used pointer-to-pointer and a demo is as below,
#include <iostream>
using namespace std;
int main()
{
// Rather than user input, I need to change this part to deciding the shape of the matrix myself
int row, col;
cout << "Enter row number and column number, separated with a space:\n";
cin >> row >> col;
int** p_p_grid = new int* [row];
for(int i = 0; i < row; i++)
{
p_p_grid[i] = new int[col];
}
// Fill in the entries
for(int i = 0; i < row; i++)
{
for(int j = 0; j < col; j++)
{
// (i + 1) * (j + 1) needs to be replaced by true entries in the matrix
p_p_grid[i][j] = (i + 1) * (j + 1);
}
}
return 0;
}
But what is an efficient way to decide the shape of a comma separated number block before assigning the number one by one? And also how do I import a CSV-structured matrix in C++? (For some reason, I don't want to use a vector type, so please focus on an array)
what is an efficient way to decide the shape of a comma separated
number block before assigning the number one by one?
Assuming you're reading from a file stream, the easiest way, would be to read the file twice: one for counting rows and commas, on for doing the real input.
Here an example of how to detect the end of the matrix, stoping when the number of elements of a new line don't match the format of the matrix:
int nrows=1, ncols=0;
string line;
while (getline(ifs, line)) {
int n=1;
for (auto x: line) // count commas in the line
if (x==',')
n++;
if (!ncols)
ncols = n; // first line sets th enumber of columns
else if (n == ncols) // subsequent lines increase the row count
nrows++;
else break; // unless the format does'n match anymore
}
ifs.clear(); // remove eof
ifs.seekg (0, ifs.beg); // rewind
Online demo
What causes lack of efficiency in this approach, is that you read the file twice. For this reason, by the way, you can't use this approach for reading cin: you can't rewind.
You can optimize this either by caching the lines read (but you'd need to manage a rowing array of strings, as you're not allowed to use vectors), or by letting the matrix grow dynamically (which no longer correspond to your question as this would not provide the matrix size upfront).
how do I import a CSV-structured matrix in C++
Within each line, just read the doubles, followed by a char (which should be the ','):
char forget_me;
for (int i=0; i<nrows; i++)
for (int j=0; j<ncols; j++) {
cin >> p_p_grid[i][j];
if (j<ncols-1)
cin>>forget_me;
}
I know you didn't want a vector-based solution, but here's one anyway
int main() {
ifstream input("input.txt");
if(!input) {
cerr << "couldn't open file" << endl;
exit(1);
}
double number;
vector<vector<double>> matrix;
vector<double> current_row;
while(input >> number) { // loop once for each number in the file
current_row.push_back(number);
int next_char = input.get(); // should be ',' or '\n'
if(next_char == '\n') {
// current row is finished
matrix.push_back(current_row);
current_row.clear();
}
}
// now print the matrix back out again
for(auto const & one_row : matrix) {
for(auto one_number : one_row) {
cout << "\t," << one_number;
}
cout << endl;
}
}
It a bit fiddly. Use either C++ iostream or C stdio.h, and read in a whole line. So if using getline / fgets, you need a very big buffer, say 8k. Now for the first line, parse into fields. For a first attempt, simply count the commas, but the actual rules are more complicated than that.
The go through line by line, extracting the data. Since you've no say over the number of rows, you've no choice other than to dynamically grow the buffer for each line. An STL vector makes this easy for you - just push it back and the buffer will grow. However if you want you can use this structure
int **p_p_grid = 0;
int Nrows = 0;
int Ncolumns = 0;
/* ( for first line, fill the number of columns) */
/* for each line */
p_p_grid = realloc((Nrows + 1) * sizeof(int *));
if(!p_p_grid)
memory_failure();
p_p_grid[Nrows] = malloc(Ncolums * sizeof(int));
if(!p_p_grid[Nrows])
memory_failure();
for(i=0;i<Ncolumns;i++)
p_p_grid[Nrows][i] = /* parse logic here */
Nrows++;
As noted, I would use std::vector instead. Considering that each row have a fixed number of elements, I would also be using std::array. Perhaps doing something like this:
#include <vector> // For std::vector
#include <array> // For std::array
#include <string> // For std::string and std::getline
#include <fstream> // For std::ifstream
#include <sstream> // For std::isstream
int main()
{
std::vector<std::array<double, 4>> grid;
std::ifstream input{"input.txt"};
std::string line;
// Outer loop reads the rows
while(std::getline(input, line))
{
int i = 0;
std::istringstream iss{line};
std::array<double, 4> values;
double value;
// Inner loop extracts the values on each row
while (iss >> value)
{
values[i] = value;
// Skip over the comma
iss.ignore(std::numeric_limits<std::streamsize>::max(), ',');
}
grid.push_back(values);
}
// Now print the values
int row_number = 1;
for (auto const& row : grid)
{
std::cout << "Row " << row_number++ << ": ";
for (auto const value : row)
{
std::cout << value << ' ';
}
std::cout << '\n';
}
}
Note that I haven't actually tested the code above. It compiles cleanly though.

How to calculate something in c++?

I am brand new in C++ and data structure. So I am learning and any advice is appreciated. I am trying to extract a csv file which looks like the following in notepad.
Sig1,Sig2,Sig3,Sig4,Sig5,Sig6,Sig7,Sig8
45,200,45,200,45,200,45,200
45,200,45,200,45,200,45,200
45,200,45,200,45,200,45,200
45,200,45,200,45,200,45,200
45,200,45,200,45,200,45,200
45,200,45,200,45,200,45,200
45,200,45,200,45,200,45,200
45,200,45,200,45,200,45,200
I want to calculate the moving average for each column and print out the results for each column. I do know how to read and print the whole csv file by rows and I also know how to calculate the moving average. But I am finding it difficult to put the two things together because I want to calculate the results by "columns" and not rows.I want to use vector(queue(string)) to read the file.
My idea: Suppose I want to read the 1st cell of the row and put it in queue1, the next in queue2 and so on, then I move on to the 2nd row and repeat the process. So the first column would be vector of queue1, then 2nd column would be vector of queue2 and so on. Then I perform moving average for each vector of queue (or column).
Does this sound like a viable idea? Check my code below.
I used the last code of this link to get an idea about how to extract the table from a csv file:
How to read-write into/from text file with comma separated values
#include "stdafx.h"
#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
#include <queue>
using namespace std;
void readCSV(istream &input, std::vector< std::queue<std::string> > &output)
{
//fstream file("c://data//test_data.csv", ios::in);
string csvLine;
// read every line from the stream
while( getline(input, csvLine) )
{
istringstream csvStream(csvLine);
queue<string> csvColumn;
string csvElement;
// read every element from the line that is seperated by commas
// and put it into the vector or strings
while( getline(csvStream, csvElement, ',') )
{
csvColumn.push(csvElement);
}
output.push_back(csvColumn);
}
}
int main()
{
ofstream myfile;
string sig;
fstream file("c://data//test_data.csv", ios::in);
if(!file.is_open())
{
cout << "File not found!\n";
return 1;
}
// typedef to save typing for the following object
typedef queue<string> Q;
typedef vector<Q> csvVector;
csvVector csvData;
const int Number_Size = 8;
int n =8;
double sum1 = 0.0;
double movingAverage = 0.0;
readCSV(file, csvData);
// Read data and perform moving average for each column
for(csvVector::iterator i = csvData.begin(); i != csvData.end(); ++i)
{
for(vector<Q>::iterator j = i ->begin(); j !=i ->end(); ++j)
{
for (int i = 0; i <= (Number_Size - n); i++)
{
sum1 = 0.0;
for( int i=0; int j = i; j < i + n; j++)
{
sum1 += sig[j];
movingAverage = sum1/n;
cout << movingAverage << endl;
}
}
}
}
myfile.close();
system("pause");
}
The problem with your approach is the way how you parse the csv file and store it. Your code creates a queue holding strings for each row and adds all created queues in a vector. This becomes problematic when you now want to iterate through a column.
Try to create a vector for each element you find in the first row. When processing any other row than the first, access the already existing vectors and add the strings. If you follow this approach, you will end up with vectors holding the content of the columns instead of the rows as it stands now. Here is some sample code:
void readCSV(istream &input, vector<vector<string>>& vOutput)
{
int iRowCnt = 0;
string csvLine;
// read every line from the stream
while( getline(input, csvLine) )
{
int iColCnt = 0;
istringstream inpStreamLine(csvLine);
string strElement;
// read every element from the line that is separated by commas
while( getline(inpStreamLine, strElement, ',') )
{
// if first line, create vector for each column
if (iRowCnt == 0)
{
vector<string> vColumn;
vOutput.push_back(vColumn);
}
// access the vector with index iColCnt and add sub string
vOutput.at(iColCnt).push_back(strElement);
iColCnt++;
}
iRowCnt++;
}
}
void getNumericValues(vector<vector<string>> &vColumns, vector<vector<int>>& vOutput)
{
// iterate across rows (signals)
for (vector< vector<string> >::iterator iterCol = vColumns.begin() ; iterCol != vColumns.end() ; ++iterCol)
{
vector<int> vColumn;
vector<string> *vCol = &(*iterCol);
// iterate across columns (signal values) while skipping first line
// convert strings to integer values and add them to vNumValues
for (vector<string>::iterator iterRow = vCol->begin()+1; iterRow < vCol->end(); ++iterRow)
{
string strElem = *iterRow;
string::size_type sz;
vColumn.push_back(stoi(strElem, &sz));
}
vOutput.push_back(vColumn);
}
}
void getMovingAveragesColumn(vector<int> &vNumValues, int iWndSize, vector<int>& vOutput)
{
if (vNumValues.size()<iWndSize) // check if we have enough values
return;
for (vector<int>::iterator iter = vNumValues.begin() ; iter < vNumValues.end()-iWndSize ; ++iter)
{
int iMovAvg = 0;
for (int ii=0; ii<iWndSize; ii++)
{
iMovAvg+= *(iter+ii);
}
iMovAvg /= iWndSize;
vOutput.push_back(iMovAvg);
}
}
void getMovingAveragesMatrix(vector<vector<int>> &vNumValues, int iWndSize, vector<vector<int>>& vOutput)
{
for (vector<vector<int>>::iterator iterCol = vNumValues.begin() ; iterCol < vNumValues.end() ; ++iterCol)
{
vector<int> *vCol = &(*iterCol);
vector<int> vMovAvg;
getMovingAveragesColumn(*vCol, iWndSize, vMovAvg);
vOutput.push_back(vMovAvg);
}
}
int _tmain(int argc, _TCHAR* argv[])
{
ofstream myfile;
fstream file("c://tmp//test_data.csv", ios::in);
if(!file.is_open())
{
cout << "File not found!\n";
return 1;
}
// vector of vectors for storing strings in matrix form
vector<vector<string>> vData;
readCSV(file, vData);
// convert to integers
vector<vector<int>> vNumValues;
getNumericValues(vData, vNumValues);
// get moving average values
vector<vector<int>> vMovAverages;
getMovingAveragesMatrix(vNumValues, 3, vMovAverages);
// print the moving average values
for (vector<vector<int>>::iterator iterCol = vMovAverages.begin() ; iterCol < vMovAverages.end() ; ++iterCol)
{
vector<int> *vCol = &(*iterCol);
for (vector<int>::iterator iterRow= vCol->begin() ; iterRow < vCol->end() ; ++iterRow)
{
cout<< *iterRow << " ";
}
cout<<"\n";
}
myfile.close();
system("pause");
}

C++ I/O numbers in text file

I'm trying to read numbers from a test file and display them in a matrix. In the text file, there is one number per line. The first two lines are the dimensions of the matrix.(3 and 4) I'm having trouble assigning the actual data values of these numbers to the matrix. In this case Values 2 through 14.
#include <iostream>
#include <fstream>
#include <iomanip>
#include <stdlib.h>
using namespace std;
#include "Matrix.h"
int main()
{
CMatrix A(10,10); //set to arbitrary size
int x;
int i = 0;
int number;
int rowsFile;
int columnsFile;
while ( myFile.good()&& myFile.is_open() )
{
myFile>>x;
if (i==0){ //for row dimension
rowsFile = x;
}
if (i==1){ //for column dimension
columnsFile = x;
}
cout<<"Value "<<i<<": "<<x<<endl; //displays the values
if (i>=2){
for (int r = 0; r < rowsFile; r++)
{
for (int c = 0; c < columnsFile; c++)
{
A.Value(r,c) = x;
myFile>>x;
}
}
myFile.close();
}
i=i+1;
}
myFile.close();
CMatrix A(rowsFile, columnsFile);
cout<<endl<< "Rows: "<<A.getNumberOfRows()<<endl;
cout<< "Columns: "<<A.getNumberOfColumns()<<endl;
cout<<endl<<A.ToString();
}
Here is a display of my output.
For some reason my commented out loop doesn't seem to be working.
Any help would be appreciated. Thank you!
While I can't offer you a complete solution due not completely understanding what you're trying to do, I recommend reading the contents of the file line wise and storing them in a vector, as in this example:
std::ifstream ifs("file.txt");
std::string line;
std::vector<std::string> lines;
if (ifs.good()) while (getline(ifs, line)) lines.push_back(line);
else throw std::runtime_error("An error occurred while trying to read from file.");
This makes it easier to work with the data.
I suggest you reorganize this code to place doubles into matrix elements immediately after reading them.
The file io code may not be perfect, but I would separate the reading of the number of rows and columns from the loop that handles the element values.
// do not declare i here
int numRows;
int numCols;
std::fstream inputFile("filename", std::in);
if ! (inputFile >> numRows >> numCols)
{
// Handle error
}
// Check that numRows and numCols are acceptable (positive)
// [not shown]
CMatrix A(numRows, numCols);
if (inputFile)
{
int elementsRead = 0;
for (int i = 0; i < numRows; i++)
{
for (int j = 0; j < numCols; j++)
{
double x;
if (inputFile >> x)
{
A.Value(i,j) = x;
++elementsRead;
} else {
// probably an error from too-short file,
// token could not be converted to double, etc.
// handle appropriately
break;
}
}
}
}
if (elementsRead != numRows * numCols)
{
// handle error
}
// Use matrix A