C言語関係掲示板

過去ログ

No.1162 リストのソート

[戻る] [ホームページ]
No.15087

自己参照構造体
投稿者---猛蹴士(2004/06/30 21:01:32)


本当にたびたびすいません。自己参照構造体を勉強していて
いきずまってしまいました。

現在、30件以上のデータ量があった場合はエラーになってしまう
ところをメモリの限界まで大丈夫にしたいのですが、術がわかりません。

このHPの自己参照構造体のところも何度も読んだのですが、はっきり
理解ができませんでした。

もしこのロジックを自己参照構造体で書き直すとしたら、現在使っている
添え字とかは使えなくなって、大幅な改良が必要でしょうか?

本当にすいません!! お暇な方がいらっしゃいましたらご指導願いたいです!!

自己参照構造体を使用するための準備のようなロジックだけは
入れたのですが・・・↓
<pre>#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;string.h&gt;
#define TRUE 1
#define FALSE 0

struct meibo {
    char  name[21];
    char  danjo;
    int   postNo;
    struct meibo *next;
};

main(int argc, char *argv[])
{
  FILE *fin,*fout;
  char  s[256]; 
  int  i,x=0,y,erlflg,NUM,Cnt;
  
  /*struct meibo member[30];*/

  struct meibo member;          
  struct meibo *head = &amp;member; /*最初の構造体の場所を記憶する*/
  struct meibo *wkdata; /* データ設定用 */
  struct meibo *wp;     /* 作業用ポインタ*/
  
  head = &amp;member;
  head-&gt;next = NULL;  /* 最初はデータがないのでNULLを設定 */

  
  struct meibo temp;

  /* 引数の個数チェック*/
  if (argc != 2){
     printf(&quot;引数の個数が違います\n&quot;);
     exit(1);
  }

  /* 入力ファイルOPEN */
  if((fin=fopen(&quot;SV.ADR&quot;,&quot;r&quot;)) == NULL){
      printf(&quot;入力ファイルが存在しないか、オープンできない\n&quot;);
      exit(1);
  }

  /* 出力ファイルOPEN */
  if((fout=fopen(&quot;ADR.SV&quot;,&quot;w&quot;)) == NULL){
      printf(&quot;出力ファイルがオープンできない\n&quot;);
      exit(1);
  }

  /* ファイルを1行ずつ最後まで読み込む*/
  while(fgets(s,256,fin)!=NULL){
     i=0; 
     erlflg = FALSE;

    /* 名前の文字列を取得*/
     while(s[i]!=' ' &amp;&amp; s[i]!='\t'&amp;&amp; s[i]!='\n'&amp;&amp;i&lt;20){
           member[x].name[i] = s[i];
           i++;
     }
     /* 終端コード*/
     member[x].name[i] = '\0';

       /* 名前が入っていない場合 */
       if (strlen(member[x].name)==0){
           /* エラー行と見なす*/
           erlflg = TRUE;
       }

     /* スペース、タブ、改行の場合、文字数カウントアップ*/
     while(s[i]==' '||s[i]=='\t'||s[i]=='\n'){
           i++;                            
     }
     /* 男女別を取得*/ 
     Cnt = 0;
     while(s[i]!=' '&amp;&amp;s[i]!='\t'&amp;&amp;s[i]!='\n'){
           /* 男女別取得時にM,F以外の文字を取得した場合*/
           if (s[i]!='M'&amp;&amp; s[i]!='F'){
               /* エラー行と見なす*/ 
               erlflg = TRUE;
           }
           else {
               member[x].danjo = s[i];
           }
           i++;
           Cnt++;
     }
        /* 男女別を1文字以上を取得した場合 */
        if (Cnt &gt; 1){
            /* エラー行と見なす*/
            erlflg = TRUE;
        }

     /* スペース、タブ、改行の場合、文字数カウントアップ*/
     while(s[i]==' '||s[i]=='\t'||s[i]=='\n'){
           i++;
     }

     /* 郵便番号を取得*/    
     member[x].postNo = 0;
     Cnt=0;
     while(s[i]!=' '&amp;&amp;s[i]!='\t'&amp;&amp;s[i]!='\n'&amp;&amp; s[i]!='\0'){

           /* 郵便番号に数字以外のものが含まれていた場合の考慮 */
           if (isdigit(s[i])) {
                member[x].postNo = member[x].postNo * 10 + s[i] - '0'; 
           }
           else {
                erlflg = TRUE;
           }
           i++;
           Cnt++;
     }
     /* 郵便番号が取得できない場合*/
     if ( member[x].postNo==0){
          /*エラー行と見なす*/
          erlflg = TRUE;
     }
     /* 郵便番号を3文字以上取得した場合*/ 
     if ( Cnt &gt; 3 ){
          /* エラー行と見なす*/
          erlflg = TRUE;
     }


     -- こんなところに入れていいんでしょうか?--
     /* 記憶領域の確保 */
     if ((wkdata = (struct meibo *)malloc(sizeof(struct meibo)))==NULL){
         printf(&quot;メモリ確保できません\n&quot;);
         exit(1);
     }



     /* エラー行でない場合 */
     if (erlflg == FALSE){
        /* 行数カウントアップ */
        x++;
     }
  }

  /* 引数によって、昇順、降順ソートを判断する*/ 
  NUM = x;
  if (strcmp(argv[1],&quot;1&quot;) == 0) {
       /* 郵便番号昇順ソート*/
       for (i=0; i&lt;NUM; i++){
            for(x=NUM-1; x&gt;i ; x--){
              /* 前の要素の方が大きい場合 */
              if ( member[x-1].postNo &gt; member[x].postNo){
                  /* 順番を入れ替える*/
                  temp = member[x];
                  member[x] = member[x-1];
                  member[x-1] = temp;
              }          
            }     
       }
   }
   else if(strcmp(argv[1],&quot;2&quot;) == 0){
           /* 郵便番号降順ソート */
           for (i=0; i&lt;NUM; i++){
                for(x=NUM-1; x&gt;i ; x--){
                    /* 前の要素の方が小さい場合 */
                    if ( member[x-1].postNo &lt; member[x].postNo){
                        /* 順番を入れ替える*/
                        temp = member[x];
                        member[x] = member[x-1];
                        member[x-1] = temp;
                    }
                }
            }
   }
   else {
          printf(&quot;引数の値が違います\n&quot;);
          exit(1);
   }
 
   /* ファイル印字 */
   for(x=0;x&lt;NUM;x++){
      fprintf(fout,&quot;%-10d%-20s%-20c\n&quot;,member[x].postNo,member[x].name,member[x].danjo);
   }

   fclose(fin);
   fclose(fout);

   return 0;
}

</pre>





No.15088

Re:自己参照構造体
投稿者---ぽこ(2004/06/30 21:37:43)


>このHPの自己参照構造体のところも何度も読んだのですが、はっきり
>理解ができませんでした。
>

どこまでが理解できて、どこまでが理解できなかったのでしょうか?


No.15089

Re:自己参照構造体
投稿者---猛蹴士(2004/06/30 21:42:21)


>
>どこまでが理解できて、どこまでが理解できなかったのでしょうか?

そういわれると困ってしまうんですが・・・
このHPの例ではポインタをつなぎかえることによって
降順の表示にしているんだなってことは理解できました。

ただ、それを自分のロジックでどう消化すればよいのかが
わからないのです。



No.15090

Re:自己参照構造体
投稿者---あかま(2004/06/30 21:49:25)


