I currently have a C++ program to read in a matrix of values (type double) and print out the transpose, how can I alter my code so that it can read in csv files rather than spaced matrix text?
I also need to write out the transposed matrix to another file after calculating it, what would be the simplest way of doing this?
int readMatrix(const string & s, vector<double> & v);
void import_csv_matrix(const char* filename_matrix, vector <double> & v, int& rows, int& columns);
int main() {
vector<double> v;
int rows = 0;
int columns = 0;
import_csv_matrix("filename.csv", v, rows, columns);
return 0;
}
int readMatrix (const string & s, vector<double> & v) {
istringstream is(s);
double n;
while (is >> n) {
v.push_back(n);
}
return v.size();
}
void import_csv_matrix(const char* filename_matrix, vector<double>& v, int& rows, int& columns) {
ifstream data_File;
string line;
data_File.open(filename_matrix);
if (data_File.is_open()) {
int i = 0;
getline(data_File, line);
columns = readMatrix(line, v);
for (i = 1; i < 100000; i++) {
if ( !getline(data_File, line) > 0) break;
readMatrix(line, v);
}
rows = i;
data_File.close();
}
cout << "Transpose:" << endl;
for (int i = 0; i < columns; i++) {
for (int j = 0; j < rows; j++) {
cout << v[i + j*columns] << "\t";
}
cout << endl;
}
}
I assume you mean that the rows are still line separated but the elements within rows are comma separated. Then all you need to do is modify the readMatrix function to handle those commas. The following code should work.
int readMatrix(const string& s, vector<double>& v) {
char comma = ',';
istringstream is{s};
for (double temp = 0.0; is >> temp; v.push_back(temp)) {
is >> comma;
if (comma != ',') break; \\ a formatting error has occurred
}
return v.size();
}
Related
I'm trying to read input from a file, and store this input in a dynamically allocated array in my matrix class.
Every time I run this code, the input and output are both correct, but it always exits with return value 3221226356. Can anyone tell me what the problem is?
The input file is a .txt file, and it contains the number of rows, number of elements, and it looks something like this:
10 15
000000000000000
000999000009900
000999000009900
000000900009900
000090000099900
000099900000000
090000900000000
099999999900000
000090090000000
000000000000000
10 is the number of rows, and 15 is the number of elements per row.
I have to read this matrix and put this into my matArray. Every character is one Element node.
#include <bits/stdc++.h>
#include<iostream>
#include<fstream>
#include<string>
#include<cstring>
using namespace std;
class Element{
private:
char value;
int processed;
public:
Element(){
value = 0;
processed = 0;
}
void setContent(char cellValue){ value = cellValue; }
void setProcessed(int num1){ processed = num1; }
char getContent(){ return value; }
int getProcessed(){ return processed; }
};
class Matrix{
private:
Element* matArray;
int rows;
int cols;
public:
Matrix(int nRows, int nCols){
matArray = new Element[nRows * nCols];
rows = nRows;
cols = nCols;
}
void setInput(int r, int c, Element input){
matArray[r * rows + c] = input;
}
Element getInput(int r, int c){
return matArray[r * rows + c];
}
};
int main(){
int numRow = 0;
int numCol = 0;
string filename = "";
string whiteSpace;
string string1;
cin >> filename;
ifstream inFS;
filename = filename + ".txt";
inFS.open(filename.c_str());
if(inFS.fail()){
cout << "fail";
}
if(inFS.good()){
cout << "good" << endl;
}
inFS >> numRow;
inFS >> numCol;
Matrix mat1(numRow, numCol);
Element temp;
char display;
getline(inFS, whiteSpace);
//Reading the matrix from the file and inserting this information to mat1
for(int i = 0; i < numRow; i++){
getline(inFS, string1);
cout << endl;
for(int j = 0; j < numCol; j++){
temp = mat1.getInput(i, j);
temp.setContent(string1[j]);
mat1.setInput(i, j, temp);
cout << mat1.getInput(i, j).getContent() << " ";
}
}
cout << endl;
return 0;
}
Your index calculations in setInput() and getInput() are wrong, causing you to access matArray's elements out of bounds, which is undefined behavior. You need to multiply the r parameter by cols (the number of elements per row) instead of by rows (the number of rows), eg:
void setInput(int r, int c, Element input){
matArray[(r * cols) + c] = input;
}
Element getInput(int r, int c){
return matArray[(r * cols) + c];
}
int main(){
int row1, column1;
cout << "How many rows for first matrix?";
cin >> row1;
cout << "How many columns first matrix?";
cin >> column1;
int org[row1][column1];
cout << "Enter the elements of first matrix: ";
for(int i=0;i<row1;i++){
for(int j=0;j<column1;j++){
cin>>org[i][j];
}
}
for(int i=0;i<row1;i++){
for(int j=0;j<column1;j++){
cout<<org[i][j];
}
cout<<endl;
}
matrixreshape sol;
I have problems passing column1, row1, and matrix org into the matrixReshape function.
cout<<sol.matrixReshape(vector<vector<int> org[row1][column1],row1, column1);
matrixReshape function as follows:
class matrixreshape {
public:
vector<vector<int>> matrixReshape(vector<vector<int>>& nums, int r, int c) {
vector<vector<int>> newMatrix(r, vector<int>(c, 0));
The method matrixReshape needs a vector<vector<int>> as an actual argument. You are trying to pass it a 2D VLA which is not directly convertible.
You need to use vector<vector<int>> for input and pass that to the matrixReshape.
Here's an example:
vector<vector<int>> org( row1 );
for ( int i = 0; i < org.size(); i++ )
{
org[i].resize( column1 );
for ( int j = 0; j < org[i].size(); j++ )
{
cin >> org[i][j];
}
}
// and then pass it
matrixreshape sol;
cout << sol.matrixReshape( org, row1, col1 );
Or, with C++11's range-for loop, it would be like this:
std::size_t rows {0};
std::size_t cols {0};
std::cin >> rows >> cols;
std::vector<std::vector<int>> matrix( rows );
for ( auto& r : matrix )
{
r.resize( cols );
for ( auto& c : r )
{
std::cin >> c;
}
}
matrixreshape sol;
std::cout << sol.matrixReshape( matrix, rows, cols );
Here's a complete working example: https://godbolt.org/z/XPwRMq
In addition, you don't need rows and columns information to pass to matrixReshape() method as the std::vector has size() method. You can use that if you need that.
Another thing is that you have to overload stream insertion operator << for this type to print it with std::cout.
Here's an example (live):
#include <iostream>
#include <vector>
using Matrix = std::vector<std::vector<int>>;
std::ostream& operator<<( std::ostream& os, const Matrix& m )
{
for ( const auto& r : m )
{
for ( const auto& c : r )
{
os << c << ' ';
}
os << '\n';
}
return os;
}
int main()
{
const Matrix m
{
{ 1, 2 },
{ 3, 4 }
};
std::cout << m;
return 0;
}
Output:
1 2
3 4
I'm trying to figure out why my program fails when I run. So far when I run my program it fails on me. I debugged the error and it brings me to dbgdel.cpp. Line 32 " _ASSERTE(_BLOCK_TYPE_IS_VALID(pHead->nBlockUse));". I've searched for the answer to no avail, but it has something to do with my memory leak?
Here is my header:
#include <iostream>
using namespace std;
namespace project
{
#ifndef MATRIX_H
#define MATRIX_H
typedef int* IntArrayPtr;
class Matrix
{
public:
friend ostream& operator<<(ostream& out, Matrix& object);
//friend istream& operator>>(istream& in, Matrix& theArray);
//Default Constructor
Matrix();
Matrix(int max_number_rows, int max_number_cols, int intial_value);
//Destructor
~Matrix();
//Copy Constructor
Matrix(const Matrix& right_side);
//Assignment Operator
Matrix& operator=(const Matrix& right_side);
void Clear();
int Rows();
int Columns();
bool GetCell(int x,int y, int& val);
bool SetCell(int x,int y, int val);
int getNumber(int r, int c);
//void Debug(ostream& out);
private:
int initialVal;
int rows;
int cols;
IntArrayPtr *m;
};
#endif
}
My implementation file:
#include <iostream>
#include "Matrix.h"
using namespace project;
using namespace std;
namespace project
{
Matrix::Matrix()
{
typedef int* IntArrayPtr;
IntArrayPtr *m = new IntArrayPtr[1];
for(int i = 0; i < 1; i++)
m[i] = new int[1];
for(int r = 0; r < 1; r++)
for(int c = 0; c < 1;c++)
m[r][c] = 0;
}
Matrix::Matrix(int max_number_rows, int max_number_cols, int initial_value)
{
initialVal = initial_value;
rows = max_number_rows;
cols = max_number_cols;
IntArrayPtr *m = new IntArrayPtr[rows];
for(int i = 0; i < rows; i++)
m[i] = new int[cols];
for(int r = 0; r < max_number_rows; r++)
for(int c = 0; c < max_number_cols;c++)
m[r][c] = initial_value;
}
Matrix::~Matrix()
{
for(int i = 0; i <= rows; i++)
delete [] m[i];
delete [] m;
}
void Matrix::Clear()
{
for(int r = 0; r < rows; r++)
for(int c = 0; c < cols;c++)
m[r][c] = initialVal;
}
int Matrix::Rows()
{
return rows;
}
int Matrix::Columns()
{
return cols;
}
bool Matrix::GetCell(int x,int y, int& val)
{
if(x < rows || y < cols)
return false;
else
{
val = m[x - 1][y - 1];
return true;
}
}
bool Matrix::SetCell(int x, int y, int val)
{
if(x < rows || y < cols)
return false;
else
{
m[x - 1][y - 1] = val;
return true;
}
}
int Matrix::getNumber(int r, int c)
{
return m[r][c];
}
ostream& operator<<(ostream& out, Matrix& object)
{
for(int r = 0; r < object.rows; r++)
{
for(int c = 0; c < object.cols; c++)
{
out << " " << object.m[r][c];
}
out << endl;
}
return out;
}
Matrix& Matrix::operator=(const Matrix& right_side)
{
if (this != &right_side)
{
rows = right_side.rows;
cols = right_side.cols;
delete[] m;
IntArrayPtr *m = new IntArrayPtr[rows];
for(int i = 0; i < rows; i++)
m[i] = new int[cols];
for(int r = 0; r < rows; r++)
for(int c = 0; c < cols;c++)
m[r][c] = right_side.initialVal;
}
return *this;
}
/*
void Matrix::Debug(ostream& out)
{
out << "Number of rows = " << rows << endl;
out << "Number of columns = " << cols << endl;
out << "Initializer = " << initialVal << endl;
out << "Current contents of the matrix: " << endl;
out << m << endl;
}
*/
/*
istream& operator >>(istream& in, Matrix& theArray)
{
in >>
}
void interfaceMatrix()
{
int userChoice, rows, columns, value;
cout << "Default matrix or custom(1 for default, 0 for custom): ";
cin >> userChoice;
if (userChoice == 1)
{
Matrix object;
return object;
}
else if(userChoice == 0)
{
cout << "Enter number of rows: ";
cin >> rows;
cout << "Enter number of columns: ";
cin >> columns;
cout << "Enter initial value of each element: ";
cin >> value;
if(rows <= 0 || columns <= 0)
{
cout << "Invalid input." << endl;
exit(1);
}
else
{
Matrix object(rows, columns, value);
return object;
}
}
else
{
cout << "Invalid choice." << endl;
exit(1);
}
}
*/
}
In my driver I just put Matrix test(2,2,2), so I can create a 2 x 2 array with initial value of 2 for each element. I get the above error.
You are allocating rows number of rows, but deallocating rows+1 number of rows.
Check the destructor. <= must be <.
Besides this there are a lot of other [potential] errors in your code:
you are setting the local m variable instead of setting the m data member of your class (that's why I have the convention to always precede data members by m_ to prevent this kind of confusion). This error appears both in the constructor and the assignment operator.
you use rows to allocate the matrix, but max_number_rows to initialize the matrix. Although it works correctly now, it may lead to errors if row is initialized differently later (e.g. if row is initialized with std::max(max_number_rows,1000). Your code in the assignment operator is better.
your if-test in GetCell and SetCell is incorrect. It should probably be >= instead of <
the assignment operator copies the size of the matrix, but assigns all cells an initialValue. This is not an assignment. This implementation might/will confuse the rest of the code.
the typedef of IntArrayPtr is unnecessary
two issues:
You are not allocating any value into the "m" member of your object, you are allocating into local variables named "m"
you are over deallocating by looping from i=0 to i <= rows, you want i=0 to i < rows
This question already has answers here:
String not outputting the characters i type in
(3 answers)
Closed 9 years ago.
this program is supposed to output to the console a string of letters i type in, for example if i type in "im hungry" then its supposed to output im hungry to the console in a matrix for, if something i type in is too long then it carries over to the next line of the matrix
heres the code i have so far:
#include <iostream>
#include <string>
using namespace std;
#define N 6
//
// fill:
//
void fill(string s, int M[][N], int ROWS, int COLS)
{
int i, r, c;
s= "x";
for (i=0, r=0; r < ROWS; r++)
{
for (c=0; c < COLS; c++)
{
M[r][c] = s[i]; // store ith character into matrix:
i++; // next character:
if (i == s.length()) // start-over if that was last char:
i = 0;
}
}
}
void print(int M[][N], int ROWS, int COLS)
{
string s;
s= "x";
int r, c;
for(r=0; r< ROWS; r++)
{
for(c=0; c < COLS; c++)
{
cout<<(char)M[r][c];
}
cout <<endl;
}
}
//
// main:
//
int main()
{
string s;
getline(cin,s);
int M[N][N];
int M2[N][N];
int row, col, ROWS, COLS;
fill(s, M, 1, 1);
print(M, ROWS, COLS);
return 0;
}
instead of outputting what I type in, it keeps outputting a matrix of random characters (same no matter what I type in) any suggestions on how I can fix this?
If you don't really need of the matrix you can simply:
void print(string s, int limit, char endl = '\n') {
if (limit == 0) return;
if (s.length > limit) {
for (int i = 0; i < s.length; i++) {
std::cout << s[i];
if (i % limit == 0)
std::cout << endl;
} else {
std::cout << s;
}
}
which will take the string and print it, in case it below the limit, or split it into different lines with the endl char.
I am trying to take in an input for the dimensions of a 2D matrix. And then use user input to fill in this matrix. The way I tried doing this is via vectors (vectors of vectors). But I have encountered some errors whenever I try to read in data and append it to the matrix.
//cin>>CC; cin>>RR; already done
vector<vector<int> > matrix;
for(int i = 0; i<RR; i++)
{
for(int j = 0; j<CC; j++)
{
cout<<"Enter the number for Matrix 1";
cin>>matrix[i][j];
}
}
Whenever I try to do this, it gives me a subscript out of range error. Any advice?
You have to initialize the vector of vectors to the appropriate size before accessing any elements. You can do it like this:
// assumes using std::vector for brevity
vector<vector<int>> matrix(RR, vector<int>(CC));
This creates a vector of RR size CC vectors, filled with 0.
As it is, both dimensions of your vector are 0.
Instead, initialize the vector as this:
vector<vector<int> > matrix(RR);
for ( int i = 0 ; i < RR ; i++ )
matrix[i].resize(CC);
This will give you a matrix of dimensions RR * CC with all elements set to 0.
I'm not familiar with c++, but a quick look at the documentation suggests that this should work:
//cin>>CC; cin>>RR; already done
vector<vector<int> > matrix;
for(int i = 0; i<RR; i++)
{
vector<int> myvector;
for(int j = 0; j<CC; j++)
{
int tempVal = 0;
cout<<"Enter the number for Matrix 1";
cin>>tempVal;
myvector.push_back(tempVal);
}
matrix.push_back(myvector);
}
Assume we have the following class:
#include <vector>
class Matrix {
private:
std::vector<std::vector<int>> data;
};
First of all I would like suggest you to implement a default constructor:
#include <vector>
class Matrix {
public:
Matrix(): data({}) {}
private:
std::vector<std::vector<int>> data;
};
At this time we can create Matrix instance as follows:
Matrix one;
The next strategic step is to implement a Reset method, which takes two integer parameters that specify the new number of rows and columns of the matrix, respectively:
#include <vector>
class Matrix {
public:
Matrix(): data({}) {}
Matrix(const int &rows, const int &cols) {
Reset(rows, cols);
}
void Reset(const int &rows, const int &cols) {
if (rows == 0 || cols == 0) {
data.assign(0, std::vector<int>(0));
} else {
data.assign(rows, std::vector<int>(cols));
}
}
private:
std::vector<std::vector<int>> data;
};
At this time the Reset method changes the dimensions of the 2D-matrix to the given ones and resets all its elements. Let me show you a bit later why we may need this.
Well, we can create and initialize our matrix:
Matrix two(3, 5);
Lets add info methods for our matrix:
#include <vector>
class Matrix {
public:
Matrix(): data({}) {}
Matrix(const int &rows, const int &cols) {
Reset(rows, cols);
}
void Reset(const int &rows, const int &cols) {
data.resize(rows);
for (int i = 0; i < rows; ++i) {
data.at(i).resize(cols);
}
}
int GetNumRows() const {
return data.size();
}
int GetNumColumns() const {
if (GetNumRows() > 0) {
return data[0].size();
}
return 0;
}
private:
std::vector<std::vector<int>> data;
};
At this time we can get some trivial matrix debug info:
#include <iostream>
void MatrixInfo(const Matrix& m) {
std::cout << "{ \"rows\": " << m.GetNumRows()
<< ", \"cols\": " << m.GetNumColumns() << " }" << std::endl;
}
int main() {
Matrix three(3, 4);
MatrixInfo(three);
}
The second class method we need at this time is At. A sort of getter for our private data:
#include <vector>
class Matrix {
public:
Matrix(): data({}) {}
Matrix(const int &rows, const int &cols) {
Reset(rows, cols);
}
void Reset(const int &rows, const int &cols) {
data.resize(rows);
for (int i = 0; i < rows; ++i) {
data.at(i).resize(cols);
}
}
int At(const int &row, const int &col) const {
return data.at(row).at(col);
}
int& At(const int &row, const int &col) {
return data.at(row).at(col);
}
int GetNumRows() const {
return data.size();
}
int GetNumColumns() const {
if (GetNumRows() > 0) {
return data[0].size();
}
return 0;
}
private:
std::vector<std::vector<int>> data;
};
The constant At method takes the row number and column number and returns the value in the corresponding matrix cell:
#include <iostream>
int main() {
Matrix three(3, 4);
std::cout << three.At(1, 2); // 0 at this time
}
The second, non-constant At method with the same parameters returns a reference to the value in the corresponding matrix cell:
#include <iostream>
int main() {
Matrix three(3, 4);
three.At(1, 2) = 8;
std::cout << three.At(1, 2); // 8
}
Finally lets implement >> operator:
#include <iostream>
std::istream& operator>>(std::istream& stream, Matrix &matrix) {
int row = 0, col = 0;
stream >> row >> col;
matrix.Reset(row, col);
for (int r = 0; r < row; ++r) {
for (int c = 0; c < col; ++c) {
stream >> matrix.At(r, c);
}
}
return stream;
}
And test it:
#include <iostream>
int main() {
Matrix four; // An empty matrix
MatrixInfo(four);
// Example output:
//
// { "rows": 0, "cols": 0 }
std::cin >> four;
// Example input
//
// 2 3
// 4 -1 10
// 8 7 13
MatrixInfo(four);
// Example output:
//
// { "rows": 2, "cols": 3 }
}
Feel free to add out of range check. I hope this example helps you :)
try this. m = row, n = col
vector<vector<int>> matrix(m, vector<int>(n));
for(i = 0;i < m; i++)
{
for(j = 0; j < n; j++)
{
cin >> matrix[i][j];
}
cout << endl;
}
cout << "::matrix::" << endl;
for(i = 0; i < m; i++)
{
for(j = 0; j < n; j++)
{
cout << matrix[i][j] << " ";
}
cout << endl;
}
Vector needs to be initialized before using it as cin>>v[i][j]. Even if it was 1D vector, it still needs an initialization, see this link
After initialization there will be no errors, see this link
What you have initialized is a vector of vectors, so you definitely have to include a vector to be inserted("Pushed" in the terminology of vectors) in the original vector you have named matrix in your example.
One more thing, you cannot directly insert values in the vector using the operator "cin". Use a variable which takes input and then insert the same in the vector.
Please try this out :
int num;
for(int i=0; i<RR; i++){
vector<int>inter_mat; //Intermediate matrix to help insert(push) contents of whole row at a time
for(int j=0; j<CC; j++){
cin>>num; //Extra variable in helping push our number to vector
vin.push_back(num); //Inserting numbers in a row, one by one
}
v.push_back(vin); //Inserting the whole row at once to original 2D matrix
}
I did this class for that purpose. it produces a variable size matrix ( expandable) when more items are added
'''
#pragma once
#include<vector>
#include<iostream>
#include<iomanip>
using namespace std;
template <class T>class Matrix
{
public:
Matrix() = default;
bool AddItem(unsigned r, unsigned c, T value)
{
if (r >= Rows_count)
{
Rows.resize(r + 1);
Rows_count = r + 1;
}
else
{
Rows.resize(Rows_count);
}
if (c >= Columns_Count )
{
for (std::vector<T>& row : Rows)
{
row.resize(c + 1);
}
Columns_Count = c + 1;
}
else
{
for (std::vector<T>& row : Rows)
{
row.resize(Columns_Count);
}
}
if (r < Rows.size())
if (c < static_cast<std::vector<T>>(Rows.at(r)).size())
{
(Rows.at(r)).at(c) = value;
}
else
{
cout << Rows.at(r).size() << " greater than " << c << endl;
}
else
cout << "ERROR" << endl;
return true;
}
void Show()
{
std::cout << "*****************"<<std::endl;
for (std::vector<T> r : Rows)
{
for (auto& c : r)
std::cout << " " <<setw(5)<< c;
std::cout << std::endl;
}
std::cout << "*****************" << std::endl;
}
void Show(size_t n)
{
std::cout << "*****************" << std::endl;
for (std::vector<T> r : Rows)
{
for (auto& c : r)
std::cout << " " << setw(n) << c;
std::cout << std::endl;
}
std::cout << "*****************" << std::endl;
}
// ~Matrix();
public:
std::vector<std::vector<T>> Rows;
unsigned Rows_count;
unsigned Columns_Count;
};
'''