读取文本文件包含矩阵C ++

时间:2012-04-09 10:35:30

标签: c++ matrix text-files

我需要在C ++上使用简单的程序,它可以从文本文件中获取两个矩阵,并且每个矩阵的行数和列数都是这样的:

这是ex的文本文件包含

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

每个矩阵的第一行包含行数和列数

这是我试图做的编程

#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;
}

4 个答案:

答案 0 :(得分:1)

您需要整体解析文件,然后通过某些分隔符(在这种情况下为换行符和空格)对其进行拆分。此过程称为标记化。许多库如boost或poco都支持这样的操作。

class StringTokenizer

boost::split

答案 1 :(得分:1)

#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
    }

}

答案 2 :(得分:0)

#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);
}

答案 3 :(得分:0)

我最近编写了一个相当简单的CSV阅读器类,这可以帮助你做很多事情。我还在堆栈交换代码审查posted this code。这还包括对代码的一些评论。我使用boost::MultiArray将结果存储在2d数组中,并使用boost::split将文件中的文本拆分为数字。

以下是代码:

头文件:

 #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;
 }

和c ++代码,包括一些示例使用:

#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() ;
}