どこがわからないのか書くのは当然として。

プログラムは関数にまとめた版があるのだからそれを載せていただきたい。
main()しかないのでは改造のしようがない。

一つ前のスレッドのFILE*はうまくいったのかな?
file_open(FILE **fi,FILE **fo);
にして
*fi=fopen()
に変えるだけだと思うけど。

あとツールを使うときに変換ボタンを間違って2回押してますよ。


No.15091

Re:自己参照構造体
投稿者---猛蹴士(2004/06/30 22:15:21)


>どこがわからないのか書くのは当然として。
>
>プログラムは関数にまとめた版があるのだからそれを載せていただきたい。

>main()しかないのでは改造のしようがない。

関数にまとめたやつは長いので、わかりづらいかなと思いまして
あえてまとめてないほうにしました。


>
>一つ前のスレッドのFILE*はうまくいったのかな?

>あとツールを使うときに変換ボタンを間違って2回押してますよ。

おかげさまで、FILE*は上手くいきました。
ありがとうございました。

変換ボタン2回押してはいないんですけどね・・・ おかしいな。



No.15092

Re:自己参照構造体
投稿者---RAPT(2004/06/30 22:22:59)


> 変換ボタン2回押してはいないんですけどね・・・ おかしいな。
最初の <pre> の前に空白や文字を含めず、最後の </pre> 以降
に空白・改行や文字列を含めなければ、うまく表示されるはずです。

いずれにしろ、確認画面で投稿後のイメージを確認できるので、きちんと
投稿前に一通り確認するようにすれば、いいでしょう。

# 「確認画面」で確認しないのでは意味無いですね。
# コンパイル時の warning を無視してるようなものですね。




No.15093

Re:自己参照構造体
投稿者---猛蹴士(2004/06/30 22:27:00)


関数化したロジックです。入力ファイルチェック用関数
の内容が省略されていますが、長くて入りきらないので
その内容に関しては、このツリーの最初のロジックを
みてもらえればと思います。

わからないところは
自己参照構造体にした場合、これだけ添字を使ってるロジック
を大幅に書き換えなくてはならないのかという点

記憶領域の確保 をするためのロジック(mallocのところ)を
どこに入れればよいのか。

特につなぎ方を変えたいわけではなく、ただメモリの最大値
までデータを受け取れるようにするためにはどうしたらよいのか

といったところです。


ロジックです。


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define TRUE 1
#define FALSE 0

struct meibo {
    char  name[21];
    char  danjo;
    int   postNo;
    struct meibo *next;
};

/***********************
  関数化プロトタイプ↓ *
************************/
/* 初期処理用関数プロトタイプ */
int init(int kosu,char *str);

/* 主処理用関数プロトタイプ */
void shu_shori(FILE *fi,FILE *fo,struct meibo *dt,int sortjun); 

/* 終了処理用関数プロトタイプ */
void end(FILE *fi,FILE *fo);

/* ファイルオープン */
void file_open(FILE *fi, FILE *fo);

/* ソートパターン選択用関数プロトタイプ */
int sortptnsel(char *str);

/* 入力ファイルチェック用関数プロトタイプ */
int filchk( char s[256],int line,struct meibo *dt);

/* ソート用関数プロトタイプ */
void bubble_sort(struct meibo *dt,int NUM,int cmdline);

/* ファイル出力用関数プロトタイプ */
void memberfprnt(struct meibo *dt,int NUM,FILE *fo);
/***********************
  関数化処理        ↓ *
************************/
/* 初期処理用関数 */
int init(int kosu,char *str){
  int sortptn,e;
  
  e=-1;

  if (kosu != 2){
     printf("引数の個数が違います\n");
     return e;
  }

  /* ソートパターン選択 */
  sortptn = sortptnsel(str);

  return sortptn;
}

/* 主処理用関数 */
void shu_shori(FILE *fi,FILE *fo,struct meibo *dt,int sortjun){
   char  s[256]; 
   int   x=0,erlchk;
   
  /* ファイルリード*/
  while(fgets(s,256,fi)!=NULL){

     /* 入力ファイルチェック */
     erlchk = filchk( s,x,dt);

     /* エラー行でない場合 */
     if (erlchk == FALSE){
        /* 行数カウントアップ */
        x++;
     }
  }

  /*ソート処理*/ 
  bubble_sort(dt,x,sortjun);

  /* ファイル出力処理 */
  memberfprnt(dt,x,fo);
}
 

/* 終了処理用関数 */
void end(FILE *fi, FILE *fo){
  /* ファイルクローズ */
  fclose(fi);
  fclose(fo);
}

void file_open(FILE *fi, FILE *fo){
    /* 入力ファイルOPEN */
  if((fi=fopen("SV.ADR","r")) == NULL){
      printf("入力ファイルが存在しないか、オープンできない\n");
      return;
  }

  /* 出力ファイルOPEN */
  if((fo=fopen("ADR.SV","w")) == NULL){
      printf("出力ファイルがオープンできない\n");
      return;
  }
}

/* ソートパターン選択用関数 */
int sortptnsel(char *str){
   
  int sortptn;
  int  e;
  
  e=-1;

  if (strcmp(str,"1") == 0) {
     sortptn = 1;
  }
  else if (strcmp(str,"2") == 0){
     sortptn = 2;
  }
  else {
     printf("引数の値が違います\n");
     return e;
  }

   return sortptn;
}

/* 入力ファイルチェック用関数 */
int filchk( char s[256],int line,struct meibo *dt){

    int Cnt, erlflg,x,i;
     
    x= line;
    i= 0;

    erlflg = FALSE;

    〜長いので処理省略〜

}

/* ソート用関数 */
void bubble_sort(struct meibo *dt,int NUM,int cmdline){
  int i,x;
  struct meibo temp;

    〜長いので処理省略〜
}

/* ファイル出力用関数 */
void memberfprnt(struct meibo *dt,int NUM,FILE *fo){

  int i;

  /* ファイル印字 */
  for(i=0;i<NUM;i++){
      fprintf(fo,"%-10d%-20s%-20c\n",dt[i].postNo,dt[i].name,dt[i].danjo);
  }
}
/***********************
  メイン処理   ↓      *
************************/
main(int argc, char *argv[])
{
  struct meibo member[30];

  FILE *fin,*fout;
  /*char  s[256]; */
  /*int  x=0,erlchk,sortptn; */
  int  sortptn; 

  /* 初期処理 */
  sortptn = init(argc,argv[1]);

  /* エラーなら処理終了 */
  if (sortptn!=1&&sortptn!=2 ){
      return 1;
  }

  /* ファイルOPEN */
  file_open(fin, fout);

  /* 主処理 */
  shu_shori(fin,fout,member,sortptn); 

  /* 終了処理 */
  end(fin,fout);

  return 0;
}





No.15095

Re:自己参照構造体
投稿者---ぽこ(2004/06/30 22:53:47)


>わからないところは
>自己参照構造体にした場合、これだけ添字を使ってるロジック
>を大幅に書き換えなくてはならないのかという点

書き換える場所は少ないと思います。
ぱっと見、表示を行う関数とソートの関数の変更は必要と思います。

>記憶領域の確保 をするためのロジック(mallocのところ)を
>どこに入れればよいのか。

今まで解析したデータ(?)を配列に代入する部分で、
リストの要素の領域確保→データをセット→リストへ追加と
やれば良いと思います。

