質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

89.98%

C言語の構造体で2分木を作るプログラムの実行時エラーの解決策を教えてください。

解決済

回答 3

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 1,713

Breaststroke

score 6

初心者なので不備が多いかと思いますが、とりあえず動くようにしたいです。
自分でいろいろいじってみましたがどうしてもわかりません。
どこをどう直せばいいのかどなたかご教授お願い致します。

概要

英文が書かれたテキストファイルから単語(スペースで区切られた塊)
を切り出して2分木にソートして順番に表示するプログラム

問題点

コンパイルは通るが、実行時に「動作を停止しました。」と出る。
デバッグすると、printTree()内のprintf()でアクセス違反が生じている。

環境

windows10
Visual Studio 2013

追記

お二方回答ありがとうございます。
fscanfで読み込んで、新しく型のエラーが生じたところを修正したところ、
一応例外は吐かなくなりました。残りは何とか考えますmm

修正前コード

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

typedef char DATA;
struct node {
    DATA d;
    int count;
    struct node *left; // 左部分木
    struct node *right; // 右部分木
};
typedef struct node NODE;
typedef NODE *BTREE;
BTREE insertNode(BTREE, DATA*);
BTREE allocNode(DATA);
void printBtree(BTREE);
void freeBtree(BTREE);

int main(void){
    FILE *fp;
    BTREE root = NULL;
    DATA str[50];
    fp = fopen("./a.txt", "r");
    if (fp == NULL){
        printf("\aファイルをオープンできません。\n");
    }
    else {
        while (fgetc(fp) != EOF){
            root = insertNode(root, str);
        }
        printBtree(root);
        freeBtree(root);
        fclose(fp);
    }
    return 0;
}

BTREE insertNode(BTREE node, DATA *x) {
    BTREE  p = node;
    DATA dat = *x;
    if (p == NULL) {  // rootに挿入
        p = allocNode(dat);
        return  p;
    }
    if (dat == p->d)
    {
        p->count++;
    }
    else if (dat < p->d)
    {
        // 左部分木に割り当て
        p->left = insertNode(p->left, &dat);
        // 再帰呼出し
    }
    else  {
        // 右部分木に割り当て
        p->right = insertNode(p->right, &dat);
        // 再帰呼出し
    }
    return  p;
}

BTREE allocNode(DATA  x) {
    BTREE  p;
    p = (BTREE)malloc(sizeof(NODE));
    p->d = x;
    p->left = p->right = NULL;
    return  p;
}

void printBtree(BTREE p) {
    if (p != NULL) {
        printBtree(p->left);        // 左部分木の処理(再帰呼び出し)
        printf("WORD : %s COUNT : %d\n",  p->d, p->count);
        printBtree( p->right );     //  右部分木の処理(再帰呼び出し)
    }
    else printf("p==NULL\n");
    return;
}

void freeBtree(BTREE p) {
    if (p != NULL) {
        freeBtree(p->left);        // 左部分木の処理(再帰呼び出し)
        freeBtree( p->right );     //  右部分木の処理(再帰呼び出し)
        free( p );
    }
    return;
}
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 3

+3

printfのフォーマット指定子が間違っているようです。

charを出力する際には%cをつかいます。
%sはchar*(NUL文字で終わる文字列)を出力する際に用いるものです。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/05/09 10:24

    回答ありがとうございます!

    キャンセル

checkベストアンサー

+1

ちょっと見ですが

        while (fgetc(fp) != EOF){
            root = insertNode(root, str);
        }


1.fgetc()で文字を読み込んでいない
2.この段階でstrのは何が入っているか分からない
3.strに文字列を格納するなら空白が出てくるまで読み込んで、文字列(終端'\0')として渡す必要がある。
[追記]

struct node {
    DATA d; <-これは?これでいいのか? 文字列では?
    int count;
    struct node *left; // 左部分木
    struct node *right; // 右部分木
};


文字列と文字との処理が混在しているようですが?

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/05/09 10:21

    ありがとうございます!

    キャンセル

  • 2017/05/09 10:51

    私の方に勘違いがあったようで、ファイルから読み込んだ文字列中の文字の出現率をカウントしてるようですが・・・であればfgets()を使って一行丸ごと読んでから処理した方がいい気がします。この場合、空白もカウントしても(表示するときにカットするなどすれば)問題ないような気もします。

    キャンセル

0

解決済ですがfgetcで作成してみました。

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

typedef char DATA;
struct node {
    DATA d[50];
    int count;
    struct node *left; // 左部分木
    struct node *right; // 右部分木
};
typedef struct node NODE;
typedef NODE *BTREE;
BTREE insertNode(BTREE, DATA *);
BTREE allocNode(DATA *);
void printBtree(BTREE);
void freeBtree(BTREE);

int main(void){
    FILE *fp;
    BTREE root  = NULL;
    BTREE rootS = NULL;
    char buf[50] = {0};
    char c;
    DATA *str = buf;
    int i = 0;
    fp = fopen("./a.txt", "r");
    if (fp == NULL){
        printf("\aファイルをオープンできません。\n");
    }
    else {
        while ((c=fgetc(fp)) != EOF){
          if ( c == '\n' || c == ' ' || c == '.' || c == ',' ){
            if ((strlen(str)) > 0){
                  root = insertNode(root, str);
               if ( rootS == NULL ) rootS=root;
            }
            i=0;
          }else{
            buf[i] = c;
            i++;
          }
          buf[i] = '\0';
        }

        printBtree(rootS);
        freeBtree(rootS);
        fclose(fp);
    }
    return 0;
}

BTREE insertNode(BTREE node, DATA *x) {
    BTREE  p = node;
    DATA *dat = x;
    if (p == NULL) {  // rootに挿入
        p = allocNode(dat);
        return  p;
    }
    if ((strcmp(dat,p->d)) == 0)
    {
        p->count++;
    }
    else if ((strcmp(dat,p->d)) < 0)
    {
        // 左部分木に割り当て
        p->left = insertNode(p->left, dat);
        // 再帰呼出し
    }
    else  {
        // 右部分木に割り当て
        p->right = insertNode(p->right, dat);
        // 再帰呼出し
    }
    return  p;
}

BTREE allocNode(DATA  *x) {
    BTREE  p;
    p = (BTREE)malloc(sizeof(NODE));
    strcpy(p->d, x);
    p->count=1;
    p->left = p->right = NULL;
    return  p;
}

void printBtree(BTREE p) {
    if (p != NULL) {
        printBtree(p->left);        // 左部分木の処理(再帰呼び出し)
        printf("WORD : %-14s COUNT : %d\n",  p->d, p->count);
        printBtree( p->right );     //  右部分木の処理(再帰呼び出し)
    }
    return;
}

void freeBtree(BTREE p) {
    if (p != NULL) {
        freeBtree(p->left);        // 左部分木の処理(再帰呼び出し)
        freeBtree( p->right );     //  右部分木の処理(再帰呼び出し)
        free( p );
    }
    return;
}

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 89.98%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る

  • トップ
  • Cに関する質問
  • C言語の構造体で2分木を作るプログラムの実行時エラーの解決策を教えてください。