/* * 課題 CNAME-02 * * CDATE FILENAME * * 代入文 * 整数型変数 ( a, b, c ) を三つ宣言する * 整数型変数 a, b にそれぞれ、123, 4 を代入する * 整数型変数 c に a と b の和を代入する * 整数型変数 c の値を画面に出力する */ #include <stdio.h> #include "s_print.h" /* * main */ int main( int argc, char *argv[] ) { /* 整数型変数 a の宣言 */ int a; /* 整数型変数 b の宣言 */ int b; /* 整数型変数 c の宣言 */ int c; /* 整数型変数 a に 123 を代入 */ a = 123; /* 整数型変数 b に 4 を代入 */ b = 4; /* 整数型変数 c に、変数 a と 変数 b の和を代入 */ c = a + b; /* 整数型変数 c の値を画面に出力 */ s_print_string ( "変数 c の値は " ); s_print_int ( c ); s_print_string ( " です。\n" ); return 0; }
#include <stdio.h> #include "s_print.h" /* この講義でのみ使う表現 */ /* 二つの整数値の和を出力する */ void print_add_num ( int n, int m ) { s_print_string ( "二つの整数値の和は " ); s_print_int ( n + m ); /* 変数 n, m に具体的な数値が割り当てられていれば */ /* 数式(文字式)「n + m」で、二つ変数が持つ値の「和」が表現できる */ s_print_string ( "です。\n" ); } int main(void) { print_add_num ( 3, 8 ); /* 3, 8 という実引数を与えて、関数呼び出し */ /* 実引数は、仮引数変数 n, m の値を割り当てる */ print_add_num ( 123, 456 ); return 0; }
#include <stdio.h> #include "s_print.h" /* 引数で与えられた、整数値と、その次の整数値を出力 */ void print_num_and_num_plus_one ( int num ) { s_print_int ( num ); /* 引数で与えれた数自身 */ s_print_string ( ", " ); s_print_int ( num + 1 ); /* 引数で与えれた数の次の数 */ s_print_string ( "\n" ); } int main(void) { print_num_and_num_plus_one ( 123 ); print_num_and_num_plus_one ( 9876 ); return 0; }
#include <stdio.h> #include "s_print.h" /* 引数で与えられた、整数値と、その次の整数値を出力 代入版 */ void print_num_and_num_plus_one ( int num ) { /* 変数 num には、引数で指定された値が割り当てられている */ s_print_int ( num ); /* 引数で与えれた数自身 */ /* 変数 num には、実引数の値が入っている */ s_print_string ( ", " ); num = 999; /* 変数 num に無条件に 値 999 を代入 */ /* 変数 num には、代入された 999 という値が入っている */ s_print_int ( num ); /* 引数で与えれた数の次の数 */ /* 変数 num には、最後に代入された値 999 が入っている */ s_print_string ( "\n" ); } int main(void) { print_num_and_num_plus_one ( 123 ); print_num_and_num_plus_one ( 9876 ); return 0; }
#include <stdio.h> #include "s_print.h" /* 引数で与えられた、整数値と、その次の整数値を出力 代入版 */ void print_num_and_num_plus_one ( int num ) { /* 変数 num には、引数で指定された値が割り当てられている */ s_print_int ( num ); /* 引数で与えれた数自身 */ /* 変数 num には、実引数の値が入っている */ s_print_string ( ", " ); num = /* num の「引数の値」に 1 を加えたもの */ /* num の「現在の num の値」に 1 を加えたもの */ num + 1; /* 「num = num + 1」*/ /* 「0 = 1」と思いそうだが、誤り */ /* C 言語では、「=」(等号)を「等式」に利用せず、「代入」に利用する */ /* 「x = 1」は、C 言語では x に 1 を「割り当てる(代入)」の意味で、 x と 1 が等しいという等式の意味ではない C 言語では、「等式」は、「==」という記号で表現する 「 1 == 1 」は正しい(真となる/成立する)等式 「 1 == 0 」は誤った(偽となる/成立しない)等式 */ /* 代入文 num = num + 1; により、 変数 num に、「現在の変数 num の値と 1 の和」を計算した値 が代入される => 「変数 num の値を 1 増やす」事になる */ s_print_int ( num ); /* 引数で与えれた数の次の数 */ /* 引数 123 -> 124 */ /* 引数 9876 -> 9877 */ s_print_string ( "\n" ); } int main(void) { print_num_and_num_plus_one ( 123 ); print_num_and_num_plus_one ( 9876 ); return 0; }
#include <stdio.h> #include "s_print.h" /* 引数で与えられた、整数値と、その次の整数値を出力 代入版 */ void print_num_and_num_plus_one ( int num ) { int mum = 0; /* 新しい整数型の局所(local)変数 mum の宣言 */ /* 宣言したばかりの変数の値は「不定」なので 局所変数は必ず、代入して使う必要がある */ /* ここでは、初期値 0 で初期化している */ s_print_int ( num ); /* 引数で与えれた数自身 */ s_print_string ( ", " ); mum = num + 1; /* num = num + 1; もともとあった num の値(実引数の値) が、失われてしまう(破壊的な振る舞い) これがいやなら 別の変数を用意して、 その変数(mum)に代入する mum = num + 1; mum には num + 1 の値が代入される # num の値は残っている ただし、 新しい変数 mum を利用するには、 その変数の「宣言」が必要 => 局所変数宣言 */ s_print_int ( mum ); s_print_string ( "\n" ); s_print_string ( "念のため num を確認 num = " ); s_print_int ( mum ); s_print_string ( "\n" ); } int main(void) { print_num_and_num_plus_one ( 123 ); print_num_and_num_plus_one ( 9876 ); return 0; }
前回(2020/09/18)の内容 ガイダンス 基本は、前期と同じ ただし、前期の知識を仮定する 目的 : 「C 言語でプログラムが書けるようになる」事 簡単なプログラムは書ける !! 原理的には、すでに、どんな目的のプログラムも書ける 三つの内容 プログラミング プログラムとはなにか プログラム作成するには、どうように考えればよいか 与えられた問題を簡単な問題に分割する(分割統治) プログラム : 入力-処理-出力 再帰関数(帰納法) : N 一般を 1 と k -> k+1 の二つに分ける => 数学の概念は、プログラムの作成のヒント 操作方法 (ubuntu の操作) コンパイル / 実行の仕方 C 言語 ( ソフトウェア概論のメイン ) プログラミング言語としての C 言語の説明 プログラムの表現の仕方 文字列の出力をするにはどうするか => printf 変数の代入をするにはどうするか => 代入文を使う 方針 同じ内容を 3 度 繰返しながら 少しずつ内容を深く進める 復習をしながら、思い出しながら、繰り返し 「実技」 学習のためには、繰り返し「手を動かす」 # 手と同時に頭も動かす 復習 1 周回 : hello world, 関数, 制御構造(順接,条件分岐,再帰) 原理的に可能なプログラムは一通りかける 2 周目 : 様々なデータ構造 ( char, int ) まだ、途中 : 早めに終らせて、3 周回のアプリ開発に行きたい 新規 変数宣言と代入文 (代入によって、変数の値を変更する) 代入 代入とは 概念 : 「変数」に「値」を「割り当て」る「操作」 変数 : 変化する「数」 変数の表し方(数学) : 文字で変数を表す a + b = b + a (交換法則) 任意の二つの数 a, b に 「a に b を加える」、「b に a を加える」 の計算結果は等しい => 実際に計算する場合は、 変数 a, b に具体的な値が入っていないといけない a <- 3 b <- 8 3 + 8 = 11 = 8 + 3 二次方程式 a x^2 + b x + c = 0 解は x = (-b +- \sqrt{ b^2 - 4 a c }) / (2a) 実際に利用する場合は a, b, c に値を具体的に与えないといけない 例 : a <- 1, b <- -2, c <- -3 x^2 - 2x - 3 = 0 x = ( -(-2) +- \sqrt{ (-2)^2 - 4 (1)(-3) } ) / (2 (1)) = ( 2 +- \sqrt{ 4 + 12 } ) / 2 = ( 2 +- 4 ) / 2 = 1 +- 2 = 3, -1 コンピュータ(C 言語)では「計算式」は、変数(文字)を含んだ「文字式」で表現可能 実際に計算をする場合 ( 変数に具体的な値を割り当てる必要がある ) 関数呼び出しにおける「実引数(値の指定)」は、 関数の仮引数変数への「値の割り当て(代入)」を行う # 数学の関数評価(関数値の計算)に対応 # f(x) = x^2 (関数定義) # f(4) = 4^2 = 16 # f(4) # f(x)=x^2 # f(x) -> x^2 # f(4) -> x^2 ( x := 4 ) # -> 4^2 # -> 16 代入文 ( C 言語において、変数に値を直接割り当てる表現 ) 構文 : 変数名 = 式; 例: x = 1; very_long_name_variable = 1 + 3 * 7 + 123; 意味 : 式の値を計算し、その結果を変数に代入する 変数に値を代入すると、 その変数には、その値が割り当てられてられて それ以後は、その変数の値は、その値になる # その変数を含む命令の振る舞いが変化する 代入「後」は、 その変数の値は、代入さ(割り当てら)れた値に「変化」する (その変数が保持していた..) 代入「前」の値は、「失われ」る # 変数は、値の「入れ物」を表現していると解釈できる # 例 : 財布は、お金の入れ物 # 財布にいつでも、3 万円入っているわけじゃない # => 飲みに 1 万円 => 残りは 2 万円 # 代入の結果 # その代入された変数を含む命令の振る舞いが(その変化する変数の値を利用するので..結果的に)変化する # 代入によって、振る舞いが変わる 代入の「前」と「後」という「時間」の概念の把握が必要となる # 「時間」が変化する <=> 「変数に割り当てられている値」が変化 表現 : 代入の構文 「変数名」=「式」 [例] a=1+2; (変数 a に 3 ( = 1+2 ) を代入) 「=」は、「代入」を表現する(等号[等しい]ではない!! / 等号は「==」) 局所変数宣言 概念 : 局所変数を宣言する 局所変数 : 関数の本体の先頭で宣言し、 その関数の本体内だけで利用可能な変数 # 「関数の中だけ」という「局所(限定された範囲)」のみ利用可能な変数 # => 「局所変数」 # !! 関数の外でも利用可能な変数 => 「大域変数」 関数(ブロック)内のみ(局所的)で有効(利用可能)な変数を宣言する 「仮引数変数(実は局所変数の一種)」以外にも、変数が増やせる 表現 : 局所変数の宣言 「変数の型名」「変数名」 [例] int a; (整数型の変数 a を宣言) cf. 仮引数変数は、実引数の値で、「代入済」の変数 未代入の変数の値は「不定(プログラムミスの代表例 !!)」 変数は宣言と同時に「初期化(最初の代入)」できる(すべき) [例] int a=1;
課題プログラム内の「/*名前:ここ*/」の部分を書き換え「/*この部分を完成させなさい*/」の部分にプログラムを追加して、プログラムを完成させます。
Download : 20200925-01.c
/* * 20200925-01-QQQQ.c */ #include <stdio.h> /* * int quad_number ( int n ) * 奇数の和で二乗を計算する */ int quad_number ( int n ) { if ( n <= 0 ) { return 0; } else { /* 再帰呼出し */ /* n^2 = (n-1)^2 + (2n-1) */ /* ** この部分を完成させなさい */ } } /* * main */ int main ( void ) { /* sum = 1 + 3 + .. + 9 = 25 = 5^2 */ /* 整数型変数 sum の値を画面に出力 */ printf ( "1 から %d までの奇数の和は %d です。\n", 2 * 5 - 1, quad_number ( 5 ) ); return 0; }
$ ./20200925-01-QQQQ.exe 1 から 9 までの奇数の和は 25 です。 $
Download : 20200925-02.c
/* * 20200925-02-QQQQ.c * 四角数の計算 ( while 構文 版 ) */ #include <stdio.h> /* * main */ int main ( void ) { /* 整数型変数 odd の宣言とその初期化 ( 初期値は 1 を指定 ) */ int odd = 1; /* 整数型変数 sum の宣言とその初期化 ( 初期値は 0 を指定 ) */ int sum = 0; /* sum = 1 + 3 + .. + 9 = 25 = 5^2 */ /* odd の値が 9 以下の間は繰り返す */ while ( /* q:ここ */ ) { /* sum に odd の値を「追加」する */ /* ** この部分を完成させなさい */ /* odd の値を次の奇数にする */ odd = odd + 2; } /* 整数型変数 sum の値を画面に出力 */ printf ( "1 から %d までの奇数の和は %d です。\n", 2 * 5 - 1, sum ); return 0; }
$ ./20200925-02-QQQQ.exe 1 から 9 までの奇数の和は 25 です。 $
Download : 20200925-03.c
/* * 20200925-03-QQQQ.c * ファイルの中の数値の総和 */ #include <stdio.h> /* * main */ int main ( void ) { FILE *fp; /* 入力するファイルへのファイルポインタ値を持つ変数 */ int num; /* 入力された一つの整数値を持つ変数 */ int sum; /* 合計値 */ /* ファイル 「num.txt」を、読込モード 「r」で開く (open) */ /* ** この部分を完成させなさい */ if ( fp != NULL ) { /* ファイルのオープンができた */ sum = 0; /* 総和を 0 で初期化 */ while ( fscanf ( fp, "%d", &num ) > 0 ) { /* データを読み込む */ /* データがある限り.. */ /* sum に読み込んだ値 (num) を加える */ /* ** この部分を完成させなさい */ } printf ( "総和は %d です。\n", sum ); /* ファイルは必ずクローズする */ /* ** この部分を完成させなさい */ } else { /* エラーメッセージを出力 */ fprintf ( stderr, "ファイルがオープンできません\n" ); return -1; /* エラー終了 */ } return 0; }
$ ./20200925-03-QQQQ.exe 総和は 258 です。 $