掲示板利用宣言

 次のフォームをすべてチェックしてからご利用ください。

 私は

 題名と投稿者名は具体的に書きます。
 課題の丸投げはしません。
 ソースの添付は「HTML変換ツール」で字下げします。
 返信の引用は最小限にします。
 環境(OSとコンパイラ)や症状は具体的に詳しく書きます。
 返信の付いた投稿は削除しません。
 マルチポスト(多重投稿)はしません。

掲示板2

管理者用メニュー    ツリーに戻る    携帯用URL    ホームページ    ログ    タグ一覧

No.27308

ポインタを利用しての二分木
投稿者---社会人SE(2006/06/25 01:56:26)


Cのファイルを入力してソースの中の単語を読み込んでいき
その単語の個数が何個あったかを調べているのですが
ポインタがNULLを指してしまい。
正確な答えを出力することができません。

環境:winxp/gcc

#include<stdio.h>
#include<ctype.h>
#include<stdlib.h>
#include<string.h>
#define   N    256

struct node{
  char identifier[N];
  int number;
  struct node *left,*right;
}*root;

void initialize(struct node *);
struct node *search(struct node *,char *,int *);
void insert(struct node *,char *);         
void print(struct node *,int *,FILE *fout);   
void print2(int *,int *,FILE *fout);   
FILE *input(FILE *,char *);
FILE *output(FILE *,char *);
int get_word(char *,int ,FILE *fin);   

main(int argc,char *argv[]){
  int c,sum=0,num=0;
  char word[256],infile[40],outfile[40]; 
  FILE *fin,*fout;
  
  fin=input(fin,infile);                       
  fout=output(fout,outfile);                   

  initialize(root);                     
  while(get_word(word,c,fin)!=0){ 
 
    search(root,word,&num);  
    }
  print(root,&sum,fout);                   
  print2(&num,&sum,fout);                   
  fclose(fin);
  fclose(fout);
  return (0);
}


void initialize(struct node *root){
  root=NULL;
}

struct node *search(struct node *root,char *key,int *num){
  
  if(root==NULL){             
    insert(root,key);
    (*num)++;
  }

  else if(strcmp(key,root->identifier)==0){
      (root->number)++;
  }

  else if(strcmp(key,root->identifier) < 0){
    root->left = search(root->left,key,num);   
  }

  else if(strcmp(key,root->identifier) >0){    
    root->right = search(root->right,key,num);     
  }
  return root;
}

void insert(struct node *root,char *x){

    root=(struct node *)malloc(sizeof(struct node));   
    strcpy(root->identifier,x);        

    root->number=1;                       
    root->left=root->right=NULL;             /

}

void print(struct node *q,int *sum,FILE *fout){
             
  struct node *p;

  p = q;
                                  
  if(p!=NULL){
    print(p->left,sum,fout);                   
    fprintf(fout,"     %s",p->identifier);  
    fprintf(fout,"  %d\n",p->number);       
    (*sum)+=p->number;                         
    print(p->right,sum,fout);                   
  }
  else{
    printf("\nNULL");
  }
}

void print2(int *num,int *sum,FILE *fout){
                                  
fprintf(fout,"\n  The kind of character sequence             : %d",*num);
fprintf(fout,"\n  The number of a character sequence         : %d",*sum);
fprintf(fout,"\n  The average number of a character sequence : %.2f",(double)(*sum)/(*num)); 
}

int get_word(char *word,int c,FILE *fin){
  int i=0; 
                                 
   while((c=getc(fin))!=EOF){
     if(isalpha(c) && i==0){
      word[i]=c;
      i++;
    }

     else if((isalnum(c) || '_'==c) && i!=0){
      word[i]=c; 
      i++;
    }

     else if(!isalnum(c)){
      if(i!=0){
      word[i]='\0';
      return 1;
      }
    }
   }
   return 0;
}

FILE *input(FILE *fin,char *infile){
                                       
  do{
  printf("Input FILE:");
  gets(infile);
    if((fin=fopen(infile,"r"))==NULL) {
      printf("can not open Input FILE!\n\a");
      printf("Please input a file name once again!\n\n");
    }
   }while((fin=fopen(infile,"r"))==NULL);
  }

