c++ - 从文件加载矩阵

标签 c++ file file-io matrix

我需要读取包含矩阵数据的文件并在我的程序中创建矩阵。 Matrix 文件格式类似于:

#  Matrix made by matblas from blosum62.iij
#  * column uses minimum score
#  BLOSUM Clustered Scoring Matrix in 1/2 Bit Units
#  Blocks Database = /data/blocks_5.0/blocks.dat
#  Cluster Percentage: >= 62
#  Entropy =   0.6979, Expected =  -0.5209
   A  R  N  D  C  Q  E  G  H  I  L  K  M  F  P  S  T  W  Y  V  B  Z  X  *
A  4 -1 -2 -2  0 -1 -1  0 -2 -1 -1 -1 -1 -2 -1  1  0 -3 -2  0 -2 -1  0 -4 
R -1  5  0 -2 -3  1  0 -2  0 -3 -2  2 -1 -3 -2 -1 -1 -3 -2 -3 -1  0 -1 -4 
N -2  0  6  1 -3  0  0  0  1 -3 -3  0 -2 -3 -2  1  0 -4 -2 -3  3  0 -1 -4 
D -2 -2  1  6 -3  0  2 -1 -1 -3 -4 -1 -3 -3 -1  0 -1 -4 -3 -3  4  1 -1 -4 
C  0 -3 -3 -3  9 -3 -4 -3 -3 -1 -1 -3 -1 -2 -3 -1 -1 -2 -2 -1 -3 -3 -2 -4 
Q -1  1  0  0 -3  5  2 -2  0 -3 -2  1  0 -3 -1  0 -1 -2 -1 -2  0  3 -1 -4 
E -1  0  0  2 -4  2  5 -2  0 -3 -3  1 -2 -3 -1  0 -1 -3 -2 -2  1  4 -1 -4 
G  0 -2  0 -1 -3 -2 -2  6 -2 -4 -4 -2 -3 -3 -2  0 -2 -2 -3 -3 -1 -2 -1 -4 
H -2  0  1 -1 -3  0  0 -2  8 -3 -3 -1 -2 -1 -2 -1 -2 -2  2 -3  0  0 -1 -4 
I -1 -3 -3 -3 -1 -3 -3 -4 -3  4  2 -3  1  0 -3 -2 -1 -3 -1  3 -3 -3 -1 -4 
L -1 -2 -3 -4 -1 -2 -3 -4 -3  2  4 -2  2  0 -3 -2 -1 -2 -1  1 -4 -3 -1 -4 
K -1  2  0 -1 -3  1  1 -2 -1 -3 -2  5 -1 -3 -1  0 -1 -3 -2 -2  0  1 -1 -4 
M -1 -1 -2 -3 -1  0 -2 -3 -2  1  2 -1  5  0 -2 -1 -1 -1 -1  1 -3 -1 -1 -4 
F -2 -3 -3 -3 -2 -3 -3 -3 -1  0  0 -3  0  6 -4 -2 -2  1  3 -1 -3 -3 -1 -4 
P -1 -2 -2 -1 -3 -1 -1 -2 -2 -3 -3 -1 -2 -4  7 -1 -1 -4 -3 -2 -2 -1 -2 -4 
S  1 -1  1  0 -1  0  0  0 -1 -2 -2  0 -1 -2 -1  4  1 -3 -2 -2  0  0  0 -4 
T  0 -1  0 -1 -1 -1 -1 -2 -2 -1 -1 -1 -1 -2 -1  1  5 -2 -2  0 -1 -1  0 -4 
W -3 -3 -4 -4 -2 -2 -3 -2 -2 -3 -2 -3 -1  1 -4 -3 -2 11  2 -3 -4 -3 -2 -4 
Y -2 -2 -2 -3 -2 -1 -2 -3  2 -1 -1 -2 -1  3 -3 -2 -2  2  7 -1 -3 -2 -1 -4 
V  0 -3 -3 -3 -1 -2 -2 -3 -3  3  1 -2  1 -1 -2 -2  0 -3 -1  4 -3 -2 -1 -4 
B -2 -1  3  4 -3  0  1 -1  0 -3 -4  0 -3 -3 -2  0 -1 -4 -3 -3  4  1 -1 -4 
Z -1  0  0  1 -3  3  4 -2  0 -3 -3  1 -1 -3 -1  0 -1 -3 -2 -2  1  4 -1 -4 
X  0 -1 -1 -1 -2 -1 -1 -1 -1 -1 -1 -1 -1 -1 -2  0  0 -2 -1 -1 -1 -1 -1 -4 
* -4 -4 -4 -4 -4 -4 -4 -4 -4 -4 -4 -4 -4 -4 -4 -4 -4 -4 -4 -4 -4 -4 -4  1 

字母具有恒定的位置,因此由于我只对其中四个感兴趣,所以我可以在程序中分配xy。我需要的只是一个包含值的矩阵,我可以通过给出函数“GetValue”“x”和“y”来搜索值。

这是我的代码。它只是头文件中定义的类的一部分,其中包含并通过矩阵搜索值。也许这不是优雅的方式,但我没有那么多时间,所以现在我想快速完成。稍后我会有更多时间,所以我会做得更好。

/*
 * algorytm.cpp
 * implementacja algorytmu
 *
 * Autor: Mateusz
 *
 */

#include <cstdlib>
#include <iostream>
#include <string>
#include <stdio.h>
#include <fstream>
#include <vector>
#include "matryca_sub.h"
#include <sstream>
#include <istream>
#include <sstream>

using namespace std;

