Reputation: 1
I need to simple program on C++ which can take two matrices from text file and also it take the number of row and column of each one like this:
this is ex for which is text file contain
3 5
1 -2 3 4 5
1 2 -3 4 5
-1 2 3 4 5
5 4
-1 2 3 4
1 -2 3 4
1 2 -3 4
1 2 3 -4
-1 -2 -3 -4
the first line of each matrix contain it`s number of row and column
and this is the prog which i tried to do it
#include <cstdio>
#include <cstring>
#include <fstream>
#define Height 3
#define Width 5
// I assume that each input line in the file can contain at most width * 3 characters.
// Three extra characters for NL, CR, 0.
// Change this if you expect the file to contain longer lines.
#define BUFFER_WIDTH (Width * 3 + 3)
unsigned char Map[Height][Width];
char line[BUFFER_WIDTH];
// Remove CR, NL at the end of the line.
void clean_line(char *line)
{
int len = strlen(line);
while (len > 0 && (line[len - 1] == '\n' || line[len - 1] == '\r'))
{
line[len - 1] = '\0';
len--;
}
}
int main ()
{
FILE *fp = fopen("input1.txt","r");
int row = 0;
while (!feof(fp) && row < Height)
{
fgets(line, BUFFER_WIDTH, fp);
clean_line(line);
int len = strlen(line);
int rowLen = len > Width ? Width : len;
for (int col = 0; col < rowLen; col++)
{
Map[row][col] = line[col];
printf("%d ",Map[row][col]);
}
printf("\n");
row++;
}
fclose(fp);
return 0;
}
Upvotes: 0
Views: 2559
Reputation: 68598
#include <iostream>
#include <vector>
using namespace std;
vector<vector<int>> read_matrix(istream& in)
{
int rows, cols;
in >> rows >> cols;
vector<vector<int>> matrix(rows, vector<int>(cols));
for (auto& row : matrix)
for (auto& cell : row)
in >> cell;
return matrix;
}
int main()
{
fstream in("input.txt");
vector<vector<int>> mat1 = read_matrix(in);
vector<vector<int>> mat2 = read_matrix(in);
}
Upvotes: 0
Reputation: 60924
I recently wrote a rather simple CSV reader class, this does a lot of the things you are looking for. I also posted this code on the stack exchange Code Review. This also includes some comments on the code. I use boost::MultiArray
to store the results in a 2d array, and I use boost::split
to split the text in the file into numbers.
Here is the code:
A header file:
#include <iostream>
#include <sstream>
#include <string>
#include <stdexcept>
class BadConversion : public std::runtime_error {
public:
BadConversion(std::string const& s)
: std::runtime_error(s)
{ }
};
class BadIndex : public std::runtime_error {
public:
BadIndex(std::string const& s)
: std::runtime_error(s)
{ }
};
inline double convertToDouble(std::string const& s)
{
std::istringstream i(s);
double x;
if (!(i >> x))
throw BadConversion("convertToDouble(\"" + s + "\")");
return x;
}
and the c++ code, which include some example uses:
#include <iostream>
#include <sstream>
#include <fstream>
#include <string>
#include <vector>
#include <boost/algorithm/string.hpp>
#include <boost/multi_array.hpp>
#include "csv-test.h"
#include <cassert>
template <class T> class csv_reader {
boost::multi_array<T, 2> content2d ;
std::vector<std::string> split_line ;
std::string line;
std::string sep ;
int ncol ;
int nrow ;
public :
csv_reader(std::string, std::string) ; // constructor
~csv_reader(); // desctructor
void cout_content() ; // print the contents
T operator() (unsigned row, unsigned column) ;
} ;
// Constructor
template <class T> csv_reader<T>::csv_reader(std::string path, std::string sep = ",")
{
// Initializing variables
ncol = 0 ; // Initialize the number of colums to 0
nrow = 1 ; // Initialize the number of rows to 1
content2d = boost::multi_array<T, 2> (boost::extents[0][0]) ;
std::ifstream data(path.c_str()) ;
// read the csv data
while(getline(data, line))
{
boost::split(split_line, line, boost::is_any_of(sep) ) ;
if(ncol == 0)
{
ncol = split_line.size() ;
}
else assert(ncol == split_line.size()) ;
content2d.resize(boost::extents[nrow][ncol]) ;
for(int i = 0; i < split_line.size(); i++)
{
content2d[nrow - 1][i] = convertToDouble(split_line[i]) ;
}
nrow++ ;
}
}
// Destructor
template <class T> csv_reader<T>::~csv_reader() { }
template <class T> void csv_reader<T>::cout_content()
{
for(int row = 0; row < (nrow - 1); row++)
{
for(int col = 0; col < ncol ; col++)
{
std::cout << content2d[row][col] << " ";
}
std::cout << "\n" ;
}
}
// Allow access to the contents
template <class T> T csv_reader<T>::operator() (unsigned row, unsigned column)
{
if (row >= nrow || column >= ncol)
throw BadIndex("boost::MultiArray subscript out of bounds");
return(content2d[row][column]) ;
}
int main()
{
// An integer csv reader
csv_reader<int> csv_obj_int("test.csv") ;
csv_obj_int.cout_content() ;
// A double csv reader
csv_reader<double> csv_obj_double("test.csv") ;
csv_obj_double.cout_content() ;
// It also supports direct access to the content using operator()
std::cout << csv_obj_double(1,1) << "\n" ;
std::cout << csv_obj_double(1,1) * 5 << "\n" ;
// This statement fails with a subscript out of bounds error
// std::cout << csv_obj_double(10,10) * 5 << "\n" ;
// Testing a different seperator
csv_reader<double> csv_obj_double_sep2("test_semicol.csv", ";") ;
csv_obj_double_sep2.cout_content() ;
}
Upvotes: 0
Reputation: 10153
#include <iostream>
void matUpdate(int***mat,int& row,int& col,int**matData,int& rowData,int& colData) {
*mat = matData;
row = rowData;
col = colData;
}
int read(int***mat1,int***mat2,int& row1,int& col1,int& row2,int& col2)
{
FILE* fp = fopen("mat.txt","r");
if (fp == NULL) {
return -1;
}
int row,col,matNum = 0;
while(matNum < 2) {
if (fscanf(fp,"%d %d",&row,&col) != 2 || row < 0 || col < 0) {
return -1;
}
int i,j;
int** mat = new int*[row];
for (i = 0; i < row;++i) {
mat[i] = new int[col];
}
for (i = 0;i < row;++i) {
for (j = 0;j < col;++j) {
fscanf(fp,"%d",&mat[i][j]);
}
}
if (matNum) {
matUpdate(mat2,row2,col2,mat,row,col);
}
else {
matUpdate(mat1,row1,col1,mat,row,col);
}
matNum++;
}
return fp;
}
int main()
{
int **mat1 = NULL,**mat2 = NULL;
int row1,col1,row2,col2;
FILE* fp = read(&mat1,&mat2,row1,col1,row2,col2);
if (fp != - 1) {
//work with matrics
//delete memory allocated for matrics
fclose(fp);
}
else {
//error
}
}
Upvotes: 1
Reputation: 11482
You need to parse the file at whole and then to split it by some delimeter(in this case newlines and blanks). This process is called tokenization. Many libraries like boost or poco support such operations.
Upvotes: 1