>特につなぎ方を変えたいわけではなく、ただメモリの最大値
>までデータを受け取れるようにするためにはどうしたらよいのか

リストに追加する要素数の制限を行わない、という認識で
よろしいでしょうか?
もし、そうであれば、何もしなければ良いと思います。



No.15096

Re:自己参照構造体
投稿者---猛蹴士(2004/06/30 23:24:21)


>>わからないところは
>>自己参照構造体にした場合、これだけ添字を使ってるロジック
>>を大幅に書き換えなくてはならないのかという点
>
>書き換える場所は少ないと思います。
>ぱっと見、表示を行う関数とソートの関数の変更は必要と思います。
>

member[x].name[i] みたいになっている場所は自己参照構造体にした
場合、書き換えなくてはならないという訳ではないのですか? 
自分ではそんな解釈だったんですけど・・・


No.15097

Re:自己参照構造体
投稿者---ぽこ(2004/06/30 23:33:55)


>member[x].name[i] みたいになっている場所は自己参照構造体にした
>場合、書き換えなくてはならないという訳ではないのですか? 
>自分ではそんな解釈だったんですけど・・・

データの表示を行う部分以外で、
再提示されたソースコードにはそのような部分は見受けられませんが^^;

member[x]というのはx番目の要素ということですよね?
リストの先頭からx番目の要素を取得する関数を作ったほうが良さそうですね。



No.15098

Re:自己参照構造体
投稿者---猛蹴士(2004/06/30 23:48:56)


>>member[x].name[i] みたいになっている場所は自己参照構造体にした
>>場合、書き換えなくてはならないという訳ではないのですか? 
>>自分ではそんな解釈だったんですけど・・・
>
>データの表示を行う部分以外で、
>再提示されたソースコードにはそのような部分は見受けられませんが^^;

再表示したソースでは、ツリーの先頭のソースの
/*ファイルを1行ずつ最後まで読み込む*/ のところのロジックが
はしょってあります(関数内で「長いので省略」となっている部分)。member[x].name[i]はそこでつかっています。

ファイルを読み込んで、それを自己参照構造体に入れて込んでいき
その結果を出力ファイルに出力したい
という処理がやりたいだけなんですけどね・・・・





No.15099

Re:自己参照構造体
投稿者---あかま(2004/07/01 00:01:29)


で、貼られたプログラムのFILE *が結局直ってないとか、
省略したところは上のプログラムを見てくれと言われても
int filchk( char s[256],int line,struct meibo *dt){
    int Cnt, erlflg,x,i;
    x= line;
    i= 0;
    erlflg = FALSE;
    
    〜長いので処理省略〜
}
これじゃ返り値もなにもわからないから書き直せない。
とか色々あるんだけど、文句ばっかりつけててもしょうがないので。

その辺は適当に書いてリストへのメンバーの追加だけ書きました。
ソートはリストだとめんどくさいので自分でどうぞ。ポインタの付け替えは勉強になります。
後でソートしないで、リストに追加するときについでに並べるといいかもしれない。

リストの先頭ポインタ
struct meibo *top;
はグローバルで宣言しています。

まぁ、とりあえず動かしてみてください。

データ形式がわからないので適当な入力データ(SV.ADR)
akama,0,123
akama2,1,124
akama3,0,125

出力(ADR.SV)。入力の逆順になる。
125       akama3              0                   
124       akama2              1                   
123       akama               0                   


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define TRUE 1
#define FALSE 0

struct meibo {
    char  name[21];
    char  danjo;
    int   postNo;
    struct meibo *next;
};

/***********************
  関数化プロトタイプ↓ *
************************/
/* 初期処理用関数プロトタイプ */
int init(int kosu,char *str);

/* 主処理用関数プロトタイプ */
void shu_shori(FILE *fi,FILE *fo,int sortjun); 
/* 終了処理用関数プロトタイプ */
void end(FILE *fi,FILE *fo);
/* ファイルオープン */
void file_open(FILE **fi, FILE **fo);
/* ソートパターン選択用関数プロトタイプ */
int sortptnsel(char *str);
/* 入力ファイルチェック用関数プロトタイプ */
int filchk( char s[256]);
/* ソート用関数プロトタイプ */
void bubble_sort(struct meibo *dt,int NUM,int cmdline);
/* ファイル出力用関数プロトタイプ */
void memberfprnt(FILE *fo);

/***********************
  メイン処理   ↓      *
************************/

struct meibo *top;

main(int argc, char *argv[])
{
  
  FILE *fin,*fout;
  int  sortptn; 

  /* 初期処理 *//* エラーなら処理終了 */
  sortptn = init(argc,argv[1]);
  if (sortptn!=1&&sortptn!=2 ){
      return 1;
  }

  /* ファイルOPEN */
  file_open(&fin, &fout);
  /* 主処理 */
  shu_shori(fin,fout,sortptn); 
  /* 終了処理 */
  end(fin,fout);
  
  return 0;
}
/***********************
  関数化処理        ↓ *
************************/

/* 初期処理用関数 */
int init(int kosu,char *str){
  int sortptn,e;
  
  e=-1;
  if (kosu != 2){
     printf("引数の個数が違います\n");
     return e;
  }
  /* ソートパターン選択 */
  sortptn = sortptnsel(str);

  return sortptn;
}

/* 主処理用関数 */
void shu_shori(FILE *fi,FILE *fo,int sortjun){
   char  s[256]; 
   
  /* ファイルリード*/
  while(fgets(s,256,fi)!=NULL){
     //filchk(s);//一件追加
     printf("%d,",filchk(s));
  }
  /*ソート処理*/ 
  //bubble_sort(dt,x,sortjun);
  
  /* ファイル出力処理 */
  memberfprnt(fo);
}
 

/* 終了処理用関数 */
void end(FILE *fi, FILE *fo){
    
  struct meibo *dt=top,*prev;
  
  /* ファイルクローズ */
  fclose(fi);
  fclose(fo);
  
  //メモリ開放
  while(dt != NULL){
    prev = dt;
    dt = dt->next;
    free(prev);
  }
}

void file_open(FILE **fi, FILE **fo){
    /* 入力ファイルOPEN */
  if((*fi=fopen("SV.ADR","r")) == NULL){
      printf("入力ファイルが存在しないか、オープンできない\n");
      return;
  }
  /* 出力ファイルOPEN */
  if((*fo=fopen("ADR.SV","w")) == NULL){
      printf("出力ファイルがオープンできない\n");
      return;
  }
}

/* ソートパターン選択用関数 */
int sortptnsel(char *str){
   
  int sortptn;
  int  e;
  
  e=-1;

  if (strcmp(str,"1") == 0) {
     sortptn = 1;
  }
  else if (strcmp(str,"2") == 0){
     sortptn = 2;
  }
  else {
     printf("引数の値が違います\n");
     return e;
  }

   return sortptn;
}

/* 入力ファイルチェック用関数 */
int filchk( char s[256]){
    
    struct meibo *wkdata;
    /* 記憶領域の確保 */
    if ((wkdata = (struct meibo *)malloc(sizeof(struct meibo)))==NULL){
        printf("メモリ確保できません\n");
        exit(1);
    }
    //データ格納
    if(sscanf(s," %[^,],%c,%d",wkdata->name,&wkdata->danjo,&wkdata->postNo) != 3){
        free(wkdata);
        return 0;
    }
    
    //リストに追加
    wkdata->next = top;
    top = wkdata;
    
    return 1;
}