FILE *output(FILE *fout,char *outfile){
                                      
  printf("Output FILE:");
  gets(outfile);
    if((fout=fopen(outfile,"w"))==NULL) {
      printf("can not open Output FILE!\n\a");
      exit(1);
    }
}



この投稿にコメントする

削除パスワード

発言に関する情報 題名 投稿番号 投稿者名 投稿日時
<子記事> Re:ポインタを利用しての二分木 27309 かずま 2006/06/25 04:38:35


No.27309

Re:ポインタを利用しての二分木
投稿者---かずま(2006/06/25 04:38:35)


どこが悪いのか説明するのが面倒なので、次のプログラムと比べて、
何が違うのかを考えて、あなたが報告してください。
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#include <string.h>

struct node {
    char *identifier;
    int number;
    struct node *left, *right;
};

void initialize(struct node **);
struct node *search(struct node *, const char *, int *);
struct node *insert(const char *);
void print(struct node *, int *, FILE *);
void print2(int *, int *, FILE *);
FILE *input(const char *);
FILE *output(const char *);
int get_word(char *, FILE *);

int main(void)
{
    int sum = 0, num = 0;
    char word[256], infile[40], outfile[40];
    FILE *fin, *fout;
    struct node *root;

    fin = input(infile);
    fout = output(outfile);

    initialize(&root);
    while (get_word(word, fin) != 0)
        root = search(root, word, &num);
    print(root, &sum, fout);
    print2(&num, &sum, fout);
    fclose(fin);
    fclose(fout);
    return (0);
}

void initialize(struct node **root)
{
    *root = NULL;
}

struct node *search(struct node *root, const char *key, int *num)
{
    int diff;
    if (root == NULL) {
        ++*num;
        return insert(key);
    }
    diff = strcmp(key, root->identifier);
    if (diff == 0)
        root->number++;
    else if (diff < 0)
        root->left = search(root->left, key, num);
    else
        root->right = search(root->right, key, num);
    return root;
}

struct node *insert(const char *x)
{
    struct node *root = malloc(sizeof(struct node));
    root->identifier = strdup(x);
    root->number = 1;
    root->left = root->right = NULL;
    return root;
}

void print(struct node *p, int *sum, FILE *fout)
{
    if (p != NULL) {
        print(p->left, sum, fout);
        fprintf(fout, "%6d %s\n", p->number, p->identifier);
        *sum += p->number;
        print(p->right, sum, fout);
    }
}

void print2(int *num, int *sum, FILE *fout)
{
    fprintf(fout, "\n  The kind of character sequence             : %d", *num);
    fprintf(fout, "\n  The number of a character sequence         : %d", *sum);
    fprintf(fout, "\n  The average number of a character sequence : %.2f\n", (double)*sum / *num);
}

int get_word(char *word, FILE * fin)
{
    fscanf(fin, "%*[^a-zA-Z_]");
    return fscanf(fin, "%255[a-zA-Z_0-9]", word) == 1;
}

FILE *input(const char *infile)
{
    FILE *fin;
    for (;;) {
        printf("Input FILE:");
        gets(infile);
        fin = fopen(infile, "r");
        if (fin) return fin;
        printf("can not open Input FILE!\n\a");
        printf("Please input a file name once again!\n\n");
    }
}

FILE *output(const char *outfile)
{
    FILE *fout;
    printf("Output FILE:");
    gets(outfile);
    fout = fopen(outfile, "w");
    if (fout == NULL) {
        printf("can not open Output FILE!\n\a");
        exit(1);
    }
    return fout;
}



この投稿にコメントする

削除パスワード

No.27310

Re:ポインタを利用しての二分木
投稿者---社会人SE(2006/06/25 10:53:43)


厳しい指摘ありがとうございます。

私のプログラムは↓であるのに対し
void initialize(struct node *root){
  root=NULL;
}



あなたのは↓
void initialize(struct node **root)
{
    *root = NULL;
}


