Back!

プログラミング演習 1年次後期 担当:村田 忠彦

目次

  1. はじめに

  2.  Oct. 22, 1999
  3. 画面への出力とキーボードからの入力

  4.  Oct. 29, 1999
  5. 条件分岐と繰り返し

  6.  Oct. 22, 1999
  7. 配列

  8.  Oct. 28, 1999
  9. ポインタ

  10.  Nov. 9, 1999
  11. 関数

  12.  Nov. 15, 1999
  13. ファイル入出力

  14.  Dec. 1, 1999
  15. 構造体

  16.  Dec. 6, 1999

All rights reserved by Tadahiko Murata, 1999

  1. はじめに
  2. 授業概要:プログラミング演習は,「プログラミング言語」で解説する Cプログラミング技法を用いてプログラミングを行い, 一層習熟することを目的とします.

     実際の授業は次のように進めていくものとします.()内はそれぞれ,該当する授業を表します.

    1. (演習)  演習課題を行い,実行可能なプログラムの記述方法を習得する.
    2. (言語)  授業の解説を聞き,演習で用いた関数,制御構造,データ構造についての理解を深める.
    3. 新しく学んだプログラミング技法を用いて更に高度なプログラミングを含めたレポートを仕上げる.

    以上のように,授業はトライ&エラーで進めていきます.したがって,演習の課題は行わなくても授業の内容を聞けば, プログラミング技法についての理解を得ることはできますが,

    この機能はどうなっているんだろう?
    これができたから,次はこんな事をしたいけどどうしたらいいんだろう?

    という疑問をもち,モチベーションを高めることによって,一層授業から学ぶことができる,と考えます.十分,演習課題を行い, 授業はわかったところの整理,わからないところや漠然としたところの確認 のつもりで聴講して下さい.

     このようなスタンスで「プログラミング演習」と「プログラミング言語」の授業を進めていきますので, 演習をおこなう時には,次のようなプロセスを踏んで下さい.

    1. 演習を行い,とりあえずできるようになる.
    2. 値を変えたりして,なにがどう変わるかを調べ,よくわからないところを発見する.
    3. わからないところについての,テキストを見る.
    4. 図書館やインターネットで,自分の知りたい情報が知りたい形で書かれている書物やページを探す.
    5. 授業を聞く.

     授業に参加する前にできることがたくさんあることに気づくはずです.プログラミング技法とは直接関係はありませんが, 自分の知りたい情報を自分で取得する力を身につけることも,授業を通して身につけて欲しい能力です.

    以下の各章の課題は,次のようなテーブル形式で記述されています.プログラムのインデントが正しく見えるように できるだけ画面はフルサイズにして見て下さい.

    例題のタイトルを示します.
    printf関数の使い方
    プログラムの概要を示します.
    printf関数を使って,画面出力を行います.
    プログラムコードを示します.

    #include<stdio.h>

    void main( void )
    {
      printf( "My name is Tadahiko Murata\n" );
    }
    プログラム記述の際の注意事項を示します.

    必ずプログラムの最初に書くこと!



    printf関数による出力
    行末にセミコロン( ; )を忘れないように!
    実行結果疑問に思って欲しい点
    実行結果と実行結果に対する注釈を示します.

      My name is Tadahiko Murata!
       名前がモニターに出ます.
    考察できる点を示します.

    ・ ダブルクォーテーション( " " )の中の \n がなくなるとどうなるか?
    Next!(さらに高度なことをやってみよう!)
    他にどんな使い方ができるか示します.

    ・ プログラム中の変数の値を出力する(変数の型と出力形式の関係).
    ・ 数字以外に任意の文字列を出力するにはどうすればいいか?(文字列の出力)

    表の内容にしたがって,次のような順番で演習を行っていってください.

    1. プログラムコードを入力する.
    2. 結果を確認する.
    3. プログラムコードの書き換えによってどんな動作をするかを確認する.
    4. さらに複雑な機能を使ってみる.

    ※注意事項
     このページに記載されているプログラムは,ウェブページ用に書かれたものです. 実際の挙動については責任を持てませんので,各自の責任のもとにプログラムを組み, 実行して下さい.間違っているところを見つけたら, 村田(←クリックすれば,メーラーが 立ち上がります)まで連絡して下さい.

    参考図書
    ・ 「Turbo C 初級プログラミング」 河西 朝雄 著 技術評論社 (1989) \2,200
    ・ 「Cプログラミング診断室」 藤原 博文 著 技術評論社 (1993) \2,427+Tax
    ・ 「新ANSI C言語辞典」 平林 雅英 著 技術評論社 (1995) \2,300+TAX

    参考になるページ
    C++入門のページ
    Cプログラミング診断室 目次にたどり着くまでの前置きが長いですが・・
    プログラミング超入門
    猫でもわかるプログラミング


  3. 画面への出力とキーボードからの入力
  4. まず,プログラミングを行い,挙動を確かめ,納得できたら,次の課題に進んでいきましょう. この課題では,printf関数(画面表示)とscanf関数(キーボード入力)についての理解を深めます.

    printf関数とscanf関数 実数型の変数を入力し,加減乗除の結果を表示する.

    #include<stdio.h>

    void main( void )
    {
      double x, y;

      printf( "入力した2つの数の加減乗除を行います." );
      printf( "割る数には0を入力しないでください.\n" );

      printf( "一つ目の変数−double(実数)型:x=");
      scanf( "%lf", &x );
      printf( "\n2つ目の変数−double(実数)型:y=");
      scanf( "%lf", &y );

      printf("\nx + y = %f + %f = %f\n"
          , x, y, x + y );
      printf("x - y = %f - %f = %f\n"
          , x, y, x - y );
      printf("x * y = %f * %f = %f\n"
          , x, y, x*y );
      printf("x / y = %f / %f = %f\n"
          , x, y, x/y );
    }


    必ずプログラムの最初につけること.



    変数の定義

    入力に関する画面表示


    変数入力を促す表示
     1つ目の変数の入力
    変数入力を促す表示
     2つ目の変数の入力

    足し算

    引き算

    かけ算

    わり算
    実行結果疑問に思って欲しい点
      x + y = 2.0000 + 4.0000 = 6.0000
      x - y = 2.0000 - 4.0000 = -2.0000
      x * y = 2.0000 * 4.0000 = 8.0000
      x / y = 2.0000 / 4.0000 = 0.5000

    • int(整数)型にした場合にはどうなるか?
    Next!(さらに高度なことをやってみよう!)

    • int型変数同士の計算で,実数の結果を出したい.→キャスト
    • 実数型変数の出力桁数を少なくする.
    • 文字列入力を行い,表示を行う.

    All rights reserved by Tadahiko Murata, 1999

  5. 条件分岐と繰り返し
  6. まず,プログラミングを行い,挙動を確かめ,納得できたら,次の課題に進んでいきましょう. この課題では,if else文(条件分岐)とfor文(繰り返し)についての理解を深めます. 他にも,条件分岐についてはswitch case文が,繰り返しについてはwhile文などがありますが, これらは,if else文やfor文によっても表現可能ですので省略し,自学自習の範囲とします.

    if else文とfor文 if文を用いた条件分岐とfor文を用いた繰り返しにより,
    *で直角三角形を画面に描きます.

    #include<stdio.h>

    void main( void )
    {
      int a;
      int cnt, cnt1;

      printf( "5以下の正の整数を入力" );
      printf( "してください.\n" );

      scanf( "%d", &a );
      if( a>0 && a<=5 ){
        for( cnt=0;cnt<a;cnt++ ){
          for( cnt1=0;cnt1<cnt;cnt1++ ){
            printf( "*" );
          }
          printf( "\n" );
        }
      }else{
        printf( "5以下の正の整数を入力してくだ" );
        printf( "さい.プログラムを終了します.\n" );
        exit(1);
      }
    }


    必ずプログラムの最初につけること.



    変数の定義






    条件の設定
    (プログラムの仕様にかなう場合の動作)





    条件の設定(プログラムの仕様に
    合わない入力を拒否し,終了する)

    プログラムの強制終了


    実行結果疑問に思って欲しい点
      *
      **
      ***
      ****
       5段にならないことに注意しよう!

    • printf関数とscanf関数は十分理解できているか? (→前章へ
    • if文で大小比較の条件文はどのように作成するのか?
    • 複数の条件を組み合わせたいときは?
    • for文では,どんな順番で繰り返しが行われるのか?
    Next!(さらに高度なことをやってみよう!)

    • 上記のプログラムを,1〜5の数字が入力されるまで,入力を求める プログラムに書き換える(if else文,for文,ループからの飛び越し). → while文を使っても良い.
    • 入力した文字を大文字にして表示する(if else文,文字コード).
    • ASCIIコードの32〜127に対応するキャラクタと16進コードを表示する(if else文,for文,文字コード).
    • 任意の数の整数データを入力し,合計と平均を求める.(if else文,for文,ループからの飛び越し).

    All rights reserved by Tadahiko Murata, 1999

  7. 配列
  8. まず,プログラミングを行い,挙動を確かめ,納得できたら,次の課題に進んでいきましょう. この課題では,配列についての理解を深めます.

    配列 配列を用いて,入力されたデータの出現頻度を
    ヒストグラムにより表します.

    #include<stdio.h>

    void main( void )
    {
      int histogram[11];
      int cnt, cnt1, dat;

      for( cnt=0;cnt<11;cnt++ ){
        histogram[cnt]=0;
      }

      printf( "0〜100の整数を入力" );
      printf( "してください.\n" );
      printf( "データの入力の終わりには,");
      printf( "Ctrl+zを入力してください.\n" );

      while( scanf("%d", &dat)!= EOF ){
        if( 0<=dat && dat<=100 ){
          histogram[dat/10]++;
        }
      }
      printf("\n----- Histogram -----\n" );
      for( cnt=10;cnt>=0;cnt-- ){
        printf( "%3d -  ", cnt*10 );
        for( cnt1=0;cnt1<histogram[cnt];cnt1++ ){
          printf( "*" );
        }
        printf( "\n" );
      }
    }


    必ずプログラムの最初につけること.



    配列の定義(histogramと言う名前で,
    [0]から[10]までの箱をつくる)

    配列の要素を初期化する(0を代入しておく).



    入力データに関する指示を画面に出す.




    Ctrl+zが入力されるまでデータの入力を行う.
    データが0から100までの間に入っているとき,
    対応する配列要素を一つ増やす.


    配列要素のヒストグラム表示
    実行結果疑問に思って欲しい点
      100 -  *
       90 -  **
       80 -  ***
       70 -  ****
       60 -  **
       50 -  ***
       40 -  ****
       30 -  **
       20 -  ***
       10 -  ****
       0 -  **

    • while関数について理解できているか?
    • データの入力の終了条件について理解できているか?
    • 配列の箱の番号は何番からついているか?
    Next!(さらに高度なことをやってみよう!)

    • 適当に数字を入力し,その数字に含まれる0〜9の数字の数をカウントするプログラムを 作成する.→getchar関数について調べる.
    • 複数人の成績表を作成し,各人の平均点を計算して,出力するプログラムを作成する. →二次元配列について調べる.

    All rights reserved by Tadahiko Murata, 1999

  9. ポインタ
  10. まず,プログラミングを行い,挙動を確かめ,納得できたら,次の課題に進んでいきましょう. この課題では,ポインタについての理解を深めます.

    ポインタと配列 任意の長さの文字列を入力して,一文字ずつ出力する.

    #include<stdio.h>

    void main( void )
    {
      char str[30];
      char *pstr;

      printf( "入力した文字を配列strに格納します." );
      printf( "30文字以内の英数字を入力してください.\n" );

      scanf( "%s", str );

      printf( "\n入力された文字は「%s」です.\n", str);

      printf("縦に書くと次のようになります.\n" );

      pstr = &str[0];
      while( *pstr != '\0' ){
        printf( "%c\n", *pstr );
        pstr++;
      }
    }


    必ずプログラムの最初につけること.



    文字型配列の定義.30個の箱が用意される.
    ポインタ変数の定義.

    入力に関する画面表示


    アルファベットの入力

    入力された文字の一括出力.



    ポインタ変数の初期化.配列の先頭アドレスを格納する.
    入力された文字の一文字ずつの出力.

    アドレスを一つ増やす.


    実行結果疑問に思って欲しい点
      入力された文字は「Nandemo_OK!」です.
      縦に書くと次のようになります.
      N
      a
      n
      d
      e
      m
      o
      _
      O
      K
      !

    • while文の中の条件はなにを表しているか?
    • cnt++;で何を増やしているか?
    • スペースを入力したらどうなるか確かめよう.
    Next!(さらに高度なことをやってみよう!)

    • 2次元配列に対するポインタを使う.→p.106 例題25
    • 入力した文字列で三角形を作る.→p.108 例題26

    All rights reserved by Tadahiko Murata, 1999

  11. 関数
  12. まず,プログラミングを行い,挙動を確かめ,納得できたら,次の課題に進んでいきましょう. この課題では,関数の作り方と関数間のデータの授受についての理解を深めます.この課題では 2つの課題があるので,まず,基本となる課題を2つ仕上げてから,Next!の課題に進んでください. 変数,値,ポインタ,アドレスの関係についてよく理解するようにしてください.

    関数(その1) 多入力一出力の関数を作る.変数の値を関数に渡す方法.

    #include<stdio.h>

    int plus( int x, int y );

    void main( void )
    {
      int a, b, c, d;
      int ans;

      a = -10;
      b = 20;

      ans = plus( a, b );

      printf( "a + b = %d + %d = %d\n", a, b, ans );

      c = 30;
      d = -40;

      ans = plus( c, d );

      printf( "c + d = %d + %d = %d\n", c, d, ans );
    }

    int plus( int x, int y )
    {
      int z;

      z = x + y;

      return( z );
    }

    必ずプログラムの最初につけること.

    main関数の中で用いる関数の定義.



    変数の定義.
    答えを代入する変数の定義.

    変数に値を代入する.


    plus関数を使って足し算を行う.aとbのを関数に対する入力値とする.

    計算結果の出力.

    変数に値を代入する.


    plus関数を使って足し算を行う.cとdのを関数に対する入力値とする.

    計算結果の出力.


    plus関数の記述. 出力の型 関数名( 入力の型 変数名, 入力の型 変数名 )

    plus関数の中だけで使うことのできる変数の定義.

    足し算の実行.

    足し算の結果を関数の出力とする.

    実行結果疑問に思って欲しい点
      a + b = -10 + 20 = 10
      c + d = 30 + -40 = -10

    • 関数にする事によってどんな利点があるのか?
    Next!(さらに高度なことをやってみよう!)

    • 引き算,かけ算,わり算の関数を作ってみる.
    • 二次方程式の解を求めるプログラムを作ってみる.
      • 係数はキーボード入力.
      • 解の公式の部分はmain関数以外の関数で行う.
     
    関数(その2) 多入力多出力(?)の関数を作る.変数のアドレスを関数に渡す方法.

    #include<stdio.h>

    int plus( int *x, int *y );

    void main( void )
    {
      int a, b, c, d;
      int ans;

      a = -10;
      b = 20;

      ans = plus( &a, &b );

      printf( "a + b = %d + %d = %d\n", a, b, ans );

      c = 30;
      d = -40;

      ans = plus( &c, &d );

      printf( "c + d = %d + %d = %d\n", c, d, ans );
    }

    int plus( int *x, int *y )
    {
      int z;

      if( *x < 0 )
        *x = -1*(*x);
      if( *y < 0 )
        *y = -1*(*y);

      z = *x + *y;

      return( z );
    }

    必ずプログラムの最初につけること.

    main関数の中で用いる関数の定義.



    変数の定義.
    答えを代入する変数の定義.

    変数に値を代入する.


    plus関数を使って足し算を行う.aとbのアドレスを関数に対する入力値とする.

    計算結果の出力.

    変数に値を代入する.


    plus関数を使って足し算を行う.cとdのアドレスを関数に対する入力値とする.

    計算結果の出力.


    plus関数の記述. 出力の型 関数名( 入力の型 変数名, 入力の型 変数名 )

    plus関数の中だけで使うことのできる変数の定義.

    変数が負の場合は正の数にする.




    足し算の実行.

    足し算の結果を関数の出力とする.

    実行結果疑問に思って欲しい点
      a + b = 10 + 20 = 30
      c + d = 30 + 40 = 70

    • 値を関数に渡す場合とどのように変わっているかを観察する.
    • 下の例で,値を渡すように変更した場合にどのように結果が変わるかを調べてみよう!
    • 答えを格納する変数ansもplus関数の引数にして,plus関数の戻り値をvoidにしても 計算結果が出るプログラムにしてみよう.
    Next!(さらに高度なことをやってみよう!)

    • 行列の逆行列を求めるプログラムを作ってみる.→配列のアドレスの渡し方と関数内での参照の仕方(p.119)

    All rights reserved by Tadahiko Murata, 1999

  13. ファイル入出力
  14. まず,プログラミングを行い,挙動を確かめ,納得できたら,次の課題に進んでいきましょう. この課題では,ファイル入出力についての理解を深めます.

    ファイル入出力 ファイル入出力

    #include<stdio.h>
    #include<process.h>

    void main( void )
    {
      FILE *fp;
      int year;
      char name[20];

      if( (fp=fopen( "file.txt", "w" ) ) == NULL ){
        printf( "Can not open the file.txt.\n" );
        exit( 1 );
      }

      printf( "名前  年齢 を入力してください.\n" );
      printf( "入力の終わりはCTRL+zを入力してください.\n" );
      fprintf( fp, "名前 年齢\n" );

      while( scanf( "%s %d", name, &year ) != EOF ){
        fprintf( fp, "%s %d\n", name, year);
      }
      fclose( fp );
    }


    必ずプログラムの最初につけること.
    exit関数を使うために必要なヘッダファイル.



    ファイルポインタの定義.
    変数の定義.
    文字列配列の定義.

    ファイルのオープン,書き込み型で定義する.
    書き込めない場合に,エラー文を画面表示して,
    終了する.


    入力を促すメッセージ文の画面表示.
    入力終了条件の指示.
    ファイルの項目のファイルへの書き込み.

    キーボードからの入力


    ファイルのクローズ


    実行結果疑問に思って欲しい点
      名前 年齢
      福田 20
      田中 19
      中村 19
      立花 21
      重田 20
      -----ここまで-----
      実行ファイルと同じフォルダでfile.txt
      というファイルをみつけ,内容を確認する.
      ファイル-開く-ファイルの種類(テキストファイル)
      でファイルを見つける.

    • 入力された文字がファイルに書き込まれていることを確認しよう.
    • printf関数とfprintf関数の違いを把握するようにしよう.
    Next!(さらに高度なことをやってみよう!)

    • ファイルからの読み込みを行う.→p.207-215
    • Excelなどの表計算ソフトにデータを読み込ませてみよう.

    All rights reserved by Tadahiko Murata, 1999

  15. 構造体
  16. まず,プログラミングを行い,挙動を確かめ,納得できたら,次の課題に進んでいきましょう. この課題では,構造体についての理解を深めます.

    構造体 構造体

    #include<stdio.h>
    #include<process.h>

    struct meibo{
      char name[20];
      char tel[20];
      char address[20];
    };

    void message( void );
    void input( FILE *fp, int cnt , struct meibo *a, int *end );

    void main( void )
    {
      struct meibo a[20];
      FILE *fp;
      int cnt, end;

      if( (fp=fopen( "meibo.dat", "w" ) ) == NULL ){
        printf( "Can not open the meibo.dat.\n" );
        exit( 1 );
      }

      message();

      fprintf( fp, "番号, 名前, TEL, 住所\n" );
      fflush( fp );

      cnt = 0;
      end = 0;
      while( end == 0 ){
        input( fp, cnt, &a[cnt], &end );
        cnt++;
        fflush( fp );
        if( cnt == 20 ){
          printf( "人数が一杯です.終了します.\n" );
          end = 1;
        }
      }
      fclose( fp );
    }

    void message( void )
    {
      printf( "名前, TEL, 住所, endを入力してください.\n" );
      printf( "継続の時はend=0," );
      printf( "中止の時は,end=1と入力してください.\n" );
    }

    void input( FILE *fp, int cnt, struct meibo *a, int *end )
    {
      printf( "名前-->" );
      scanf( "%s", a->name );
      printf( "TEL -->" );
      scanf( "%s", a->tel );
      printf( "住所-->" );
      scanf( "%s", a->address );
      printf( "Exit? Continue:0 Exit:1 -->" );
      scanf( "%d", end );
      printf( "\n" );
      fprintf( fp, "%2d, %s, %s, %s\n",
        cnt+1, a->name, a->tel, a->address );
    }


    必ずプログラムの最初につけること.
    exit関数を使うために必要なヘッダファイル.

    構造体meiboの宣言.
    構造体の内容の定義.


    }の後のコンマを忘れないように!

    入力を促す画面表示関数.
    入力関数



    構造体配列の定義.
    ファイルポインタの定義.
    カウンタ変数の定義.

    ファイルのオープン,書き込み型で定義する.
    書き込めない場合に,エラー文を画面表示して,
    終了する.


    入力を促すメッセージ文を画面表示するための関数.

    ファイルの項目のファイルへの書き込み.
    ファイルポインタバッファの解放.

    カウンタ変数の初期化.
    終了判定変数の初期化.
    終了判定(0の場合にwhile文を実行する).
    入力のための関数.
    カウンタの増分.
    ファイルポインタバッファの解放.
    カウンタが一杯の時の対応.




    ファイルポインタのクローズ.


    message関数の内容.

    画面表示.




    input関数の内容.

    入力を促す画面表示.
    scanf関数による変数への入力




    終了判定変数への値の入力.


    入力された値のファイルへの書き込み.


    実行結果疑問に思って欲しい点
      番号, 名前, TEL, 住所
       1, 福田, 56-3478, 足利市
       2, 田中, 65-9947, 足利市
       3, 中村, 37-6587, 佐野市
       4, 立花, 42-3456, 佐野市
       5, 重田, 88-9987, 宇都宮市
      -----ここまで-----
      実行ファイルと同じフォルダでmeibo.dat
      というファイルをみつけ,内容を確認する.
      ファイル-開く-ファイルの種類(テキストファイル)
      でファイルを見つける.

    • 関数について理解できているか確認しよう.
    Next!(さらに高度なことをやってみよう!)

    • Excelなどの表計算ソフトにデータを読み込ませてみよう.

    All rights reserved by Tadahiko Murata, 1999