/* ソート用関数 */
void bubble_sort(struct meibo *dt,int NUM,int cmdline){
  int i,x;
  struct meibo temp;

    //〜長いので処理省略〜
}

/* ファイル出力用関数 */
void memberfprnt(FILE *fo){

  struct meibo *dt=top;

  /* ファイル印字 */
  for(;dt != NULL;dt = dt->next){
      fprintf(fo,"%-10d%-20s%-20c\n",dt->postNo,dt->name,dt->danjo);
  }
}





No.15103

Re:自己参照構造体
投稿者---REE(2004/07/01 10:36:22)


>わからないところは
>自己参照構造体にした場合、これだけ添字を使ってるロジック
>を大幅に書き換えなくてはならないのかという点

はい、そうです。
データの構造を変えるということは、それに関わる部分を全部変えるということです。

>記憶領域の確保 をするためのロジック(mallocのところ)を
>どこに入れればよいのか。

新しい要素をリストに追加するところです。



No.15104

Re:自己参照構造体
投稿者---猛蹴士(2004/07/01 11:35:48)


>はい、そうです。
>データの構造を変えるということは、それに関わる部分を全部変えるということです。

>>どこに入れればよいのか。
>
>新しい要素をリストに追加するところです。

いろいろありがとうございます。
と、いうことで、ある程度直してみたのですが、まだ不完全な状態
ですが、感じとしてはこんな感じでいいのでしょうか?

sscanfもグローバル変数も使ってはいけないという状況でやってるので、
これからが大変なんですけど・・・

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define TRUE 1
#define FALSE 0

struct meibo {
    char  name[21];
    char  danjo;
    int   postNo;
    struct meibo *next;
};

/***********************
  関数化プロトタイプ↓ *
************************/
/* 初期処理用関数プロトタイプ */
int init(int kosu,char *str,FILE **fi, FILE **fo);

/* 主処理用関数プロトタイプ */
void shu_shori(FILE *fi,FILE *fo,struct meibo *dt,int sortjun); 

/* 終了処理用関数プロトタイプ */
void end(FILE *fi,FILE *fo);

/* ファイルオープン用関数プロトタイプ */
int file_open(FILE **fi, FILE **fo);

/* ソートパターン選択用関数プロトタイプ */
int sortptnsel(char *str);

/* 入力ファイルチェック用関数プロトタイプ */
int filchk( char s[256],int line,struct meibo *dt);

/* ソート用関数プロトタイプ */
void bubble_sort(struct meibo *dt,int NUM,int cmdline);

/* ファイル出力用関数プロトタイプ */
void memberfprnt(struct meibo *dt,int NUM,FILE *fo);

/***********************
  メイン処理   ↓      *
************************/
main(int argc, char *argv[])
{
  struct meibo member;

/*
  struct meibo *head = &member;
  struct meibo *wkdata;
  struct meibo *wp;
  head = &member;
  member->next = NULL;*/

  FILE *fin,*fout;
  int  sortptn; 

  /* 初期処理 */
  sortptn = init(argc,argv[1],&fin, &fout);

  /* エラーなら処理終了 */
  if (sortptn!=1&&sortptn!=2 ){
      return 1;
  }

  /* 主処理 */
  shu_shori(fin,fout,member,sortptn);


  /* 終了処理 */
  end(fin,fout);

  return 0;
}
   〜次に続く〜




No.15105

Re:自己参照構造体
投稿者---猛蹴士(2004/07/01 11:37:41)


  〜一つ前からの続き〜

/***********************
  関数化処理        ↓ *
************************/
/* 初期処理用関数 */
int init(int kosu,char *str,FILE **fi, FILE **fo){
  int open_status,sortptn,e;
  
  e=-1;

  /* 引数の個数確認 */
  if (kosu != 2){
     printf("引数の個数が違います\n");
     return e;
  }

  /* ソートパターン選択 */
  sortptn = sortptnsel(str);

  if (sortptn!=1&&sortptn!=2 ){
     printf("引数の値が違います\n");
     return e;
  }
   
  /*ファイルオープン処理*/
  open_status = file_open(fi, fo);

  if (open_status!=0){
     return e;
  }

  return sortptn;
}

/* 主処理用関数 */
void shu_shori(FILE *fi,FILE *fo,struct meibo *dt,int sortjun){
   char  s[256]; 
   int   x=0,erlchk;
   
  /* ファイルリード*/
  while(fgets(s,256,fi)!=NULL){

     /* 入力ファイルチェック */
     erlchk = filchk( s,x,dt);

     /* エラー行でない場合 */
     if (erlchk == FALSE){
        /* 行数カウントアップ */
        x++;
     }
  }

  /*ソート処理*/ 
  bubble_sort(dt,x,sortjun);

  /* ファイル出力処理 */
  memberfprnt(dt,x,fo);
}
 
/* 終了処理用関数 */
void end(FILE *fi, FILE *fo){
  /* ファイルクローズ */
  fclose(fi);
  fclose(fo);
}

/* ファイルオープン処理 */
int file_open(FILE **fi, FILE **fo){
  int a=0,e=-1;
    /* 入力ファイルOPEN */
  if((*fi=fopen("SV.ADR","r")) == NULL){
      printf("入力ファイルが存在しないか、オープンできない\n");
      return e;
  }
  /* 出力ファイルOPEN */
  if((*fo=fopen("ADR.SV","w")) == NULL){
      printf("出力ファイルがオープンできない\n");
      return e;
  }
  return a;
}

