ぼんさい塾

ぼんさいノートと補遺に関する素材や注釈です.ミスが多いので初稿から1週間を経た重要な修正のみ最終更新日を残しています.

Cの文法 (16)

2010-10-03 22:57:26 | 暮らし
「まず覚えるCの文法」校正中)

Ex5-1: 解答例
//-------------------------------------
member *addr(int i){
  member *p=&igo; int k;
  for(k=0; k<10; k++){
    if(p[k].id==i || p[k].id==0){break;}
  }
  if(k<10){return p+k;}
  else{return NULL;}
}
void show(int i){
  member *p=addr(i);
  if(p->id==i){
    printf("%d, %s, %s\n", 
           p->id, p->name, p->mail);
  }else{printf("?\n");}
}
void add(int i, char *n, char *m){
  member *p=addr(i);
  if(p!=NULL && p->id==0){
    p->id=i;
    strcpy(p->name, n);
    strcpy(p->mail, m);
  }else{printf("-\n");}
}
void del(int i){
  member *p=addr(i), *q;
  if(p!=NULL && p->id==i){
    q=addr(0); q--;
    if(q!=p && q->id!=0){
      p->id=q->id;
      strcpy(p->name, q->name);
      strcpy(p->mail, q->mail);
    }else{q=p;}
    q->id=0;
    q->name[0]=q->mail[0]='\0';
  }else{printf("?\n");}
}
//-------------------------------------

Ex5-2: 解答例
//-------------------------------------
member *addr(group *g, int i){
  member *p=g->top; int k;
  for(k=0; k<g->max; k++){
    if(p[k].id==i || p[k].id==0){break;}
  }
  if(k<g->max){return p+k;}
  else{return NULL;}
}
//-------------------------------------


問5-1. P53A のプログラムに次の void 型関数を追加せよ.
(1) 引数 i の値に等しい id のメンバの id, name, mail
   を表示する関数 show(int i).
  a) 存在しない id のときは "?\n" を表示する. 
(2) 引数 i, *n, *m の値を id, name, mail とする新しい
   メンバを追加する関数 add(int i, char *n, char *m).
  a) i は正の整数とする.(id==0 の行は空)
  b) id が 0 でない行は連続しているとする.
  c) id が既存のとき,登録メンバ数が 10 のときは "-\n"
     を表示する.
(3) 引数 i の値に等しい id のメンバの行を削除する関数
    del(int i).
  a) 削除した行には id>0 である末尾のデータを移動する.
  b) 存在しない id のときは "?\n" を表示する. 

・文字列のコピーにシステム関数の strcpy() を使いました.
    void strcpy(char *to, char *from){
      while(*to++=*from++);
    }
・各関数には引数 i に等しい id のメンバが登録されている
  か否かを調べ,登録されていれば igo[k]==i である k の
  値あるいは igo[k] のアドレスを求めるという共通の処理
  があります.Ex5-1 の解答例では関数 addr() でこの処理
  を行っています.
・main() を
    int main(void){
      member *p=igo;
      add(5, "Tanaka", "foo@zzz.ac.jp");
      del(2);
      while(p->id!=0){show(p->id); p++;}
      return 0;
    }
  に変更して実行すると,
    1, Aoki, aoki@xxx.ne.jp
    5, Tanaka, foo@zzz.ac.jp
  と表示されることを確認してください.

問5-2. Ex5-1 の関数を igo[10] 以外の member 型変数の配列
にも使えるように,構造体 group を
  typedef struct{
    member *top; int max;
  } group;
で定義し,「group g_igo={&igo, 10};」で宣言された g_igo に
対して
  show(&g_igo, i)
  add(&g_igo, i, *n, *m)
  del(&g_igo, i) 
を Ex5-1 の show(i), add(i, *n, *m), del(i) の代わりに使う
ように変更したい.このための addr() の変更案を示せ.

・show(), add(), del() は addr() の呼び出し部分以外は変わり
  ません.