从文件加载Matrix

时间:2011-02-06 16:45:23

标签: c++ file file-io matrix

我需要阅读矩阵数据,并在我的prrogram中创建矩阵。 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函数之前打印许多start reading matrix from file之一。

5 个答案:

答案 0 :(得分:3)

哦,我的。如果我听起来很苛刻,我希望你能原谅我,但是这段代码有很多很多的问题,一直从基本设计一直到你使用的循环之类的细节从文件中读取数据。

首先,在我看来,你的“矩阵”课程需要健康的“单一责任”。我把它拆成二维矩阵,没别的。

其次,我将摆脱自己处理内存管理的问题。你真正需要的只是一个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确实能够保证它,主要是因为它适用于所有已知的实现。

答案 1 :(得分:1)

此:

scores = new int[[*edge] [*edge]];

是无效的C ++语法。你是说这个吗?:

scores = new int[*edge * *edge];

同样,当您尝试访问scores的元素时,您应该执行以下操作:

scores[(cols * y) + x] = val;

顺便说一句,如果您不打算修改原始值,则无法通过指针将int传递给函数。我会将CreateMatrix()重写为:

void ScoreMatrix::CreateMatrix(int edge)
{
   scores =  new int[edge*edge];
   cols = edge;
}

答案 2 :(得分:1)

(如果您的代码不起作用)读取此(仅限于此)格式的C代码:

int base2num(char b)
// just a numbering scheme for the input characters. This indexing will be used
// in the matrix into which it is read
{
    switch (b) 
    {
    case 'A': case 'a': return 0; break;
    case 'C': case 'c': return 1; break;
    case 'G': case 'g': return 2; break;
    case 'T': case 't': return 3; break;
    case 'P': case 'p': return 4; break;
    case 'V': case 'v': return 5; break;
    case 'L': case 'l': return 6; break;
    case 'I': case 'i': return 7; break;
    case 'M': case 'm': return 8; break;
    case 'F': case 'f': return 9; break;
    case 'Y': case 'y': return 10; break;
    case 'W': case 'w': return 11; break;
    case 'H': case 'h': return 12; break;
    case 'K': case 'k': return 13; break;
    case 'R': case 'r': return 14; break;
    case 'Q': case 'q': return 15; break;
    case 'N': case 'n': return 16; break;
    case 'E': case 'e': return 17; break;
    case 'D': case 'd': return 18; break;
    case 'S': case 's': return 19; break;
    default: return -1;
    }
}

void str2int(char *line, int i, int *mat, char *arr)
{
    int m,k;
    char * endptr;
    endptr=line+1;
    for (m=0;m<23;m++)
    {
        k=base2num(arr[m]);
        if (k==-1)
            continue;
        mat[i*20+k]=strtol(endptr,&endptr,0);


    }
 }
void parseinp(FILE *fp, int *mat)
{
    int i,j;
    char line[256];
    char arr[23];

    while (fgets(line,256,fp)!=NULL)
    {    
        if (line[0]=='#')
            continue;

        i=3;
        j=0;
        if (base2num(line[3])!=-1) 
            //assumption: the first character is
        //part of the 20 bases
        {
            while(line[i]!='*') 
             // this is the first line of the table,
            // that which contains  A R N D etc.
            // store the chars in arr
            {
                arr[j]=line[i];
                j++;
                i+=3;
            }   
            continue;
        }   
        i=base2num(line[0]);
        if (i<0) // not one of the 20 core bases
        {
            continue;
        }
        else
        {
          //  printf("%d\n",i);
            str2int(line,i,mat,arr);
        }
    }
}

int * get_blosum()
{
    FILE *fp;
    int  *mat;
    int n,m;

    mat=(double *) calloc(400, sizeof(double));
    fp =fopen("BLOSUM62","r");
    if (fp==NULL)
    {
        perror("failed to open protein matrix file!");
    }
    parseinp(fp, mat);

    fclose(fp);
    return mat;
}

答案 3 :(得分:0)

您似乎错误地使用了[]语法。我想你想改变以下几行:

scores =  new int[[*edge] [*edge]];
scores[cols *[y + x]] = val;
return *scores[cols *[x + y]];

scores =  new int[(*edge) * (*edge)];
scores[cols * (y + x)] = val;
return *scores[cols * (x + y)];

请注意使用括号()代替[]

答案 4 :(得分:0)

要在其他人之前评估某些内容,请不要使用[],而应使用括号。它应该是这样的:

void ScoreMatrix::CreateMatrix(int *edge)
{
   scores =  new int[(*edge) * (*edge)];
   cols = *edge;
}

void ScoreMatrix::SetValue(int x, int y, int val)
{
    scores[cols * (y + x)] = val;
}

int ScoreMatrix::GetValue(int x, int y)
{
    return *scores[cols * (x + y)];
}