になっていますね。
どうしてダブルポインタを使用するのでしょうか?


この投稿にコメントする

削除パスワード

No.27311

Re:ポインタを利用しての二分木
投稿者---επιστημη(2006/06/25 11:30:01)


>どうしてダブルポインタを使用するのでしょうか?

↓コレと同じこと。
/* iに1を加える */

/* まちがい */
void inc(int i) { i++; }
int main() { int i = 0; inc(i); /* i は0のまま */ ... }

/* 正解 */
void int(int* i) { (*i)++; }
int main() { int i = 0; inc(&i); /* i は1になる */ ... }



この投稿にコメントする

削除パスワード

No.27312

Re:ポインタを利用しての二分木
投稿者---社会人SE(2006/06/25 12:00:20)


つまり

*root は構造体のstruct nodeを指すのに対し

**root は何を指すのでしょうか??


この投稿にコメントする

削除パスワード

No.27314

Re:ポインタを利用しての二分木
投稿者---kz3(2006/06/25 12:25:56)


>*root は構造体のstruct nodeを指すのに対し
>
>**root は何を指すのでしょうか??

「ダブルポインタ」っと慣れたように呼んでいるので
分かっているんじゃないかと思っていましたが、分かっていないんですねorz
(「ダブルポインタ」という呼び方は結構使われているんですか?初耳です... )

ポインタのポインタを読んでみてください。

と書いてみましたが...
ポインタの配列をポインタのポインタで受け取る、
と余計なものが入っていて分かりにくかったかもです。

int型へのポインタを受け取る変数の型はint *型
int *型へのポインタを受け取る変数の型はint **型

intをstruct nodeに読み替えて、逆から読んでみてください。分かると思います。
合わせて関数initialize()が何をするための関数なのかも考えると理由が分かると思います。



この投稿にコメントする

削除パスワード

No.27315

Re:ポインタを利用しての二分木
投稿者---社会人SE(2006/06/25 13:02:23)


ありがとう。
つまり
*rootはstruct nodeを指すものであり
**rootはstruct nodeの中身を指すものですね☆

initialize()はつまりstruct nodeの中身を全部NULLにしちゃうことですね。


この投稿にコメントする

削除パスワード

No.27320

Re:ポインタを利用しての二分木
投稿者---επιστημη(2006/06/25 16:46:28)


>initialize()はつまりstruct nodeの中身を全部NULLにしちゃうことですね。

ちがう。


この投稿にコメントする

削除パスワード

No.27324

Re:ポインタを利用しての二分木
投稿者---επιστημη(2006/06/25 17:06:11)


>*rootはstruct nodeを指すものであり
>**rootはstruct nodeの中身を指すものですね☆

**rootは "struct nodeを指すもの"を指すもの。



この投稿にコメントする

削除パスワード

No.27325

Re:ポインタを利用しての二分木
投稿者---かずま(2006/06/25 17:25:01)


>> *rootはstruct nodeを指すものであり
>> **rootはstruct nodeの中身を指すものですね☆
>
> **rootは "struct nodeを指すもの"を指すもの。
ちがう。
struct node **root と宣言されているとき、
root は "struct nodeを指すポインタ"を指すポインタ。
*root は struct nodeを指すポインタ。
**root は struct node。



この投稿にコメントする

削除パスワード

No.27327

Re:ポインタを利用しての二分木
投稿者---επιστημη(2006/06/25 17:27:45)


>>> *rootはstruct nodeを指すものであり
>>> **rootはstruct nodeの中身を指すものですね☆
>>
>> **rootは "struct nodeを指すもの"を指すもの。
>
> ちがう。

> struct node **root と宣言されているとき、
> root は "struct nodeを指すポインタ"を指すポインタ。
> *root は struct nodeを指すポインタ。
> **root は struct node。

ですね。

struct node **root と表記されているときのrootは
"struct nodeを指すもの"を指すもの。



この投稿にコメントする

削除パスワード

管理者用メニュー    ツリーに戻る    携帯用URL    ホームページ    ログ    タグ一覧