/* ソートパターン選択用関数 */
int sortptnsel(char *str){
   
  int sortptn;
  int  e;
  
  e=-1;

  if (strcmp(str,"1") == 0) {
     sortptn = 1;
  }
  else if (strcmp(str,"2") == 0){
     sortptn = 2;
  }
  else {
     return e;
  }
   return sortptn;
}
/* 入力ファイルチェック用関数 */
int filchk( char s[256],int line,struct meibo *dt){

    int Cnt, erlflg,x,i;     
    x= line;
    i= 0;
    erlflg = FALSE;
    struct meibo *wkdata;

    /* 記憶領域の確保 */
    if ((wkdata = (dt *)malloc(sizeof(dt)))==NULL){
        printf("malloc error\n");
        return 1;
    }

    /* 名前の文字列を取得*/
     while(s[i]!=' ' && s[i]!='\t'&& s[i]!='\n'&&i<20){
           wkdata->name[i] = s[i];
           i++;
     }
     /* 終端コード*/
     wkdata->name[i] = '\0';

       /* 名前が入っていない場合 */
       if (strlen(wkdata->name)==0){
           /* エラー行と見なす*/
           erlflg = TRUE;
       }

     /* スペース、タブ、改行の場合、文字数カウントアップ*/
     while(s[i]==' '||s[i]=='\t'||s[i]=='\n'){
           i++;                            
     }
     /* 男女別を取得*/ 
     Cnt = 0;
     while(s[i]!=' '&&s[i]!='\t'&&s[i]!='\n'){
           /* 男女別取得時にM,F以外の文字を取得した場合*/
           if (s[i]!='M'&& s[i]!='F'){
               /* エラー行と見なす*/ 
               erlflg = TRUE;
           }
           else {
               wkdata->danjo = s[i];
           }
           i++;
           Cnt++;
     }
        /* 男女別を1文字以上を取得した場合 */
        if (Cnt > 1){
            /* エラー行と見なす*/
            erlflg = TRUE;
        }

     /* スペース、タブ、改行の場合、文字数カウントアップ*/
     while(s[i]==' '||s[i]=='\t'||s[i]=='\n'){
           i++;
     }

     /* 郵便番号を取得*/    
     wkdata->postNo = 0;
     Cnt=0;
     while(s[i]!=' '&&s[i]!='\t'&&s[i]!='\n'&& s[i]!='\0'){

           /* 郵便番号に数字以外のものが含まれていた場合の考慮 */
           if (isdigit(s[i])) {
                wkdata->postNo = wkdata->postNo * 10 + s[i] - '0'; 
           }
           else {
                erlflg = TRUE;
           }
           i++;
           Cnt++;
     }
     /* 郵便番号が取得できない場合*/
     if ( wkdata->postNo==0){
          /*エラー行と見なす*/
          erlflg = TRUE;
     }
     /* 郵便番号を3文字以上取得した場合*/ 
     if ( Cnt > 3 ){
          /* エラー行と見なす*/
            erlflg = TRUE;
     }

     return  erlflg;
}
/* ソート用関数 */
void bubble_sort(struct meibo *dt,int NUM,int cmdline){
  int i,x;
  struct meibo temp;

  /* 引数によって、昇順、降順ソートを判断する*/ 
  if (cmdline == 1) {
       /* 郵便番号昇順ソート*/
       for (i=0; i<NUM; i++){
            for(x=NUM-1; x>i ; x--){
              /* 前の要素の方が大きい場合 */
              if ( dt[x-1].postNo > dt[x].postNo){
                  /* 順番を入れ替える*/
                  temp = dt[x];
                  dt[x] = dt[x-1];
                  dt[x-1] = temp;
              }          
            }     
       }
   }
   else if(cmdline == 2){
           /* 郵便番号降順ソート */
           for (i=0; i<NUM; i++){
                for(x=NUM-1; x>i ; x--){
                    /* 前の要素の方が小さい場合 */
                    if ( dt[x-1].postNo < dt[x].postNo){
                        /* 順番を入れ替える*/
                        temp = dt[x];
                        dt[x] = dt[x-1];
                        dt[x-1] = temp;
                    }
                }
            }
   }
}

/* ファイル出力用関数 */
void memberfprnt(struct meibo *dt,int NUM,FILE *fo){

  int i;

  /* ファイル印字 */
  for(i=0;i<NUM;i++){
      fprintf(fo,"%-10d%-20s%-20c\n",dt[i].postNo,dt[i].name,dt[i].danjo);
  }
}




No.15110

Re:自己参照構造体
投稿者---REE(2004/07/01 13:44:56)


  /* 記憶領域の確保 */
    if ((wkdata = (dt *)malloc(sizeof(dt)))==NULL){
        printf("malloc error\n");
        return 1;
    }

ポインタ入れる領域を確保するわけではないので、ここは、以下の様になりますね。

