私はコード(一部に含まれています)の一部がfastaパーサーであるように、fasta filesを読み出す必要のあるコードを書いています。単一のシーケンスはfasta形式の複数の行にまたがることができるので、ファイルから読み込んだ複数の連続する行を連結して単一の文字列にする必要があります。これは、各行を読み込んだ後に文字列バッファをrealloc'ingすることで、シーケンスの現在の長さと読み込まれた行の長さになるようにします。私は空白を取り除くなど、いくつかの作業を行います。ファーストファイルは複数のシーケンスを含むことができます。同様に、私は2つの文字列(タイトルと実際のシーケンス)を持つ構造体の動的配列を "char *"として持っています。繰り返しますが、新しいタイトル( '>'で始まる行で紹介されます)が出現すると、シーケンスの数を増やしてシーケンスリストバッファを再割り当てします。私は理由を見ることができない私の人生のためにファイルクラッシュから読み込み中にreallocを使ってバッファを展開する
*** glibc detected *** ./stackoverflow: malloc(): memory corruption: 0x09fd9210 ***
Aborted
と第二の配列のためのスペースを割り当てる上のreallocのセグメンテーションフォルト。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <math.h>
#include <errno.h>
//a struture to keep a record of sequences read in from file, and their titles
typedef struct {
char *title;
char *sequence;
} sequence_rec;
//string convenience functions
//checks whether a string consists entirely of white space
int empty(const char *s) {
int i;
i = 0;
while (s[i] != 0) {
if (!isspace(s[i])) return 0;
i++;
}
return 1;
}
//substr allocates and returns a new string which is a substring of s from i to
//j exclusive, where i < j; If i or j are negative they refer to distance from
//the end of the s
char *substr(const char *s, int i, int j) {
char *ret;
if (i < 0) i = strlen(s)-i;
if (j < 0) j = strlen(s)-j;
ret = malloc(j-i+1);
strncpy(ret,s,j-i);
return ret;
}
//strips white space from either end of the string
void strip(char **s) {
int i, j, len;
char *tmp = *s;
len = strlen(*s);
i = 0;
while ((isspace(*(*s+i)))&&(i < len)) {
i++;
}
j = strlen(*s)-1;
while ((isspace(*(*s+j)))&&(j > 0)) {
j--;
}
*s = strndup(*s+i, j-i);
free(tmp);
}
int main(int argc, char**argv) {
sequence_rec *sequences = NULL;
FILE *f = NULL;
char *line = NULL;
size_t linelen;
int rcount;
int numsequences = 0;
f = fopen(argv[1], "r");
if (f == NULL) {
fprintf(stderr, "Error opening %s: %s\n", argv[1], strerror(errno));
return EXIT_FAILURE;
}
rcount = getline(&line, &linelen, f);
while (rcount != -1) {
while (empty(line)) rcount = getline(&line, &linelen, f);
if (line[0] != '>') {
fprintf(stderr,"Sequence input not in valid fasta format\n");
return EXIT_FAILURE;
}
numsequences++;
sequences = realloc(sequences,sizeof(sequence_rec)*numsequences);
sequences[numsequences-1].title = strdup(line+1); strip(&sequences[numsequences-1].title);
rcount = getline(&line, &linelen, f);
sequences[numsequences-1].sequence = malloc(1); sequences[numsequences-1].sequence[0] = 0;
while ((!empty(line))&&(line[0] != '>')) {
strip(&line);
sequences[numsequences-1].sequence = realloc(sequences[numsequences-1].sequence, strlen(sequences[numsequences-1].sequence)+strlen(line)+1);
strcat(sequences[numsequences-1].sequence,line);
rcount = getline(&line, &linelen, f);
}
}
return EXIT_SUCCESS;
}
サブストリングルーチンに関するすべてのコメントをありがとう。私は自分のコードで修正しました。しかし、負のインデックスを扱う方法が間違っていたことにも気付きました。私は、負のインデックスを追加する必要があります、それを引くことはありません。つまり、私は、貼り付けられたコードの残りの部分では呼び出さないので、substr関数を誤ってコピーしたことに気付きました。 – sirlark
'strip()'もバグです。長さのゼロの文字列で悪いことをするでしょう。このような文字列では呼び出さないように見えますが、他の場所で使用されているときに修正するのは良いことだと思います。 –