/*
* 課題 CNAME-01
*
* CDATE FILENAME
*
* Hello, World (3 度目)
*/
#include <stdio.h>
/*
* main
*/
int main( int argc, char *argv[] )
{
printf ( "Hello, World\n" );
/*
画面に「Hello, World」という文字列と、
その後に、「改行」を表示する
=> このプログラムを実行すると、
画面に「Hello, World[改行]」が表示される
*/
return 0;
}
/*
* 課題 CNAME-02
*
* 20210917 20210917-02-QQQQ.c
*
* 局所変数の宣言と、代入文
* 局所変数の宣言:
* 利用する変数名をきめ、その型宣言(変数に代入可能な値の型の指定)
* printf の使い方
*/
#include <stdio.h>
/*
*
*/
/*
* main
*/
int main( int argc, char *argv[] )
{
/* 二つの整数型(int)の変数 ia, ib の宣言と、初期代入 */
int ia = 7;
int ib = 15;
/* 二つの浮動小数点型(double)の変数 da, db の宣言と、初期代入 */
double da = 3.14;
double db = 1.59;
printf ( "%d + %d = %d\n", ia, ib, ia + ib ); /* 整数型の和 */
/* 結果
ia <= 7, ib <= 15, 22 => ia + ib
7 + 15 = 22
7 + 15 = 22
^ ^^ ^^ 3 箇所 整数型 ( ia, ib, ia + ib の値 )
%d + %d = %d <= 書式指定 ( printf の最初の引数 )
printf の二つ目以後は、
埋め込む整数型の値の指定 ia, ib, ia+ib
!! printf を使うと
!! 出力したい結果を念頭において、書式設定ができる
!! => 望みに近い形での出力が可能
*/
printf ( "%f / %f = %f\n", da, db, da / db ); /* 浮動小数点数の商 */
/* 結果
3.140000 / 1.590000 = 1.974843
*/
return 0;
}
#include <stdio.h>
/*
前期 : 「変数」の導入
関数の「引数」として導入
*/
/*
鈴木さんと、田中さんに、挨拶のメッセージ (printf で表示)を送る
*/
int main(void) {
printf ( "こんにちは、" );
printf ( "鈴木さん\n" );
printf ( "こんにちは、" );
printf ( "田中さん\n" );
return 0;
}
#include <stdio.h>
/*
前期 : 「変数」の導入
関数の「引数」として導入
*/
/*
鈴木さんと、田中さんに、挨拶のメッセージ (printf で表示)を送る
関数版
*/
/*
それぞれの人に挨拶をする関数を個別に作成
*/
/* 関数「suzuki」の定義 */
/*
{ ? } の内容に、「suzuki」という名前をつけた
「suzuki」という関数の本体(中身)が { ? }
*/
void suzuki (void) {
printf ( "こんにちは、" );
printf ( "鈴木さん\n" );
}
void tanaka (void) {
printf ( "こんにちは、" );
printf ( "田中さん\n" );
}
int main(void) {
suzuki(); /* 関数「suzuki」の呼び出し */
/* 関数「suzuki」の内容が実行される */
/* 「suzuki」という名前をつけた命令が実行される */
tanaka();
return 0;
}
#include <stdio.h>
/*
前期 : 「変数」の導入
関数の「引数」として導入
関数の「仮引数『変数』」
変数は、(実引数変数で指定する事により..)
色々な「値」を取りうる「物」である
(すくても、命令が実行される時[実行時]には)
その変数の値が、確定していないといけない
!! プログラムを作る時は、値が未定でよい
=> 実行時に変数の値を決める操作が必要
仮引数変数の場合は、
関数呼び出しの実引数を指定する事が、
それに相当する
*/
/*
鈴木さんと、田中さんに、挨拶のメッセージ (printf で表示)を送る
引数付き関数版(変数の導入)
*/
/*
それぞれの人に挨拶をする関数を個別に作成
*/
/*
二つの関数(suzuki, tanaka)の内容(本体)は、
よく似ている(違う部分があるために同じにならない)
=> 違う部分だけ、「変数化」(共通の変数名[表記]になるので)
=> 「同じ」にできてしまう
*/
void aisatu ( char *X ) {
printf ( "こんにちは、" );
printf ( X ); /* 異なる部分を「X」という変数にする */
}
/*
suzuki() <-> aisatsu で、かつ X が 「鈴木さん\n」の時
tanaka() <-> aisatsu で、かつ X が 「田中さん\n」の時
引数付き関数
似たような関数を変数を利用して、抽象化し、まとめる
*/
void suzuki (void) {
/*
printf ( "こんにちは、" );
printf ( "鈴木さん\n" );
*/
aisatu ( "鈴木さん\n" );
/* 関数 aisatsu を呼び出す時に、
引数変数 ( この例では変数 X )
に当てはまる値を指定する (実引数) */
}
void tanaka (void) {
/*
printf ( "こんにちは、" );
printf ( "田中さん\n" );
*/
aisatu ( "田中さん\n" );
}
int main(void) {
suzuki(); /* 関数「suzuki」の呼び出し */
/* 関数「suzuki」の内容が実行される */
/* 「suzuki」という名前をつけた命令が実行される */
tanaka();
aisatu ( "高橋さん\n" );
/* 引数付き関数を作成する事により、
様々な実引数に対して、処理をする事が可能になる */
return 0;
}
#include <stdio.h>
/*
前期 : 「変数」の導入
関数の「引数」として導入
関数の「仮引数『変数』」
*/
void aisatu ( char *X ) {
printf ( "こんにちは、" );
printf ( X ); /* 異なる部分を「X」という変数にする */
}
int main(void) {
aisatu ( "高橋さん\n" );
/*
aisatu("高橋さん\n")
<=>
X <- "高橋さん\n"
<= 変数 X に代入が行われている
printf ( "こんにちは、" );
printf ( X );
<=>
printf ( "こんにちは、" );
printf ( "高橋さん\n" );
=>
「こんにちは、高橋さん[改行]」が表示される
*/
return 0;
}
#include <stdio.h>
/*
前期 : 「変数」の導入
関数の「引数」として導入
関数の「仮引数『変数』」
*/
int main(void) {
char *X; /* 変数 X の宣言 */
/* 関数の仮引数変数宣言の代わり、
(auto 変数/局所変数)変数宣言が必要 */
/*
aisatu ( "高橋さん\n" );
関数をなくして、元に戻す
*/
/*
変数 X に「"高橋さん\n"」という値を代入したい
!! 関数呼び出しなら、実引数の指定
!! 新しい方法を紹介する
*/
X = "高橋さん\n"; /* 変数 X に対する代入操作 */
/* 「代入」には記号「=」を使うが、
これは、「等号(等しい)」(という意味)ではない
!! そもそも、逆にできない
!! 「"高橋さん\n" = X」は、意味が違う(この場合は、こうできない)
「代入」には方向性があって
左辺にある「変数」に右辺の式の値が「代入される」
cf.
Pascal 言語では、代入には「:=」を使う
X := "高橋さん\n";
*/
printf ( "こんにちは、" );
printf ( X );
/*
printf ( "こんにちは、" );
printf ( "高橋さん\n" );
*/
return 0;
}
#include <stdio.h>
/*
前期 : 「変数」の導入
関数の「引数」として導入
関数の「仮引数『変数』」
*/
int main(void) {
char *X; /* 変数 X の宣言 */
/* 変数 X には、(明示的な..)「値」はない */
/* !! 実際は、「ゴミ」が入っているので、
!! 最初の代入(変数の初期化)が行われるまでは、
!! その変数(の値)を参照(変数の値を問う[取り出す])してはいけない */
X = "高橋さん\n";
/* 変数 X の値は(直前の代入の結果)「"高橋さん\n"」になっている */
printf ( "こんにちは、" );
printf ( X ); /* 変数 X の値が参照されて、「"高橋さん\n"」が値として利用される */
/* 参照されても、変数の値は変更されない */
/* => 必要ならば、何度でも、同じ(変数を利用して)値を取り出す事ができる */
printf ( "こんにちは、" );
printf ( X ); /* 変数 X の値がもう一度参照され、同じが使われる */
/* 変数を利用するメリット
=> 変数に、同じ値を代入しておくことにより、
同じ値を何度でも利用できる
!! 変数に、「計算した結果」を代入する事により、
!! 同じ値の計算を、二度としなくても済む
!! => 効率化
!! !! 昔の計算機は、遅かった
!! !! => できるだけ無駄を省く
!! !! => 代入が基本操作
!! !! !! 効率的なアルゴリズムのいくつかは
!! !! !! => もともとの(定義にあった)計算の中から、(代入等を利用して..)無駄を省く事により効率化している
*/
X = "鈴木さん\n"; /* 変数 X に再度代入が行われる */
/* 変数 X がもっていた前の値(「高杯さん\n」)は、失われる */
/* => 変数 X を利用して、その値を取りだす事ができない */
/* 「上書き」がおきる */
printf ( "こんにちは、" );
printf ( X );
X = "田中さん\n";
printf ( "こんにちは、" );
printf ( X );
return 0;
}
#include <stdio.h>
int main(void) {
printf ( "単純に文字列をそのまま出力する\n" );
/* これまでの printf の使い方 */
/* 新しい使い方
最初の引数は、「書式指定」を含む文字列で、
実際に出力したい値は、その後に続く引数で指定をする */
printf ( "%s", "abc\n" ); /* %s : 文字列を出力する書式 */
/* ^^^ ^^^^^^
↑ |
+--------+ 書式指定の場所に、後の引数の値が埋め込まれる
*/
/* 画面に「abc[改行]」が表示される */
/* printf の書式指定は、「%」から始まる文字列で行う */
printf ( "(%s)", "abc\n" ); /* %s : 文字列を出力する書式 */
/* %s のところだけが、"abc\n" */
/* => (abc\n) に変化する */
printf ( "\n" );
printf ( "(%s)\n", "abc" ); /* %s : 文字列を出力する書式 */
/* %s のところだけが、"abc" */
/* => (abc)\n に変化する */
printf ( "(%d)\n", 123+456 ); /* %d : 整数値を出力する書式 */
printf ( "(%f)\n", 1.23 * 4.56 ); /* %f : 浮動小数点数を出力する書式 */
return 0;
}
#include <stdio.h>
int main(void) {
int a=123;
double b=1.23;
printf ( "int a=%d, double b=%f\n", a, b );
/* ^^ ^^ | |
| | | |
+------------|-----+ |
+--------+
*/
return 0;
}
前回の内容
前回の内容
ガイダンス : 基本は、前期と同じ / ただし、前期の知識を仮定する
目的 : 「C 言語でプログラムが書けるようになる」事
三つの内容 : プログラミング / 操作方法 / C 言語
方針 : 同じ内容を 3 度、繰返しながら、少しずつ内容を深く進める
復習
1 周回 : hello world, 関数, 制御構造(順接,条件分岐,再帰)
原理的に可能なプログラムは一通りかける
2 周目 : 様々なデータ構造 ( char, int )
まだ、途中 : 早めに終らせて、3 周回のアプリ開発に行きたい
代入
代入とは
概念 : 「変数」に「値」を「割り当て」る「操作」
「変数」
関数の引数変数として導入
色々値を持ちうるもの
プログラム作成時は、値がきまってなくてもよいが
実行時には、値が決まっている必要がある
=> 「値を決める」という作業
=> 「値」を「割り当てる」
例:
仮引数変数の場合は、
実引数(これが割り当てる変数の値)が相当する
=>
実引数を指定(して、関数を呼び出しを)する事は、
仮引数変数への代入
「=」を利用した代入の話
代入「後」は、その変数の値は、代入さ(割り当てら)れた値に「変化」する
1 限の内容
a. 「代入」という言葉
b. 「代入」の仕組み => 関数引数と同じ働き
c. 「代入」を C 言語で(関数呼び出しを使わず、直接)実行する方法
代入文 ( 「=」を利用した、代入の表現 )
(代入文の左辺に現れる変数を利用するための..) 変数宣言
=> 関数の仮引数変数と同じ
表 : 代入文と関数呼び出しの比較
代入の対象 代入元 タイミング 回数 影響範囲
代入文 局所変数 代入文の右辺の式 いつでも 何度でも 次の代入まで
関数呼び出し 仮引数変数 実引数 関数呼び出し時 一回 関数(呼び出し)内
代入を行うと
(その変数が保持していた..) 代入「前」の値は、「失われ」る
代入の「前」と「後」という「時間」の概念の把握が必要となる
!! 数学には「時間の概念がない」
表現 : 代入の構文
「変数名」=「式」 [例] a=1+2; (変数 a に 3 ( = 1+2 ) を代入)
=> 代入文は、「式の『計算』要求」にもなっている
=> 代入文を並べる事により、
「計算を進める」事にもなっている
手続き型言語 ( 代入文を中心にプログラムを書く事を想定した言語 )
「=」は、「代入」を表現する(等号[等しい]ではない!! / 等号は「==」)
局所変数宣言
概念 : 局所変数を宣言する
cf. 関数の仮引数変数は、関数の定義時に、仮引数部でおこなっている
関数の本体 ( { ? } : ブロック ) の先頭でやる
# C 言語の制約のひとつ / C++ などは、先頭に限定しない..
=>
プログラミング時は、変数の型を指定し、
変数に代入可能な値の制限を行う
実行時は、変数の値を収める領域を準備する命令になる
関数(ブロック)内のみ(局所的)で有効(利用可能)な変数を宣言する
「仮引数変数(実は局所変数の一種)」以外にも、変数が増やせる
!! 仮引数変数も代入文をつかって、値が変更できる
表現 : 局所変数の宣言
「変数の型名」「変数名」 [例] int a; (整数型の変数 a を宣言)
cf. 仮引数変数は、実引数の値で、「代入済」の変数
-> 局所変数は宣言をした段階では、「ゴミ」が入っている
未代入の変数の値は「未定(プログラムミスの代表例 !!)」
変数は宣言と同時に「初期化(最初の代入)」できる(すべき) [例] int a=1;
!! 最初に何をいれるべきかがわからない場合がある
!! 変数を使いたい場所と、宣言をする場所が離れているから
!! その場合は、「固定」な値を無条件に設定する
!! 例 : int 0/char '\0'/char * ""
課題 : 20210917-02
=> 後回し
標準 I/O ライブラリの利用
標準 I/O ライブラリ ( stdio )
I/O とは Input(入力) と Output(出力) の事
Input : プログラムが、プログラムの外から、情報を読み込む(Read)
Output : プログラムが、プログラムの外へ、情報を書き出す(Write)
[ポイント] 「外」はプログラムの置かれている環境で異る (i.e OS)
例 : 「あいさつ」をするとき日本とアメリカで異るの嫌(だから全て英語で.. それも困るが..)
環境の違いを吸収して、
プログラムは同じだが、実行結果は、
その環境において、適切に変化するようにする仕組みが欲しい
その「仕組み」が標準ライブラリ
=> 標準ライブラリを利用すれば、
環境の違いを意識せずに、同じプログラムで(同じ機能を実現)できる
標準 I/O ライブラリの役割
異る環境でも、プログラムとしては、同じ方法で I/O を行うための仕組
環境の違いはライブラリが吸収 (挨拶は手を振るで OK)
標準 I/O ライブラリの機能
I/O する物 : 文字、文字列、数値(基本データ)
I/O の相手先 : キーボード(I), ディスプレイ(O),ファイル(I/O)
printf
printf : 超高機能出力関数
print with format (書式付き出力)
単なる文字列出力関数ではなかった
cf.
printf ( "Hello, World\n" );
=> 引数で指定された「文字列」を出力する
「書式('%' + 書式指示)」を指定する事により何(基本型+文字列)が出力できる
printf ( 書式指定(の文字列) + 色々な型の値 );
=> 基本型であれば、どんな型の値でも出力可能
!! printf の関数の引数には、
!! 色々な型の値を指定する事ができる
!! !! 関数の実引数は、仮引数変数の型と同じ型の値と指定する
!! !! => 関数の引数の型は、いつも同じ
!! なぜ、このような(変な)事ができるかは..
!! この講義の最後あたりで、説明したい..
!! いまはしない..
printf ( "%d", 123 ); / printf ( "%f", 1.23 ); / printf ( "%c", 'a' ); / printf ( "%s", "abc" );
文字列の中に出力(色々な値)を「埋め込む」事ができる
int a=123; printf ( "int a=%d\n", a );
複数のデータを一度に出力する事ができる
int a=123; double b=1.23; printf ( "int a=%d, double b=%f\n", a, b );
非常に高機能
printf の動作原理
後でちゃんと話すので、今回は我慢 !!
課題プログラム内の「/*名前:ここ*/」の部分を書き換え「/*この部分を完成させなさい*/」の部分にプログラムを追加して、プログラムを完成させます。
Download : 20210924-01.c
/*
* 20210924-01-QQQQ.c
*
* コンパイル :
* cc -c 20210924-01-QQQQ.c
* cc -o 20210924-01-QQQQ.exe 20210924-01-QQQQ.o
* 実行 :
* ./20210924-01-QQQQ.exe
*/
#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;
}
$ ./20210924-01-QQQQ.exe 1 から 9 までの奇数の和は 25 です。 $
Download : 20210924-02.c
/*
* TITLE
*
* 20210924-02-QQQQ.c
*
* コンパイル :
* cc -c 20210924-02-QQQQ.c
* cc -o 20210924-02-QQQQ.exe 20210924-02-QQQQ.o
* 実行 :
* ./20210924-02-QQQQ.exe
*/
#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;
}
$ ./20210924-02-QQQQ.exe 1 から 9 までの奇数の和は 25 です。 $
Download : 20210924-03.c
/*
* TITLE
*
* 20210924-03-QQQQ.c
*
* コンパイル :
* cc -c 20210924-03-QQQQ.c
* cc -o 20210924-03-QQQQ.exe 20210924-03-QQQQ.o
* 実行 :
* ./20210924-03-QQQQ.exe
*
* ファイルの中の数値の総和
*/
#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;
}
$ ./20210924-03-QQQQ.exe 総和は 258 です。 $