if ((wkdata = (struct meibo *)malloc(sizeof(struct meibo)))==NULL){

ところで、この確保した領域が、そのまま放置されています。
ちゃんとリスト構造になるように繋げて下さい。
その時に、順番になるように繋げると、あとでソートしなおす必要がなくなりますよ。



No.15112

Re:自己参照構造体
投稿者---猛蹴士(2004/07/01 14:25:29)


>ポインタ入れる領域を確保するわけではないので、ここは、以下の様になりますね。
>
> if ((wkdata = (struct meibo *)malloc(sizeof(struct meibo)))==NULL){
>
>ところで、この確保した領域が、そのまま放置されています。
>ちゃんとリスト構造になるように繋げて下さい。
>その時に、順番になるように繋げると、あとでソートしなおす必要がなくなりますよ。


ありがとうございます。いわれたように直してみたのですが、
struct meibo *wkdata; の宣言がおかしいといわれてしまいます。
おかしいようには思えないんですが・・・
どこか別のロジックの所の影響でしょうか・・?


/* 入力ファイルチェック用関数 */
int filchk( char s[256],int line,struct meibo *dt){
/*int filchk( char s[256]){*/

    int Cnt, erlflg,x,i;     
    x= line;
    i= 0;
    erlflg = FALSE;
    struct meibo *wkdata;

    /* 記憶領域の確保 */
    if ((wkdata = (struct meibo *)malloc(sizeof(struct meibo)))==NULL){
        printf("malloc error\n");
        return 1;
    }

    /* 記憶領域の確保 */
    /*if ((wkdata = (struct meibo *)malloc(sizeof(struct meibo)))==NULL){
        printf("メモリ確保できません\n");
        exit(1);
    }*/


    /* 名前の文字列を取得*/
     while(s[i]!=' ' && s[i]!='\t'&& s[i]!='\n'&&i<20){
           wkdata->name[i] = s[i];
           i++;
     }
     /* 終端コード*/
     wkdata->name[i] = '\0';

       /* 名前が入っていない場合 */
       if (strlen(wkdata->name)==0){
           /* エラー行と見なす*/
           erlflg = TRUE;
       }

     /* スペース、タブ、改行の場合、文字数カウントアップ*/
     while(s[i]==' '||s[i]=='\t'||s[i]=='\n'){
           i++;                            
     }
     /* 男女別を取得*/ 
     Cnt = 0;
     while(s[i]!=' '&&s[i]!='\t'&&s[i]!='\n'){
           /* 男女別取得時にM,F以外の文字を取得した場合*/
           if (s[i]!='M'&& s[i]!='F'){
               /* エラー行と見なす*/ 
               erlflg = TRUE;
           }
           else {
               wkdata->danjo = s[i];
           }
           i++;
           Cnt++;
     }
        /* 男女別を1文字以上を取得した場合 */
        if (Cnt > 1){
            /* エラー行と見なす*/
            erlflg = TRUE;
        }

     /* スペース、タブ、改行の場合、文字数カウントアップ*/
     while(s[i]==' '||s[i]=='\t'||s[i]=='\n'){
           i++;
     }

     /* 郵便番号を取得*/    
     wkdata->postNo = 0;
     Cnt=0;
     while(s[i]!=' '&&s[i]!='\t'&&s[i]!='\n'&& s[i]!='\0'){

           /* 郵便番号に数字以外のものが含まれていた場合の考慮 */
           if (isdigit(s[i])) {
                wkdata->postNo = wkdata->postNo * 10 + s[i] - '0'; 
           }
           else {
                erlflg = TRUE;
           }
           i++;
           Cnt++;
     }
     /* 郵便番号が取得できない場合*/
     if ( wkdata->postNo==0){
          /*エラー行と見なす*/
          erlflg = TRUE;
     }
     /* 郵便番号を3文字以上取得した場合*/ 
     if ( Cnt > 3 ){
          /* エラー行と見なす*/
            erlflg = TRUE;
     }

     return  erlflg;
}





No.15113

Re:自己参照構造体
投稿者---REE(2004/07/01 15:02:41)


>struct meibo *wkdata; の宣言がおかしいといわれてしまいます。
>おかしいようには思えないんですが・・・
>どこか別のロジックの所の影響でしょうか・・?

C言語では、変数宣言・定義はブロックの始めにまとまってなければいけません。
x= line;
の前の行に移動してください。



No.15114

Re:自己参照構造体
投稿者---猛蹴士(2004/07/01 15:26:30)


> x= line;の前の行に移動してください。

上手くいきました。すいませんでした。

ただ肝心なリード処理、ソート(チェインの繋ぎ換えになるのかな?)、
ファイル出力に関しては未だ解決策が見出せずにいます・・・



No.15119

Re:自己参照構造体
投稿者---あかま(2004/07/01 17:18:33)


なぜか
/* 記憶領域の確保 */
が二つ?一ついらない。

>ただ肝心なリード処理、ソート(チェインの繋ぎ換えになるのかな?)、
>ファイル出力に関しては未だ解決策が見出せずにいます・・・
リードはもうできているのでは?

「ソートは1件読み込む度にやってしまえ」とこのスレの中で"3回"ほど書かれてますよ。
かずまさんのプログラムが参考になるでしょう。
sscanfを使わないという理由だけで読まないのはもったいないことです。
sscanfの部分を自分のリード方式に置き換えるだけなのですから。

ファイル出力もかずまさんの書かれたプログラムをほぼそのままで使えるでしょう。
引数のNameListをstruct meibo に変えるだけです。

で、今なにが必要かと言えば折角確保したメモリをリストに繋げていないことです(これもすでに指摘されている)。
ソートが分からないならまずは"リストに繋げるだけ"を書いてみてください。


No.15120

Re:自己参照構造体
投稿者---猛蹴士(2004/07/01 17:33:01)


>ソートが分からないならまずは"リストに繋げるだけ"を書いてみてください。

いろいろすいません。いろいろな人の教えを参考にして、とりあえず、"リストに繋げるだけ"は出来ました。
ですが、今はグローバル変数をつかっていますが、それを使わないようにしたい
のと、後はソートです。REEさんから「リスト構造に順番になるように繋げると、ソートしなおす必要がなくなる」という助言を頂いたので、それをやろうとおもうのですが。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define TRUE 1
#define FALSE 0

struct meibo {
    char  name[21];
    char  danjo;
    int   postNo;
    struct meibo *next;
};

/***********************
  関数化プロトタイプ↓ *
************************/
/* 初期処理用関数プロトタイプ */
int init(int kosu,char *str,FILE **fi, FILE **fo);

/* 主処理用関数プロトタイプ */
int shu_shori(FILE *fi,FILE *fo,int sortjun);

/* 終了処理用関数プロトタイプ */
void end(FILE *fi,FILE *fo);

/* ファイルオープン用関数プロトタイプ */
int file_open(FILE **fi, FILE **fo);

/* ソートパターン選択用関数プロトタイプ */
int sortptnsel(char *str);

/* 入力ファイルチェック用関数プロトタイプ */
int filchk( char s[256]);

/* ソート用関数プロトタイプ */
void bubble_sort(struct meibo *dt,int NUM,int cmdline);

/* ファイル出力用関数プロトタイプ */
void memberfprnt(FILE *fo);

/***********************
  グローバル変数(仮) *
************************/
struct meibo *top;

/***********************
  メイン処理   ↓      *
************************/
main(int argc, char *argv[])
{

  FILE *fin,*fout;
  int  sortptn, err_status; 

  /* 初期処理 */
  sortptn = init(argc,argv[1],&fin, &fout);

  /* エラーなら処理終了 */
  if (sortptn!=1&&sortptn!=2 ){
      return 1;
  }

  /* 主処理 */
  err_status=shu_shori(fin,fout,sortptn);

  /* エラーなら処理終了 */
  if (err_status!=0){
      return 1;
  }

  /* 終了処理 */
  end(fin,fout);

  return 0;
}
  〜次に続く〜






No.15121

Re:自己参照構造体
投稿者---猛蹴士(2004/07/01 17:34:31)


 〜前からの続き〜

/***********************
  関数化処理        ↓ *
************************/
/* 初期処理用関数 */
int init(int kosu,char *str,FILE **fi, FILE **fo){
  int open_status,sortptn,e;
  
  e=-1;

  /* 引数の個数確認 */
  if (kosu != 2){
     printf("引数の個数が違います\n");
     return e;
  }

  /* ソートパターン選択 */
  sortptn = sortptnsel(str);

  if (sortptn!=1&&sortptn!=2 ){
     printf("引数の値が違います\n");
     return e;
  }
   
  /*ファイルオープン処理*/
  open_status = file_open(fi, fo);

  if (open_status!=0){
     return e;
  }

  return sortptn;
}

/* 主処理用関数 */
int shu_shori(FILE *fi,FILE *fo,int sortjun){

   char  s[256]; 
   int   x=0,erlchk,e=-1,a=0;
   
  /* ファイルリード*/
  while(fgets(s,256,fi)!=NULL){

     /* 入力ファイルチェック */
     erlchk = filchk(s);

     /* エラーの場合 */
     if (erlchk == -1){
         return e;
     }
  }

  /*ソート処理*/ 
  /*bubble_sort(dt,x,sortjun);*/

  /* ファイル出力処理 */
  memberfprnt(fo);

  return a;
}
 
/* 終了処理用関数 */
void end(FILE *fi, FILE *fo){

  struct meibo *dt=top,*prev;

  /* ファイルクローズ */
  fclose(fi);
  fclose(fo);

  while(dt != NULL){
    prev = dt;
    dt = dt->next;
    free(prev);
  }
}

/* ファイルオープン処理 */
int file_open(FILE **fi, FILE **fo){
  int a=0,e=-1;
    /* 入力ファイルOPEN */
  if((*fi=fopen("SV.ADR","r")) == NULL){
      printf("入力ファイルが存在しないか、オープンできない\n");
      return e;
  }
  /* 出力ファイルOPEN */
  if((*fo=fopen("ADR.SV","w")) == NULL){
      printf("出力ファイルがオープンできない\n");
      return e;
  }
  return a;
}

/* ソートパターン選択用関数 */
int sortptnsel(char *str){
   
  int sortptn;
  int  e;
  
  e=-1;

  if (strcmp(str,"1") == 0) {
     sortptn = 1;
  }
  else if (strcmp(str,"2") == 0){
     sortptn = 2;
  }
  else {
     return e;
  }
   return sortptn;
}
/* 入力ファイルチェック用関数 */
int filchk( char s[256]){

    struct meibo *wkdata;
    int Cnt, erlflg,i,e=-1,a=0;
     
    i= 0;
    erlflg = FALSE;

    /* 記憶領域の確保 */
    if ((wkdata = (struct meibo *)malloc(sizeof(struct meibo)))==NULL){
        printf("メモリ確保できません\n");
        return e;
    }

    /* 名前の文字列を取得*/
     while(s[i]!=' ' && s[i]!='\t'&& s[i]!='\n'&&i<20){
           wkdata->name[i] = s[i];
           i++;
     }
     /* 終端コード*/
     wkdata->name[i] = '\0';

       /* 名前が入っていない場合 */
       if (strlen(wkdata->name)==0){
           /* エラー行と見なす*/
           erlflg = TRUE;
       }

     /* スペース、タブ、改行の場合、文字数カウントアップ*/
     while(s[i]==' '||s[i]=='\t'||s[i]=='\n'){
           i++;                            
     }
     /* 男女別を取得*/ 
     Cnt = 0;
     while(s[i]!=' '&&s[i]!='\t'&&s[i]!='\n'){
           /* 男女別取得時にM,F以外の文字を取得した場合*/
           if (s[i]!='M'&& s[i]!='F'){
               /* エラー行と見なす*/ 
               erlflg = TRUE;
           }
           else {
               wkdata->danjo = s[i];
           }
           i++;
           Cnt++;
     }
        /* 男女別を1文字以上を取得した場合 */
        if (Cnt > 1){
            /* エラー行と見なす*/
            erlflg = TRUE;
        }

     /* スペース、タブ、改行の場合、文字数カウントアップ*/
     while(s[i]==' '||s[i]=='\t'||s[i]=='\n'){
           i++;
     }

     /* 郵便番号を取得*/    
     wkdata->postNo = 0;
     Cnt=0;
     while(s[i]!=' '&&s[i]!='\t'&&s[i]!='\n'&& s[i]!='\0'){

           /* 郵便番号に数字以外のものが含まれていた場合の考慮 */
           if (isdigit(s[i])) {
                wkdata->postNo = wkdata->postNo * 10 + s[i] - '0'; 
           }
           else {
                erlflg = TRUE;
           }
           i++;
           Cnt++;
     }
     /* 郵便番号が取得できない場合*/
     if ( wkdata->postNo==0){
          /*エラー行と見なす*/
          erlflg = TRUE;
     }
     /* 郵便番号を3文字以上取得した場合*/ 
     if ( Cnt > 3 ){
          /* エラー行と見なす*/
            erlflg = TRUE;
     }

     /* エラー行ではない場合 */
     if ( erlflg != TRUE){
        /*リストに追加*/
        wkdata->next = top;
        top = wkdata;
     }

     /*return  erlflg;*/
     return  a;
}
/* ソート用関数 
void bubble_sort(struct meibo *dt,int NUM,int cmdline){
  int i,x;
  struct meibo temp;

   引数によって、昇順、降順ソートを判断する
  if (cmdline == 1) {
        郵便番号昇順ソート
       for (i=0; i<NUM; i++){
            for(x=NUM-1; x>i ; x--){
               前の要素の方が大きい場合 
              if ( dt[x-1].postNo > dt[x].postNo){
                   順番を入れ替える
                  temp = dt[x];
                  dt[x] = dt[x-1];
                  dt[x-1] = temp;
              }          
            }     
       }
   }
   else if(cmdline == 2){
            郵便番号降順ソート 
           for (i=0; i<NUM; i++){
                for(x=NUM-1; x>i ; x--){
                     前の要素の方が小さい場合 
                    if ( dt[x-1].postNo < dt[x].postNo){
                         順番を入れ替える
                        temp = dt[x];
                        dt[x] = dt[x-1];
                        dt[x-1] = temp;
                    }
                }
            }
   }
}*/

/* ファイル出力用関数 */
void memberfprnt(FILE *fo){
  struct meibo *dt = top;

  for(;dt !=NULL; dt=dt->next){
      fprintf(fo,"%-10d%-20s%-20c\n",dt->postNo,dt->name,dt->danjo);
  }
}




No.15122

Re:自己参照構造体
投稿者---あかま(2004/07/01 18:32:23)


>ですが、今はグローバル変数をつかっていますが、それを使わないようにしたい
グローバル変数を使わないようにするのは、かずまさんのプログラム方式が綺麗だと思います。
関数内でリストを全部完成させてしまって、リストの先頭ポインタを返します。

>のと、後はソートです。REEさんから「リスト構造に順番になるように繋げると、ソートしなおす必要がなくなる」という助言
繋げる要素をリストの先頭と比較して、順番がもっと後なら次の要素と比較してってのを繰り返して、挿入する位置を決めます。
そうするとリスト完成時にはソートもされているという方法です。

かずまさんのプログラムのread_data()で全て行われているので読んでみてください。

NameList *read_data(FILE *fp, int sort_pattern)
{
    char buf[256], name[21], sex[2], c;  int zip;
    NameList head = { 0 }, *p, *np;

    while (fgets(buf, sizeof buf, fp)) {//ファイルが終わるまで
        if (sscanf(buf, "%20s %1[MF] %d %c", name, sex, &zip, &c) != 3//データの読み込み
            || zip > 999) continue;//不正データなら無視

        if (sort_pattern == 1) //降順か昇順かで
            for (p = &head; p->next && p->next->zip < zip; p = p->next) ;//挿入する位置決め
        else
            for (p = &head; p->next && p->next->zip > zip; p = p->next) ;//挿入する位置決め
                        
        if (!(np = malloc(sizeof(NameList))) || !(np->name = strdup(name)))//メモリの確保。確保したメモリに名前を格納
            puts("out of memory"), exit(1);//エラーなら
        np->sex = sex[0];  np->zip = zip;//読み込んだ残りのデータの格納
        np->next = p->next;  p->next = np;//リストに挿入

    }
    return head.next;//リストの先頭ポインタを返す

}

どこか分からないところはありますか?



No.15134

Re:自己参照構造体
投稿者---猛蹴士(2004/07/02 01:32:07)


>どこか分からないところはありますか?

いろいろありがとうございます。なんとかこのロジックを自分のソースに
落とし込めるように努力してみますが、出来れば、現在のロジックをあまり変えることなく処理を組み込みたいのです。




No.15141

Re:自己参照構造体
投稿者---REE(2004/07/02 10:27:47)


>いろいろありがとうございます。なんとかこのロジックを自分のソースに
>落とし込めるように努力してみますが、出来れば、現在のロジックをあまり変えることなく処理を組み込みたいのです。

それならば、現在のロジックをあまり変えないように、このロジックを落とし込めばいいだけでは?

このロジックをちゃんと理解すれば、問題なく出来るはずです。


No.15142

いまだ解決せず・・・
投稿者---猛蹴士(2004/07/02 10:36:32)


昨日の夜中も考えて、今朝からも考えているのですが、いまだに
うまくいきません。

かずまさんのロジックを参考にしたらよいという意見を頂き、なんとか
落とし込めないかとやってみましたが、どうにも上手くいきません。

できるだけ既存のロジックを変えたくないので、
この関数のロジック内でソートをかけたいのと(ソートの為の引数が増える
のは構いません)、
今使っているグローバル関数「top」を使わず、
関数間でデータを引き継ぎ、ファイル出力までやる上手い方法はないですかね・・・


/* 入力ファイルチェック用関数 */
int filchk( char s[256]){

    struct meibo *wkdata;
    int Cnt, erlflg,i,e=-1,a=0;
     
    i= 0;
    erlflg = FALSE;

    /* 記憶領域の確保 */
    if ((wkdata = (struct meibo *)malloc(sizeof(struct meibo)))==NULL){
        printf("メモリ確保できません\n");
        return e;
    }

    /* 名前の文字列を取得*/
     while(s[i]!=' ' && s[i]!='\t'&& s[i]!='\n'&&i<20){
           wkdata->name[i] = s[i];
           i++;
     }
     /* 終端コード*/
     wkdata->name[i] = '\0';

       /* 名前が入っていない場合 */
       if (strlen(wkdata->name)==0){
           /* エラー行と見なす*/
           erlflg = TRUE;
       }

     /* スペース、タブ、改行の場合、文字数カウントアップ*/
     while(s[i]==' '||s[i]=='\t'||s[i]=='\n'){
           i++;                            
     }
     /* 男女別を取得*/ 
     Cnt = 0;
     while(s[i]!=' '&&s[i]!='\t'&&s[i]!='\n'){
           /* 男女別取得時にM,F以外の文字を取得した場合*/
           if (s[i]!='M'&& s[i]!='F'){
               /* エラー行と見なす*/ 
               erlflg = TRUE;
           }
           else {
               wkdata->danjo = s[i];
           }
           i++;
           Cnt++;
     }
        /* 男女別を1文字以上を取得した場合 */
        if (Cnt > 1){
            /* エラー行と見なす*/
            erlflg = TRUE;
        }

     /* スペース、タブ、改行の場合、文字数カウントアップ*/
     while(s[i]==' '||s[i]=='\t'||s[i]=='\n'){
           i++;
     }

     /* 郵便番号を取得*/    
     wkdata->postNo = 0;
     Cnt=0;
     while(s[i]!=' '&&s[i]!='\t'&&s[i]!='\n'&& s[i]!='\0'){

           /* 郵便番号に数字以外のものが含まれていた場合の考慮 */
           if (isdigit(s[i])) {
                wkdata->postNo = wkdata->postNo * 10 + s[i] - '0'; 
           }
           else {
                erlflg = TRUE;
           }
           i++;
           Cnt++;
     }
     /* 郵便番号が取得できない場合*/
     if ( wkdata->postNo==0){
          /*エラー行と見なす*/
          erlflg = TRUE;
     }
     /* 郵便番号を3文字以上取得した場合*/ 
     if ( Cnt > 3 ){
          /* エラー行と見なす*/
            erlflg = TRUE;
     }

     /* エラー行ではない場合 */
     if ( erlflg != TRUE){
        /*リストに追加*/
        wkdata->next = top;
        top = wkdata;
     }

     /*return  erlflg;*/
     return  a;
}




No.15145

Re:いまだ解決せず・・・
投稿者---猛蹴士(2004/07/02 10:51:06)


あまり関係ないですが、sscanf strdupは使えない状況です。

またかずまさんのロジックでやっている、
for (p = &head; p->next && p->next->zip < zip; p = p->next) ;//挿入する位置決め

はfor文としては値を終わりがくるまでどんどんセットし続けるということ
をやっているだけですか?

標準書式の
    for(式1;式2;式3;){
           文
    }        

     という形でないので、質問させてもらいました。


No.15146

Re:いまだ解決せず・・・
投稿者---ニタチ(2004/07/02 11:23:33)


>はfor文としては値を終わりがくるまでどんどんセットし続けるということ
>をやっているだけですか?

 う〜ん‥‥多分言いたいことはあってるかもしれませんが、
 任意の位置までリストをたどる処理をしています。

>for (p = &head; p->next && p->next->zip < zip; p = p->next) ;

 ↑は、
 for (p = &head; p->next && p->next->zip < zip; p = p->next){
 }
 としてブロック内の処理を書いてないだけと捉えればいいと思います。



No.15148

Re:いまだ解決せず・・・
投稿者---NykR(2004/07/02 11:40:53)


標準書式の
    for(式1;式2;式3;){
           文
    }        
     という形でないので、質問させてもらいました。

その書き方ではシンタックスエラーです。

forの構文は

for ( 式 ; 式 ; 式 ) 文
for ( 宣言 式 ; 式 ) 文 (JISX3010:2003)

のいずれかです。




No.15149

Re:いまだ解決せず・・・
投稿者---猛蹴士(2004/07/02 11:47:36)


for文はよくわかりました。{}をつけてしまったのは、こちらの確認ミス
でした。ありがとうございました。

それはともかく、自己参照構造体のほうが・・・


No.15151

Re:いまだ解決せず・・・
投稿者---あかま(2004/07/02 12:40:21)


>それはともかく、自己参照構造体のほうが・・・
あの、前々から感じてたんですけども。
自分で理解する気はありますか?
わからないとゴネてゴネて誰かが答え書いてくれるまで待ってますよね?

きちんとレスはつけていただいてるのでやる気があるのはわかるのですが、
提示されたプログラムの一部をコピペして動いたからこれでいいやって感じがします。

いまさらですがリスト構造を理解していますか?
リストへの追加時についでにソートするという方法を理解していますか?
理解していないならまずそこからです。
よーく考えて見てください。絵を描くのも有効です。

理解したらソースに手を加えてください。
>落とし込めないかとやってみましたが、どうにも上手くいきません。
だけでは、何がうまくいかないのか、どう間違っているのかがわかりません。
うまくいかないソースを載せてください。
そうすれば、それを直すためのヒントなり答えなりを書いてもらえるでしょう。


No.15153

Re:いまだ解決せず・・・
投稿者---nop(2004/07/02 12:54:07)


>for文はよくわかりました。{}をつけてしまったのは、こちらの確認ミス
>でした。

{}の問題ではないでしょう。
「文」には複文も含まれる訳ですから。

# ご自分の投稿内容もよく確認しましょう。
# 式3に「;」はいらんでしょ?


No.15152

Re:いまだ解決せず・・・
投稿者---ニタチ(2004/07/02 12:48:13)


>今使っているグローバル関数「top」を使わず、
>関数間でデータを引き継ぎ、ファイル出力までやる上手い方法はないですかね・・・

 グローバル変数ですよね?
 関数間のファイルポインタの引継ぎで理解したなら、これは簡単ですよ?
 topを受け取るために関数の引数を一つ増やせばいいだけです。


No.15094

Re:自己参照構造体
投稿者---ぽこ(2004/06/30 22:38:00)


>関数にまとめたやつは長いので、わかりづらいかなと思いまして
>あえてまとめてないほうにしました。

これはむしろ逆でしょうね。^^;
疑問点&問題点が分かっているとき、
機能別に関数として分けられているソースの方が
注目すべき関数がはっきりとし、問題点を見つけ易いです。

#あくまで私見ですが。。


No.15101

Re:自己参照構造体
投稿者---かずま(2004/07/01 03:58:42)


> もしこのロジックを自己参照構造体で書き直すとしたら、現在使っている
> 添え字とかは使えなくなって、大幅な改良が必要でしょうか?

リストのソートはちょっと厄介なので、入力時にやってしまうといいでしょう。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct NameList {
    char *name;  char sex;  int zip;
    struct NameList *next;
} NameList;

NameList *read_data(FILE *fp, int sort_pattern)
{
    char buf[256], name[21], sex[2], c;  int zip;
    NameList head = { 0 }, *p, *np;

    while (fgets(buf, sizeof buf, fp)) {
        if (sscanf(buf, "%20s %1[MF] %d %c", name, sex, &zip, &c) != 3
            || zip > 999) continue;
        if (sort_pattern == 1) 
            for (p = &head; p->next && p->next->zip < zip; p = p->next) ;
        else
            for (p = &head; p->next && p->next->zip > zip; p = p->next) ;
        if (!(np = malloc(sizeof(NameList))) || !(np->name = strdup(name)))
            puts("out of memory"), exit(1);
        np->sex = sex[0];  np->zip = zip;
        np->next = p->next;  p->next = np;
    }
    return head.next;
}

void print_data(FILE *fp, NameList *p)
{
    for (; p; p = p->next)
        fprintf(fp, "%-10d%-20s%-20c\n", p->zip, p->name, p->sex);
}

int main(int argc, char *argv[])
{
    FILE *fin, *fout;  int sort_pattern;  NameList *head;

    if (argc != 2 ||
            (sort_pattern = atoi(argv[1])) != 1 && sort_pattern != 2)
        puts("wrong argument"), exit(1);

    fin = fopen("SV.ADR", "r");
    if (fin == NULL) puts("can't open SV.ADR"), exit(1);

    fout = fopen("ADR.SV", "w");
    if (fout == NULL) puts("can't create ADR.SV"), exit(1);

    head = read_data(fin, sort_pattern);
    print_data(fout, head);

    fclose(fin);
    fclose(fout);
    return 0;
}