バイナリツリーの作成について

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
Keikisa

バイナリツリーの作成について

#1

投稿記事 by Keikisa » 3ヶ月前

二分木のプログラムを作っています.
文字列の読み込みができないのはなぜでしょうか.
ファイルオープンのエラーはありません.

コード:

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

typedef struct BTREE_ {
    struct BTREE_ *left, *right;
    char data[20];
}Btree;

Btree *newCell(char *data) {
    Btree *bp;
    bp = (Btree *)malloc(sizeof(Btree));
    bp->left = NULL;
    bp->right = NULL;
    strcpy(bp->data, data);
    return bp;
}
Btree *registBtree(Btree *node, char *newdata) {
    int len1, len2;
    len1 = strlen(node->data);
    len2 = strlen(newdata);
    if (node == NULL) {
        node = newCell(newdata);
    }
    else if (len2 < len1) {
        node->left = registBtree(node->left, newdata);
    }
    else {
        node->right = registBtree(node->right, newdata);
    }
    return node;
}
/* 部分木の全ての値を出力 */
Btree *printBtree(Btree *node) {
    if (node == NULL) {
        return NULL;
    }
    printBtree(node->left);
    printf("data[%s]\n", node->data);
    printBtree(node->right);
    return node;
}
int main() {
    FILE*fp;
    Btree *start;
    //int newdata = 0;
    char newdata[20];
    if ((fp = fopen("food.txt", "r")) == NULL) {
        fprintf(stderr, "%s\n", "error: can't read file.");
        return EXIT_FAILURE;
    }
    fscanf(fp, "%s", newdata);//root
    start = newCell(newdata);
    while (fscanf(fp, "%s", newdata) != EOF) {
        registBtree(start, newdata);
    }
    printBtree(start);
    return 0;
}

アバター
みけCAT
記事: 6189
登録日時: 8年前
住所: 千葉県
連絡を取る:

Re: バイナリツリーの作成について

#2

投稿記事 by みけCAT » 3ヶ月前

registBtree関数において、nodeがNULLかチェックする前にnode->dataにアクセスしているので、
2個目の文字列を読み込んだ後のregistBtree関数の呼び出しにより、
アクセス違反でプログラムが強制終了してしまい、3個目以降の文字列が読み込めないようですね。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

アバター
みけCAT
記事: 6189
登録日時: 8年前
住所: 千葉県
連絡を取る:

Re: バイナリツリーの作成について

#3

投稿記事 by みけCAT » 3ヶ月前

オフトピック
ちなみに、ぱっと見main関数内でregistBtree関数の戻り値を投げ捨てていて良くないように見えますが、
よく見ると、(malloc関数が失敗しない場合)main関数のstartはNULLにならず、
registBtree関数はnodeがNULLでない場合渡されたnodeをそのまま返すので、
main関数内でregistBtree関数の戻り値をstartに代入しなくても問題はありません。
また、nodeにNULLを渡す可能性があるregistBtree関数内では、
仮にアクセス違反による強制終了が起こらないとすると、
きちんとregistBtree関数の戻り値を適切な場所に代入しており、問題はありません。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

Keikisa

Re: バイナリツリーの作成について

#4

投稿記事 by Keikisa » 3ヶ月前

ご指摘ありがとうございました!!
改善できました。

返信

“C言語何でも質問掲示板” へ戻る