Download : sample-001.c
/*
* 2019/10/11 sample-001.c
*/
/*
* 型の違い
*
* 利用方法
* コンパイル
* cc -I ~/c/include -c sample-001.c
* リンク
* cc -o sample-001.exe sample-001.c
* 実行
* ./sample-001.exe
*/
#include <stdio.h>
#include "s_input.h"
#include "s_print.h"
/*
* main 関数
*/
int main ( void ) {
/*
* 型が違っても表示は同じ
*/
s_print_string ( "整数 : " );
s_print_int ( 9 );
s_print_newline();
s_print_string ( "文字 : " );
s_print_char ( '9' );
s_print_newline();
s_print_string ( "文字列 : " );
s_print_string ( "9" );
s_print_newline();
/*
* 整数の場合の +1
*/
s_print_string ( "整数の計算 : 9 + 1 = " );
s_print_int ( 9 + 1 );
s_print_newline();
/*
* 文字の場合の +1
*/
s_print_string ( "文字の計算 : '9' + 1 = " );
s_print_char ( '9' + 1 );
s_print_newline();
/*
* 文字列の場合の +1
*/
s_print_string ( "文字の計算 : \"9\" + 1 = " );
s_print_string ( "9" + 1 );
s_print_newline();
/*
* 型によって、計算結果が異る
*/
return 0;
}
$ ./sample-001.exe 整数 : 9 文字 : 9 文字列 : 9 整数の計算 : 9 + 1 = 10 文字の計算 : '9' + 1 = : 文字の計算 : "9" + 1 = $
Download : sample-002.c
/*
* 2019/10/11 sample-002.c
*/
/*
* 整数の四則計算式
*
* 利用方法
* コンパイル
* cc -I ~/c/include -c sample-002.c
* リンク
* cc -o sample-002.exe sample-002.c
* 実行
* ./sample-002.exe
*/
#include <stdio.h>
#include "s_input.h"
#include "s_print.h"
/*
* main 関数
*/
int main ( void ) {
/*
* 加法(足し算)
*/
s_print_string ( "12 + 5 = " );
s_print_int ( 12 + 5 ); /* 整数の 12 と 5 を加える */
s_print_newline();
/*
* 減法(引き算)
*/
s_print_string ( "12 - 5 = " );
s_print_int ( 12 - 5 ); /* 整数の 12 から 5 を引く */
s_print_newline();
/*
* 乗法(かけ算)
*/
s_print_string ( "12 * 5 = " );
s_print_int ( 12 * 5 ); /* 整数の 12 に 5 をかける */
s_print_newline();
/*
* 商法(割り算)
*/
s_print_string ( "12 / 5 = " );
s_print_int ( 12 / 5 ); /* 整数の 12 を 5 で割る */
s_print_newline();
/*
* 式の優先順位やかっこも利用可能
*/
s_print_string ( "1 + 2 * 3 = " );
s_print_int ( 1 + 2 * 3 ); /* かけ算が優先される */
s_print_newline();
s_print_string ( "(1 + 2) * 3 = " );
s_print_int ( (1 + 2) * 3 ); /* かっこの中の計算が優先される */
s_print_newline();
return 0;
}
$ ./sample-002.exe 12 + 5 = 17 12 - 5 = 7 12 * 5 = 60 12 / 5 = 2 1 + 2 * 3 = 7 (1 + 2) * 3 = 9 $
Download : sample-003.c
/*
* 2019/10/11 sample-003.c
*/
/*
* 文字列の演算式
*
* 利用方法
* コンパイル
* cc -I ~/c/include -c sample-003.c
* リンク
* cc -o sample-003.exe sample-003.c
* 実行
* ./sample-003.exe
*/
#include <stdio.h>
#include "s_input.h"
#include "s_print.h"
/*
* main 関数
*/
int main ( void ) {
/*
* 文字列への加法
*/
s_print_string ( "\"abc\" + 1 = " );
s_print_string ( "abc" + 1 ); /* 文字列が短くなる */
s_print_newline();
/*
* 先頭の文字の取出し
*/
s_print_string ( "*\"abc\" = " );
s_print_char ( *"abc" ); /* 先頭の文字が出て来る */
s_print_newline();
return 0;
}
$ ./sample-003.exe "abc" + 1 = bc *"abc" = a $
Download : sample-004.c
/*
* 2019/10/11 sample-004.c
*/
/*
* 関数呼出しを含む形の「式」
*
* 利用方法
* コンパイル
* cc -I ~/c/include -c sample-004.c
* リンク
* cc -o sample-004.exe sample-004.c
* 実行
* ./sample-004.exe
*/
#include <stdio.h>
#include "s_input.h"
#include "s_print.h"
/*
* main 関数
*/
int main ( void ) {
/*
* 加法(足し算)
*/
s_print_string ( "12 + 5 = " );
s_print_int ( 12 + 5 ); /* 整数の 12 と 5 を加える */
s_print_newline();
/*
* 減法(引き算)
*/
s_print_string ( "12 - 5 = " );
s_print_int ( 12 - 5 ); /* 整数の 12 から 5 を引く */
s_print_newline();
/*
* 乗法(かけ算)
*/
s_print_string ( "12 * 5 = " );
s_print_int ( 12 * 5 ); /* 整数の 12 に 5 をかける */
s_print_newline();
/*
* 商法(割り算)
*/
s_print_string ( "12 / 5 = " );
s_print_int ( 12 / 5 ); /* 整数の 12 を 5 で割る */
s_print_newline();
return 0;
}
$ ./sample-004.exe 12 + 5 = 17 12 - 5 = 7 12 * 5 = 60 12 / 5 = 2 $
Download : sample-005.c
/*
* 2019/10/11 sample-005.c
*/
/*
* 複数の正の整数の総和を計算する
*
* 利用方法
* コンパイル
* cc -I ~/c/include -c sample-005.c
* リンク
* cc -o sample-005.exe sample-005.c
* 実行
* ./sample-005.exe
*/
#include <stdio.h>
#include "s_print.h"
#include "s_input.h"
/*
正の整数をいくつかキーボードから入力し、
その総和を出力する
ただし、最後に、0 以下の数を入力する
入力は、関数を呼び出す前に行われ、引数に渡される
目的 : 入力(したデータ)を、
終了のためのチェック
加えるデータ
の二ヶ所で利用したい
入力したデータ二ヶ所で利用したいは関数に引数として
わたして、その引数変数を経由して利用するパターンを使う
(注意) 後で、「代入」を学ぶと、もっと簡単になる
引数 :
int pre_input
関数を呼び出すまえに入力されたデータ
int total
これまで、入力されたデータの総和が入っている
入力の例
1 2 3 4 -1
-> 結果の総和として 10 が表示される
*/
void input_sum ( int pre_input, int total ) {
if ( pre_input <= 0 ) { /* 加えるデータはもうない */
/* お仕舞いなので.. */
s_print_string ( "総和は " );
s_print_int ( total );
s_print_string ( " です。\n" );
} else { /* 入力が正なので、まだやる可能性がある */
input_sum ( s_input_int(), total + pre_input );
/*
total にはこれまでの和
pre_input には、今回の入力
なので
ここまでの総和は
total + pre_input
になる
*/
}
}
int main(void) {
input_sum( s_input_int(), 0 );
return 0;
}
12 83 40 58 42 0
$ ./sample-005.exe < sample-005.in 12 83 40 58 42 0 総和は 235 です。 $
Download : sample-006.c
/*
* 2019/10/11 sample-006.c
*/
/*
* rand 関数の利用例
*
* 利用方法
* コンパイル
* cc -I ~/c/include -c sample-006.c
* リンク
* cc -o sample-006.exe sample-006.c
* 実行
* ./sample-006.exe
*/
#include <stdio.h>
#include "s_print.h"
void print_n_random ( int n ) {
if ( n <= 0 ) {
} else {
/* ここから */
s_print_int ( rand() );
s_print_char ( '\n' );
/* ここまでが、 n 回繰り返される */
print_n_random ( n - 1 );
}
}
int main(void) {
print_n_random ( 10 ); /* 10 個の乱数を出力 */
return 0;
}
$ ./sample-006.exe 1804289383 846930886 1681692777 1714636915 1957747793 424238335 719885386 1649760492 596516649 1189641421 $
Download : sample-007.c
/*
* 2019/10/11 sample-007.c
*/
/*
* srand による乱数系列の変更
*
* 利用方法
* コンパイル
* cc -I ~/c/include -c sample-007.c
* リンク
* cc -o sample-007.exe sample-007.c
* 実行
* ./sample-007.exe
*/
#include <stdio.h>
#include "s_print.h"
#include "s_input.h"
int main(void) {
s_print_string ( "乱数の seed(種) を入力してください : " );
srand(s_input_int()); /* キーボードから seed を入力 */
s_print_string ( "1回目 : " );
s_print_int ( rand() );
s_print_char ( '\n' );
s_print_string ( "2回目 : " );
s_print_int ( rand() );
s_print_char ( '\n' );
s_print_string ( "3回目 : " );
s_print_int ( rand() );
s_print_char ( '\n' );
return 0;
}
1234
$ ./sample-007.exe < sample-007.in 乱数の seed(種) を入力してください : 1234 1回目 : 479142414 2回目 : 465566339 3回目 : 961126155 $
Download : sample-008.c
/*
* 2019/10/11 sample-008.c
*/
/*
* 時刻による乱数系列の選択
*
* 利用方法
* コンパイル
* cc -I ~/c/include -c sample-008.c
* リンク
* cc -o sample-008.exe sample-008.c
* 実行
* ./sample-008.exe
*/
#include <stdio.h>
#include "s_print.h"
#include "s_input.h"
int main(void) {
srand(time(NULL)); /* プログラムの実行開始時間を種にする */
//srand(0); /* プログラムをチェックする時は乱数列を固定 */
s_print_string ( "1回目 : " );
s_print_int ( rand() );
s_print_char ( '\n' );
s_print_string ( "2回目 : " );
s_print_int ( rand() );
s_print_char ( '\n' );
s_print_string ( "3回目 : " );
s_print_int ( rand() );
s_print_char ( '\n' );
return 0;
}
$ ./sample-008.exe 1回目 : 1123889825 2回目 : 2146878529 3回目 : 161066507 $
Download : sample-009.c
/*
* 2019/10/11 sample-009.c
*/
/*
* 数当てゲーム
*
* 利用方法
* コンパイル
* cc -I ~/c/include -c sample-009.c
* リンク
* cc -o sample-009.exe sample-009.c
* 実行
* ./sample-009.exe
*/
#include <stdio.h>
#include "s_input.h"
#include "s_print.h"
#include "s_random.h" /* s_random.h を利用してみる */
/*
s_random.h によって、次の関数が利用可能になる
s_random() rand() と同じ、整数の乱数を返す
s_init_random() 時刻を利用して、乱数系列を変更
s_n_random(N) 0 〜 (N-1) の間の整数の乱数を返す
s_random_a_b(A,B) A 〜 B の間の整数の乱数を返す
s_coin() 0(裏) or 1(表) のどちらかを返す
s_dice() 1 〜 6 の間の整数の乱数を返す
*/
/*
プログラムが考えた数 ( 1 〜 100 の乱数 ) を
人間が、予想して、当てるというゲームプログラム
入力する個数は、当るまでなので、何度も入力する必要がある
-> input loop を使う
問題を作るのに乱数を利用する
*/
void game( int input, int question ) {
if ( input == question ) { /* 予想が当っている */
s_print_string ( "おめでとう、ございます。当たりです\n" );
} else {
if ( input > question ) {
s_print_string ( "大きすぎます。\n" );
} else {
s_print_string ( "ちいさすぎます。\n" );
}
s_print_string ( "もう一度予想してください : " );
game( s_input_int(), question );
}
}
/*
* main
*/
int main(int argc, char *argv[]) {
s_init_random(); /* 現在の時刻を利用して乱数を初期化*/
/* 毎回異る問題になる */
s_print_string ( "コンピュータが考えた 1 〜 100 の数を予想して入力してください : " );
game ( s_input_int(), s_random_a_b(1,100) );
}
コンピュータが考えた 1 〜 100 の数を予想して入力してください : 40 40 ちいさすぎます。 もう一度予想してください : 60 60 ちいさすぎます。 もう一度予想してください : 80 80 大きすぎます。 もう一度予想してください : 70 70 大きすぎます。 もう一度予想してください : 65 65 ちいさすぎます。 もう一度予想してください : 68 68 大きすぎます。 もう一度予想してください : 67 67 大きすぎます。 もう一度予想してください : 66 66 おめでとう、ございます。当たりです
Download : sample-010.c
/*
* 2019/10/11 sample-010.c
*/
/*
* 数当て(逆)
*
* 利用方法
* コンパイル
* cc -I ~/c/include -c sample-010.c
* リンク
* cc -o sample-010.exe sample-010.c
* 実行
* ./sample-010.exe
*/
#include <stdio.h>
#include "s_input.h"
#include "s_print.h"
/*
sample-009.c とは逆に、
人間が数を考え、
コンピュータが当てる
*/
/*
考えかた
答えが、区間 [a,b] の中にあるとして、
答の案として x = (a+b)/2 を言う
もし、x が大きい場合は、答えは
区間 [a,x-1] の中にある
逆に、そうでない場合は
区間 [x+1,b] の中にある
にある事がわかる
これをヒントに考える
ルール
コンピュータの予想が正しい時は 0
コンピュータの予想が大きいときは 1
コンピュータの予想が小さいときは 2
を答える
*/
void game ( int ans, int a, int b, int x ) {
if ( ans == 0 ) { /* 当たり */
s_print_string ( "やっぱり " );
s_print_int ( x );
s_print_string ( " でしたか.. 当って嬉しいです\n" );
} else {
if ( ans == 1 ) { /* 予想が大きい */
/* 答えは、区間 [a, x-1] にある.. */
s_print_string ( "私の予想は " );
s_print_int ( (a+(x-1))/2 );
s_print_string ( " です。いかがでしょうか : " );
game(s_input_int(), a, x-1, (a+(x-1))/2 );
} else { /* ans == 2 のはず.. 予想が小さい */
/* 答えは、区間 [x+1,b] にある.. */
s_print_string ( "私の予想は " );
s_print_int ( ((x+1)+b)/2 );
s_print_string ( " です。いかがでしょうか : " );
game(s_input_int(), x+1, b, ((x+1)+b)/2 );
}
}
}
int main(void) {
s_print_string ( "1 〜 100 数を考えてください\n" );
s_print_string ( "私が、その数を予想します\n" );
s_print_string ( "私の予想は 50 です。いかがでしょうか : " );
game ( s_input_int(), 1, 100, 50 );
}
1 2 1 0
$ ./sample-010.exe < sample-010.in 1 〜 100 数を考えてください 私が、その数を予想します 私の予想は 50 です。いかがでしょうか : 1 私の予想は 25 です。いかがでしょうか : 2 私の予想は 37 です。いかがでしょうか : 1 私の予想は 31 です。いかがでしょうか : 0 やっぱり 31 でしたか.. 当って嬉しいです $
Download : sample-011.c
/*
* 2019/10/11 sample-011.c
*/
/*
* 2 のべき乗を順に n 個出力する
*
* 利用方法
* コンパイル
* cc -I ~/c/include -c sample-011.c
* リンク
* cc -o sample-011.exe sample-011.c
* 実行
* ./sample-011.exe
*/
#include <stdio.h>
#include "s_print.h"
#include "s_input.h"
/*
2 のべき乗を順に n 個出力する
*/
void power ( int n, int b ) {
if ( n <= 0 ) {
} else {
s_print_int ( b );
s_print_char ( '\n' );
power ( n - 1, b * 2 );
}
}
/*
* main
*/
int main( int argc, char *argv[] ) {
power ( s_input_int(), 2 );
return 0;
}
10
$ ./sample-011.exe < sample-011.in 10 2 4 8 16 32 64 128 256 512 1024 $
Download : sample-012.c
/*
* 2019/10/11 sample-012.c
*/
/*
* 浮動小数点数の出力
*
* 利用方法
* コンパイル
* cc -I ~/c/include -c sample-012.c
* リンク
* cc -o sample-012.exe sample-012.c
* 実行
* ./sample-012.exe
*/
#include <stdio.h>
#include "s_input.h"
#include "s_print.h"
int main(void) {
s_print_double ( 1.234 ); /* 小数点を含む数が扱える */
s_print_char ( '\n' );
return 0;
}
$ ./sample-012.exe 1.234000 $
Download : sample-013.c
/*
* 2019/10/11 sample-013.c
*/
/*
* 浮動小数点数の入力
*
* 利用方法
* コンパイル
* cc -I ~/c/include -c sample-013.c
* リンク
* cc -o sample-013.exe sample-013.c
* 実行
* ./sample-013.exe
*/
#include <stdio.h>
#include "s_input.h"
#include "s_print.h"
int main(void) {
s_print_double ( s_input_double() );
/* 小数点を含む数を入力して、そのまま出力 */
/* 整数の時には s_print_int ( s_input_int() ); だった */
s_print_char ( '\n' );
return 0;
}
12.34
$ ./sample-013.exe < sample-013.in 12.340000 12.340000 $
Download : sample-014.c
/*
* 2019/10/11 sample-014.c
*/
/*
* 浮動小数点数の計算
*
* 利用方法
* コンパイル
* cc -I ~/c/include -c sample-014.c
* リンク
* cc -o sample-014.exe sample-014.c
* 実行
* ./sample-014.exe
*/
#include <stdio.h>
#include "s_input.h"
#include "s_print.h"
/*
* main
*/
int main( int argc, char *argv[] ) {
s_print_double ( s_input_double() * 1.08 );
/* 小数点を含む数を入力して、消費税込みの値段に.. */
s_print_char ( '\n' );
return 0;
}
123
$ ./sample-014.exe < sample-014.in 123.000000 132.840000 $
Download : sample-015.c
/*
* 2019/10/11 sample-015.c
*/
/*
* s_random.h の利用
*
* 利用方法
* コンパイル
* cc -I ~/c/include -c sample-015.c
* リンク
* cc -o sample-015.exe sample-015.c
* 実行
* ./sample-015.exe
*/
#include <stdio.h>
#include "s_print.h"
#include "s_input.h"
#include "s_random.h"
/*
s_random.h によって、次の関数が利用可能になる
s_random() rand() と同じ、整数の乱数を返す
s_init_random() 時刻を利用して、乱数系列を変更
s_n_random(N) 0 〜 (N-1) の間の整数の乱数を返す
s_random_a_b(A,B) A 〜 B の間の整数の乱数を返す
s_coin() 0(裏) or 1(表) のどちらかを返す
s_dice() 1 〜 6 の間の整数の乱数を返す
*/
/*
* main
*/
int main(int argc, char *argv[]) {
s_init_random(); /* 時計を使って、乱数列を初期化 */
s_print_string ( "1回目 : " );
s_print_int ( s_dice() ); /* サイコロの結果 */
s_print_char ( '\n' );
s_print_string ( "2回目 : " );
s_print_int ( s_dice() );
s_print_char ( '\n' );
s_print_string ( "3回目 : " );
s_print_int ( s_dice() );
s_print_char ( '\n' );
return 0;
}
$ ./sample-015.exe 1回目 : 2 2回目 : 1 3回目 : 4 $
/*
* 課題 CNAME-02
*
* 20190927 20190927-02-QQQQ.c
*
* 0 〜 99 の偶数を出力する
*
*/
#include <stdio.h>
/*
* for 文を利用して、0 から 99 の偶数の数値
(そのニ) i が 0 〜 99 の間の偶数だけを動くようにし、毎回 i を出す
*/
int main(int ac, char *av[] ) {
int i; /* for 文の制御変数 */
for ( i = 0; i < 100; i = i + 2 ) { /* i++ -> i = i + 1 (1 ずつ増える) */
/* i = i + 2 (2 ずつ増える) */
/* i++ だと i = 0, 1, 2, .. */
/* ○○とすれば i = 0, 2, 4, .. */
printf ( "%d\n", i ); /* i を出力 */
}
return 0;
}
/*
* 20191011-01-QQQQ.c
*
* 二つの整数値をキーボードから入力し、その四則並びに余りを出力する
*
* コンパイル :
* cc -I ~/c/include -c 20191011-01-QQQQ.c
* cc -o 20191011-01-QQQQ.exe 20191011-01-QQQQ.o
* 実行 :
* ./20191011-01-QQQQ.exe
*
*/
#include <stdio.h>
/*
* print_int_result
*/
void print_int_result ( char *name, int a, int b, char op, int value ) {
/*
print_int_result ( "和", 175, 51, '+', 175 + 51 );
*/
/* 「和 : 175 + 51 = 226」と出力したい */
printf ( "%s : ", name ); /* 「和 : 」を出力 */
/* 「175 + 51」 */
/* 175 <- a, 51 <- b, '+' <- op */
printf ( "%d %c %d", a, op, b );
printf ( " = %d\n", value ); /* 「 = 226」を出力 */
}
/*
* print_int_calc (四則+あまり)
*/
void print_int_calc ( int a, int b ) {
print_int_result ( "和", a, b, '+', a + b ); /* 和 */
print_int_result ( "差", a, b, '-', a - b ); /* 差 */
print_int_result ( "積", a, b, '*', a * b ); /* 積 */
/* ??? */ /* 商 */
print_int_result ( "余り", a, b, '%', a % b ); /* あまり */
}
/*
* main
*/
int main( int argc, char *argv[] )
{
int a; /* (入力した)二つの整数値を保持する変数 */
int b;
printf ( "一つ目の整数値を入力してください : " );
scanf ( "%d", &a );
/* 最初の引数は、書式 "%d" => 「%」で書式指定、「d」整数値(decimal) */
/* scanf は、キーボードから、「整数値を表現するような文字列」を入力し、
その文字列を、それが表現している整数値に変換する */
/* ^^^^^ */
/* 二つの引数が 「&a」 : 「&」:必要だが、説明しない+「a」:読みこんだ変数を指定している */
/* scanf は、キーボードから読み取り変換した整数値を、変数 a に代入する */
/* !! scanf は一種の代入文 */
printf ( "二つ目の整数値を入力してください : " );
/* ヒント : 二つ目は、変数 b に値を保持する.. */
scanf ( "%d", &b );
printf ( "入力された二つの数値は %d と %d です。\n", a, b );
print_int_calc ( a, b );
return 0;
}
/*
* 20191011-02-QQQQ.c
*
* 二つの浮動小数点数値をキーボードから入力し、その四則を出力する
*
* コンパイル :
* cc -I ~/c/include -c 20191011-02-QQQQ.c
* cc -o 20191011-02-QQQQ.exe 20191011-02-QQQQ.o
* 実行 :
* ./20191011-02-QQQQ.exe
*
*/
#include <stdio.h>
/*
* print_double_result
*/
void print_double_result ( char *name, double a, double b, char op, double value ) {
printf ( "%s : ", name );
printf ( "%f %c %f", a, op, b ); /* 「a op b」の出力をしたい */
/* 出力する値の型に合わせて、書式指定する */
printf ( " = %f\n", value );
}
/*
* print_double_calc
*/
void print_double_calc ( double a, double b ) {
print_double_result ( "和", a, b, '+', a + b ); /* 和 */
print_double_result ( "差", a, b, '-', a - b ); /* 差 */
/* ??? */ /* 積 */
/* ??? */ /* 商 */
/* 浮動小数点数では、「あまり」はない */
/* int 型同士の計算は int 型に、 double 型同士の計算は、double 型 */
}
/*
* main
*/
int main( int argc, char *argv[] )
{
double a; /* 二つの浮動小数点数値を保持する変数 */
double b; /* 整数の時には int => 浮動小数点数 double */
printf ( "一つ目の浮動小数点数値を入力してください : " );
scanf ( "%lf", &a ); /* double の入力の時は 「%lf」 !!! 「%f」ではない */
printf ( "二つ目の浮動小数点数値を入力してください : " );
scanf ( "%lf", &b );
print_double_calc ( a, b );
return 0;
}
#include <stdio.h>
/*
1 ? 10 の和計算する
*/
int main(int argc, char *argv[] ) {
int n; /* 1 ? 10 に変化する値を保持 */
int sum; /* (最終的に) 1 ? 10 の和を保持 : 途中では、1 ? n の値和を保持 */
sum=0; /* sum -> 0 ? 0 = 0 */
n=1; /* n -> 1 */
printf ( "n = %d, sum = %d\n", n, sum );
sum = sum + n; /* sum -> 0 + 1 -> 0 ? 1 -> 1 */
n = n + 1; /* n -> 2 */
printf ( "n = %d, sum = %d\n", n, sum );
sum = sum + n; /* sum -> 0 ? 1 + 2 -> 0 ? 2 -> 3 */
n = n + 1; /* n -> 3 */
printf ( "n = %d, sum = %d\n", n, sum );
sum = sum + n;
n = n + 1; /* n -> 4 */
printf ( "n = %d, sum = %d\n", n, sum );
sum = sum + n;
n = n + 1; /* n -> 5 */
printf ( "n = %d, sum = %d\n", n, sum );
sum = sum + n;
n = n + 1; /* n -> 6 */
printf ( "n = %d, sum = %d\n", n, sum );
sum = sum + n;
n = n + 1; /* n -> 7 */
printf ( "n = %d, sum = %d\n", n, sum );
sum = sum + n;
n = n + 1; /* n -> 8 */
printf ( "n = %d, sum = %d\n", n, sum );
sum = sum + n;
n = n + 1; /* n -> 9 */
printf ( "n = %d, sum = %d\n", n, sum );
sum = sum + n;
n = n + 1; /* n -> 10 */
printf ( "n = %d, sum = %d\n", n, sum );
sum = sum + n;
n = n + 1; /* n -> 11 */
printf ( "sum of 1 to 10 is %d\n", sum );
return 0;
}
#include <stdio.h>
/*
1 ? 10 の和計算する
*/
int main(int argc, char *argv[] ) {
int n; /* 1 ? 10 に変化する値を保持 */
int sum; /* (最終的に) 1 ? 10 の和を保持 : 途中では、1 ? n の値和を保持 */
sum=0; /* sum -> 0 ? 0 = 0 */
n=1; /* n -> 1 */
while ( n <= 10 ) { /* 繰り返しの条件 */
/* 繰り返す命令の部分を while 構文の「本体」として指定する */
printf ( "n = %d, sum = %d\n", n, sum );
sum = sum + n;
n = n + 1;
}
printf ( "n = %d\n", n );
printf ( "sum of 1 to 10 is %d\n", sum );
return 0;
}
#include <stdio.h>
int main(int argc, char *argv[]) {
double v; /* 浮動小数点数型の変数の宣言 */
printf ( "浮動小数点数を入力してください : " );
scanf ( "%lf", &v ); /* double 型の変数の入力の書式は %lf */
printf ( "入力させた値は %f です。\n", v );
/* 浮動小数点数の型の値の出力は %f */
/* !! 浮動小数点型には、double の他に float がある .. */
return 0;
}
#include <stdio.h>
int main(int argc, char *argv[]) {
double v;
printf ( "浮動小数点数を入力してください : " );
scanf ( "%lf", &v );
printf ( "入力させた値は %20f です。\n", v );
/* %f だと 10 桁で表示されるが %20f とする 20 桁になる */
return 0;
}
#include <stdio.h>
int main(int argc, char *argv[]) {
double v;
printf ( "浮動小数点数を入力してください : " );
scanf ( "%lf", &v );
printf ( "入力させた値は %20.10f です。\n", v );
/* %20.10f とすると小数点以下が 10 桁になる */
return 0;
}
#include <stdio.h>
int main(int argc, char *argv[]) {
double v;
printf ( "浮動小数点数を入力してください : " );
scanf ( "%lf", &v );
printf ( "入力させた値は %5.2f です。\n", v );
/* %5.2f : 小数点以下が 2 桁しか出力されない */
/* => 小数点第 3 位で、四捨五入される */
return 0;
}
#include <stdio.h>
#include <math.h> /* 浮動小数点数を扱う数学ライブラリの宣言 */
int main(int argc, char *argv[]) {
double a; /* 平方根を計算したい値 */
double xo;
double xn;
printf ( "平方根を計算したい値を入力してください : " );
scanf ( "%lf", & a );
xo = 0.0;
xn = 1.0; /* xo と違えば、なんでもよい */
while ( fabs(xn-xo) > 0.00001 ) { /* fabs : 浮動小数点数の絶対値の計算 */
xo = xn; /* その値で、元の変数を更新 */
xn = (-(xo * xo - a))/(2*xo) + xo; /* 次の値を計算 */
printf ( "xo = %f, xn = %f, xo-xn = %f\n", xo, xn, xo-xn );
}
printf ( "%f の平方根は %20.16f で、誤差は %20.18f\n", a, xn, a - xn * xn );
return 0;
}
#include <stdio.h>
/*
1 ? 10 の和計算する
*/
int main(int argc, char *argv[] ) {
int n; /* 1 ? 10 に変化する値を保持 */
int sum; /* (最終的に) 1 ? 10 の和を保持 : 途中では、1 ? n の値和を保持 */
sum=0; /* sum -> 0 ? 0 = 0 */
for ( n=1; n <= 10; n = n + 1 ) { /* 制御変数に関する記述が一か所にまとまっている */
/* n を 1 から 10 まで、 1 増やしながら... 繰り返す */
printf ( "n = %d, sum = %d\n", n, sum );
sum = sum + n;
}
/*
n=1;
while ( n <= 10 ) {
printf ( "n = %d, sum = %d\n", n, sum );
sum = sum + n;
n = n + 1;
}
*/
printf ( "n = %d\n", n );
printf ( "sum of 1 to 10 is %d\n", sum );
return 0;
}
/*
* 課題 CNAME-02
*
* 20190927 20190927-02-QQQQ.c
*
* 0 〜 99 の偶数を出力する
*
*/
#include <stdio.h>
/*
* for 文を利用して、0 から 99 の偶数の数値
(そのニ) i が 0 〜 99 の間の偶数だけを動くようにし、毎回 i を出す
*/
int main(int ac, char *av[] ) {
int i; /* for 文の制御変数 */
for ( i = 0; 2*i < 100 /* i < 100/2 */; i++ ) {
printf ( "%d\n", 2*i ); /* 2*i を出力 */
}
return 0;
}
[前回の内容]
「代入」:
変数に対して、値を指定する
1. 値を指定する「命令」なので、「実行する時期」を指定できる
cf. 関数の「仮引数変数」の値は、関数が呼び出され時点(自動[安全]/制御できない)
# 代入のし忘れ(初期値の未設定問題)がおきる可能性がある
2. 値の再設定が可能
cf. 「仮引数変数」の値(変更は可能だったが..)そうしてなかった
=> 特定な変数を含む命令は(その命令が同じなのに..)変数の値の変更(代入)によって、異なる振る舞いをする
変数の値の「更新」 : 右辺に左辺と同じ変数を含む代入
例:
i=1;
...
i = i + 1; <= もとの i の値に 1 を加えて、新しい i の値とする
=> i の値を 1 増やす
代入文を利用したプログラミング(手続き型言語によるプログラミング)
=> 現状(問題が解けていない状態)から解答(となる値を持つ変数がある状態)へ、
変数の値を更新して、近づけてゆく行為
# 人間が問題を解く、手順をたどる形で、プログラムが実行される
# => 「時間」の概念 ( 代入前と後 ) がある
# => 「自分の手できない事」は、「プログラムでも作れない」
## 数学の考え方は、代入文を不要としている(時間概念が不要)
## 例 : 再帰的関数定義 (関係を記述するだけで、手順を記述していない)
## => 普段の問題解決とアプローチが異なる(ので難しい)
## <= 数学の便利が出てくる
[while 構文]
「繰返し」を実現するもう一つの手段 ( cf. 再帰呼出し )
構文 : while ( <条件> ) { <繰返し命令> }
意味 : <条件> が成立する限り、<繰り返し命令>を繰り返す
while 構文の実行の流れは
<条件> <繰り返し命令> <条件> <繰り返し命令> .. <条件>
という流れ
制御変数(while の条件部分で参照され、本体で更新される変数)の更新が必須
cf. 再帰呼び出しの時も、引数の値が更新される事ポイント
=> 再帰呼び出しの場合は、関数の呼び出しの時に、制御変数の更新が(裏側で..)行わるので、
意図的に変更する必要はなかった
<= while 構文の場合は、制御変数を意識する必要がある
# 制御は一つとは限らないので注意
[scanf]
データをキーボードから入力し、変数に代入する関数
=> printf と対にして説明される
# printf は print with format
# format の部分にいろいろ指定ができる
# <= scanf も format を利用するので、大概、対で説明される
# !! 入力と出力なので、対称性を考えて、対にするのは理解できるが..
# !! => printf/scanf は、理解するのに必要な知識に差がありすぎる..
[注意]
scanf の 書式指定は、本当に入力する値の書式だけを指定する(ことが望ましい)
一つの scanf では、一つの変数への入力にする(ことが望ましい)
scanf で、値を入力し、代入する変数の前に「&」を忘れないように注意
[本日の内容]
[浮動小数点数(double 型)]
=> 「小数」で表現(小数点を含む数値)される数値を扱う
例:
123.456 => 123456 x 10^{-3}
0.00123456 => 123456 x 10^[-9]
123456000 => 123456 x 10^{3}
有効桁数 大きさ
!! 浮動小数点数の構造に関しては、重要だが、ソフトウェア概論では扱わない
<=
整数型は、小数点の位置が、いつも一の位に右に「固定」されている(ので「固定小数点数」と言えないこともない)
!! 「1」は整数値だが「1.」は浮動小数点数
浮動小数点数の出力に %f だと、小数点以下は、6 桁しかでず、7 桁以降は、表示されない
=> もし、7 桁以後も必要ならば、書式指定で、精度(桁数)を指定して、それが、きちんと、出力されるようにする
浮動小数点数では、「==」を使わない
!! 二つの(異なる形で計算された..)浮動小数点数が一致するのは稀なので、めったにおきない
a == b と同様な事をしたければ、
ε (小さな正の浮動小数点数.. 例えば 10^{-6} など ) を用意し
fabs( a - b ) < ε
の形チェックする ( a と b の差が、十分に小さい場合に、「等しい」とみなす )
<応用>
ある値に収束する数列を作り、その収束値を計算するプログラム
具体的な例として、与えらた数の平方根を計算するプログラム(ニュートン法)
=> p-007.c
[for 構文]
while 構文(や再帰)と同様、繰り返しを実現する構文
文法 : for ( <初期化式>; <条件式>; <再初期化式> ) { <繰り返し命令> }
意味 : ほぼ、次の while 構文と同じ
<初期化式>;
while ( <条件式> ) { <繰り返し命令> <再初期化式>; }
for 構文は、繰り返しにかかわる制御変数への操作を、一か所に、まとめて、
記述することが可能なので、わかりやすい。
特に 「for ( 変数 = a; 変数 =< b; 変数の更新 ) { .. }」は、
「変数の値が a ? b まで 値を更新しながら繰り返す」という「成句(イデオム)」として利用できる
例:
for ( i = 0; i < n; i++ ) { /* i++ ? i = i + 1 */
}
i を 0 ? n-1 まで 1 ずつ増やしながら、繰り返す
=> 繰り返す回数は n になる。
!! for 構文の三つ要素 ( <初期化式>; <条件式>; <再初期化式> ) は省略可
!! => <条件式> が空 (常に「真」として扱われる)
課題プログラム内の「/*名前:ここ*/」の部分を書き換え「/*この部分を完成させなさい*/」の部分にプログラムを追加して、プログラムを完成させます。
Download : 20191011-01.c
/*
* 20191011-01-QQQQ.c
*
* 二つの整数値をキーボードから入力し、その四則並びに余りを出力する
*
* コンパイル :
* cc -I ~/c/include -c 20191011-01-QQQQ.c
* cc -o 20191011-01-QQQQ.exe 20191011-01-QQQQ.o
* 実行 :
* ./20191011-01-QQQQ.exe
*
*/
#include <stdio.h>
/*
* print_int_result
*/
void print_int_result ( char *name, int a, int b, char op, int value ) {
printf ( "%s : ", name );
/*
** この部分を完成させなさい
*/
printf ( " = %d\n", value );
}
/*
* print_int_calc
*/
void print_int_calc ( int a, int b ) {
print_int_result ( "和", a, b, '+', a + b );
print_int_result ( "差", a, b, '-', a - b );
/*
** この部分を完成させなさい
*/
print_int_result ( "余り", a, b, '%', a % b );
}
/*
* main
*/
int main( int argc, char *argv[] )
{
int a; /* 二つの整数値を保持する変数 */
int b;
printf ( "一つ目の整数値を入力してください : " );
scanf ( "%d", &a );
printf ( "二つ目の整数値を入力してください : " );
/*
** この部分を完成させなさい
*/
print_int_calc ( a, b );
return 0;
}
175 51
$ ./20191011-01-QQQQ.exe 一つ目の整数値を入力してください : 175 二つ目の整数値を入力してください : 51 和 : 175 + 51 = 226 差 : 175 - 51 = 124 積 : 175 * 51 = 8925 商 : 175 / 51 = 3 余り : 175 % 51 = 22 $
Download : 20191011-02.c
/*
* 20191011-02-QQQQ.c
*
* 二つの浮動小数点数値をキーボードから入力し、その四則を出力する
*
* コンパイル :
* cc -I ~/c/include -c 20191011-02-QQQQ.c
* cc -o 20191011-02-QQQQ.exe 20191011-02-QQQQ.o
* 実行 :
* ./20191011-02-QQQQ.exe
*
*/
#include <stdio.h>
/*
* print_double_result
*/
void print_double_result ( char *name, double a, double b, char op, double value ) {
printf ( "%s : ", name );
/*
** この部分を完成させなさい
*/
printf ( " = %f\n", value );
}
/*
* print_double_calc
*/
void print_double_calc ( double a, double b ) {
print_double_result ( "和", a, b, '+', a + b );
print_double_result ( "差", a, b, '-', a - b );
/*
** この部分を完成させなさい
*/
}
/*
* main
*/
int main( int argc, char *argv[] )
{
double a; /* 二つの浮動小数点数値を保持する変数 */
double b;
printf ( "一つ目の浮動小数点数値を入力してください : " );
scanf ( "%lf", &a );
printf ( "二つ目の浮動小数点数値を入力してください : " );
/*
** この部分を完成させなさい
*/
print_double_calc ( a, b );
return 0;
}
123.456 789.012
$ ./20191011-02-QQQQ.exe 一つ目の浮動小数点数値を入力してください : 123.456000 二つ目の浮動小数点数値を入力してください : 789.012000 和 : 123.456000 + 789.012000 = 912.468000 差 : 123.456000 - 789.012000 = -665.556000 積 : 123.456000 * 789.012000 = 97408.265472 商 : 123.456000 / 789.012000 = 0.156469 $