int ScoreMatrix::MainMatrix(char *mat_file, int x, int y)
{
    cout << "Main matrix function start" << endl;
    CreateMatrix(30);
    ReadMatrix(mat_file);
    int val;
    val=GetValue(x, y);
    return val;
    cout << "Main matrix function end" << endl;
}

void ScoreMatrix::CreateMatrix(int edge)
{
    cout << "Creating sub matrix start" << endl;
   //int** scores = new int* [*edge-1];
   //for (int i=0; i<=23; i++) scores[i] = new int[*edge-1];
   if( scores != 0 ) delete [] scores;
   scores =  new int [edge*edge];
   cols = edge;
   cout << "Sub matrix created" << endl;
}

void ScoreMatrix::SetValue(int x, int y, int val)
{
    cout << "write to sub matrix start" << endl;
    //scores[x][y] = val;
    scores[(cols* y) + x] = val;
    cout << "write to sub matrix end" << endl;
}

int ScoreMatrix::GetValue(int x, int y)
{
    //cout << "GetValue start" << endl;
    //return scores[x][y];
    return scores[(cols * x) + y];
    cout << "GetValue end" << endl;
}

void ScoreMatrix::ReadMatrix(char *mat_file)
{
    cout << "start reading matrix from file" << endl;
    int row=0;
    ifstream mfile;
    mfile.open(mat_file);
    mfile.precision(2);
    mfile.setf(ios::fixed, ios::showpoint);
    while(!mfile.eof())
    {
        for (row=0; row<=23; row++)
        {
        string line;
        getline( mfile, line);
        istringstream iss(line);

        if (line[0] !='#' && line[0] != ' ')
        {
            int s;
            iss >> s;
            for (int i=1; !iss.eof(); i++)
            {
                iss >> s;
                SetValue(i, row, s);
            }

        }
        }
    }
    cout << "end reading matrix from file" << endl;
}

包含头文件:

/*
 * File:   mat_sub.h
 * Author: mateusz
 *
 * Created on 6 luty 2011, 14:44
 */

#ifndef MAT_SUB_H
#define MAT_SUB_H
#include <cstdlib>
#include <iostream>
#include <string>
#include <stdio.h>
#include <stdlib.h>
#include <fstream>
#include <vector>
#include <algorithm>
#include <string.h>

using namespace std;

class ScoreMatrix
{
public:
    ScoreMatrix():
    cols (0)
    ,scores (0)
    {}

    char mat_file;
    int MainMatrix(char *mat_file, int x, int y);
    int GetValue(int x, int y);

private:
    int cols, rows;
    int* scores;

    void CreateMatrix(int edge);
    void SetValue(int x, int y, int val);
    void ReadMatrix(char *mat_file);
};



#endif  /* MAT_SUB_H */

在seagfoult函数打印许多开始从文件读取矩阵之一之前。

最佳答案

天哪。如果我听起来很刺耳,希望您能原谅我,但是这段代码有很多问题,从基本设计一直到细节,例如您使用的循环从文件中读取数据。

首先,在我看来,您的“矩阵”类需要应用适量的“单一责任”。我会将其简化为二维矩阵,仅此而已。

其次,我将摆脱您自己处理内存管理的麻烦。您真正需要的只是一个 std::vector,以及足够的前端来提供 2D 寻址。

第三,我会摆脱“getValue”/“setValue”,并像自 20 世纪 50 年代科学程序员从汇编语言转换为 Fortran 以来的每一个精心设计的矩阵一样使用下标。

考虑到这些,我们得到一个简化的矩阵类,如下所示:

template <class T>
class matrix { 
    std::vector<T> data;
    size_t cols;
public:
    matrix(int x, int y) : cols(x), data(x*y) {}
    T &operator()(int x, int y) { 
         return data[cols * y + x];
    }
};

请注意,为简单起见,当您为其添加下标时,您将大致像在 Fortran 或 BASIC 中一样使用 (),而不是像通常那样使用 [] C 或 C++。您可以支持后者,但这需要更多(而且更难看)code 。另请注意,您想要cols * (y+x),如果您坚持使用,则需要(cols * y) + x括号(尽管认为这很愚蠢,因为乘法和加法的相对优先级是众所周知的。最后,我将其作为模板,只是因为这样做很容易 - 如果您想直接指定类型,那就是显然很容易做到。

最后,我将把文件中的数据读取到矩阵中作为一个自由函数。这样做时,我会摆脱所有 while (!whatever.eof()),因为它们几乎肯定会错误地工作。

template <class T>
void read_matrix(std::string const &filename, matrix<T> &m) { 
    std::ifstream infile(filename);
    std::string line;
    int x = 0, y=0;

    while (std::getline(infile, line)) {
        if (line[0] == '#' || line[0] == ' ')
            continue;

        int value;
        std::istringinstream converter(&line[1]); // &line[1] to skip leading letter
        while (converter >> value)
            m(x++, y) = value;
        ++y;
    }            
}

从技术上讲,&line[1] 不能保证在 C++03 上工作,但 C++11 确实可以保证它,主要是因为它可以与所有已知的实现一起工作。

关于c++ - 从文件加载矩阵,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4914654/

相关文章:

c++ - 如何写在文件中的特定行?

java - 从SD卡读取文件

c - 如何获取包含文件的底层挂载 block 设备?

windows - 如何查找 NTFS 逻辑簇是否空闲?

c++ - 实现定义的行为是否需要在 C++ 中的运行之间保持一致?

c++ - 使用 libtool 链接非 libtool 库

c++ - 纹理模型

C++冒泡排序动态分配数组

python - 写入文件的更好方法?

file - 处理时output.println()中的错误