0

Cは初めてですが、このリンクリストプログラムを作成しようとしていますが、セグメンテーション違反が発生し続けます。11.リンクリストの作成だけにある問題に絞り込んだと思います。問題のある領域。このセクションをコメントアウトすると、セグメンテーション違反は発生しません。

私は紙の上で何が起こっているのかを調べ続けていますが、なぜそれが機能しないのか理解できません。経験が浅いので、ポインタやmallocの使用を誤解しているだけかもしれません。

このプログラムで動作するテキストファイルの例:

>984932:39284 mus musculus okodvcxvmkw2e2p \n
ATCTCAATCGCACTATCTAGCATGTCGTATGCTTGCATGTCGTAGTCGT\n
ATGCTATGCTTACTCTATTTACGGCGCATCGTGATCGTAGGAGCGAGCT\n

>984932:39284 mus huumoros okodvcxvmkw2e2p \n
ATCTCAATCGCACTATCTAGCATGTCGTATGCTTGCATGTCGTAGTCGT\n
ATGCTATGCTTACTCTATTTACGGCGCATCGTGATCGTAGGAGCGAGCT\n

>984932:39284 mus pisces okodvcxvmkw2e2p \n
ATCTCAATCGCACTATCTAGCATGTCGTATGCTTGCATGTCGTAGTCGT\n
ATGCTATGCTTACTCTATTTACGGCGCATCGTGATCGTAGGAGCGAGCT\n

私がやろうとしていること:リンクリストを作成します。各ノードは上のテキストの1ブロックです。つまり、各ノードには、「>」で始まるヘッダーと、すべてのACTGであるシーケンスデータが含まれます。上記のサンプルテキストファイルでは、リスト内のヘッド/テールノードに加えて3つのノードがあります。

私がそれをやろうとしている方法(問題のセクション):Charがスキャンされます。charが'>'の場合、ヘッダーにいることがわかり、改行文字に到達するまで、後続のすべての文字を新しいノードのヘッダーフィールドに読み込みます。この時点で、シーケンスデータを読み込むことがわかります。別の「>」に到達するまでこれを続け、到達したら繰り返します。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int list_header_size = 200;
int list_data_size = 2000;

struct list{
    char *header;
    char *data;
    struct list *next;
    struct list *prev;
};

//append char onto a string
void append(char *s, char c){
    int len = strlen(s);
    s[len] = c;
    s[len + 1] = '\0';
}

int create_list(char *filename){

    FILE *fp = fopen(filename, "r");

    if(fp == NULL){
        printf("File could not be opened. Exiting..");
        exit(1);
    }

    //setup head - doesn't hold a char
    struct list *head = malloc(sizeof(struct list));
    head->next = NULL;
    head->header = NULL;
    head->data = NULL;
    head->prev = NULL;

    //setup tail - doesn't hold a char
    struct list *tail = malloc(sizeof(struct list));
    tail->next = NULL;
    tail->header = NULL;
    tail->data = NULL;
    tail->prev = NULL;

    /***scan the .fasta file, populate list***/

    //char holder
    char c;
    int list_size = 0;
    int i = 1;

    //pull single char from file until end of file is reached
    do{

        c = getc(fp);

        //******PROBLEM IS IN THIS SECTION********//

        //if header text is found
        if(c == '>'){

            //create a node
            struct list *temp = malloc(sizeof(struct list));

            //first case to setup head
            if(i == 1){
                head->next = temp;
                temp->prev = head;
                i = 0;
            }

            tail->next = temp;
            tail->prev = temp;

            //create space for header/sequence data in the new node
            temp->header = (char*) malloc(sizeof(list_header_size));
            temp->data = (char*) malloc(sizeof(list_sequence_size));

            //add current char to header
            append(temp->header, c);

            c = getc(fp);

            //put file's header data into node's header data
            while(c != '\n'){
                append(temp->header, c);

                c = getc(fp);
            }

            //put file's sequence data into node's sequence data
            while(c != '>' && c != EOF){
                append(temp->data, c);
            }
        }

        //*******END OF PROBLEM SECTION********//

    }while(c != EOF);

    /***end of scanning .fasta file and creating linked list***/

    return 1;
}

int main(int argc, char * argv[]){

    char *filename = (char*) malloc(80);

    //check options
    int i;
    for(i = 1; i < argc; i++){

        if(argv[i][0] == '-'){

            switch(argv[i][1]){     
                default:;
            }

        }else{
            //arg is filename
            filename = argv[i];
        }

    }

    create_list(filename);

    return 1;
}
4

2 に答える 2

4

最も直接的なことはこれです:

  //create space for header/sequence data in the new node
  temp->header = (char*) malloc(sizeof(list_header_size));
  temp->data = (char*) malloc(sizeof(list_sequence_size));

私はこれがこれであるべきだと信じています:

  //create space for header/sequence data in the new node
  temp->header = malloc(list_header_size);
  temp->data = malloc(list_sequence_size);

もしあなたがCに慣れていないのなら、おそらくここにも他のことがありますが、mallocとそのサイズは常に私が最初にチェックするものであり、これは正しくありません。

別の問題を編集する:

これでバッファが割り当てられましたが、append()関数は、バッファが最初からゼロで終了することを想定しています。ではない。これを追加:

  temp->header = malloc(list_header_size);
  temp->data = malloc(list_sequence_size);
  temp->header[0] = temp->data[0] = 0; // <=== this

正直なところ、これらのサイズは固定されているので、実際のノード構造を次のように宣言するだけです。

struct list{
    char header[200];
    char data[2000];
    struct list *next;
    struct list *prev;
};

そして、すべての余分な割り当てを完全に回避し、フィールドではなくノードを割り当てるだけです。フィールドサイズが動的になる場合は、これを変更する必要がありますが、それまでは単純にしてください。

于 2013-02-22T16:32:37.100 に答える
1

私はあなたのappend(...)関数と、それにフィードするデータを見てみたいと思います。関数への最初の呼び出しは

append(temp->header, c);

ゼロにtemp->headerなることは保証されていません。ほとんどのコンパイラはそれをゼロにします(またはそうしようとします)が、それは何でも指すことができます。callocの代わりに使用しmallocます。

于 2013-02-22T16:42:14.240 に答える