2011-02-06 115 views
2

我需要用矩阵数据读取文件并在我的程序中创建矩阵。矩阵文件格式类似于这样:从文件中加载矩阵

# 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一个之前。

回答

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; 
} 
+0

是的,但我知道某事得到这样的: “代码”(matryca_sub.cpp :29:错误:从'int *'无效转换为'int') – 2011-02-06 16:58:33

+0

@Mateusz:您是否复制了我的代码*完全*? – 2011-02-06 17:01:15

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)]; 

注意使用括号(),而不是[]的。

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)]; 
} 
3

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

首先,在我看来,你的“矩阵”类需要应用健康剂量的“单一责任”。我会把它分解成2D矩阵,没有别的。

其次,我会摆脱处理自己的内存管理。所有你真正需要的是一个std::vector,有足够的前端提供2D寻址。第三,我会摆脱“getValue”/“setValue”,并使用下标,就像自1950年代科学程序员从汇编语言转换到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),你想,如果你坚持要用括号(虽然认为这是非常愚蠢的,因为乘法和加法的相对优先级是非常著名。最后,我做了这个模板只是因为这很容易 - 如果你想直接指定类型,这显然很容易做到。

最后,我会从文件读取数据到一个矩阵到一个自由函数。这样做,我会摆脱所有的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

(如果你的代码不工作),AC码读取这个(也只有这个)格式:

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