Download : sample-001.c
/*
* CDATE sample-001.c
*/
/*
* 多次元配列
*
* 利用方法
* コンパイル
* cc -c sample-001.c
* リンク
* cc -o sample-001.exe sample-001.c
* 実行
* ./sample-001.exe
*/
#include <stdio.h>
/*
* main
*
*/
int main( int argc, char *argv[] )
{
int a[3][4]; /* 二次元配列の宣言 3 x 4 (= 12) 個の変数を宣言 */
/* int a00, a01, .., a03, a10, .., a13, .., a23; と同様 */
int i;
int j;
a[0][0] = 0; /* 添字は、二つ必要 ( 二次なので.. ) で、0 から始まる */
a[2][3] = 6; /* 添字の大きさは、配列の大きさ - 1 まで */
/* 0 〜 2 と 0 〜 3 のかけ算表を作ってみる */
for ( i = 0; i < 3; i++ ) {
for ( j = 0; j < 4; j++ ) {
a[i][j] = i * j; /* a[i][j] 成分の値が i*j になるようにする */
}
}
printf ( "2 * 1 = %d\n", a[2][1] ); /* 2 と表示される筈 */
if ( a[1][2] == a[2][1] ) { /* 1 * 2 = 2 * 1 か ? */
printf ( "1 * 2 = 2 * 1 が成立\n" );
} else {
printf ( "1 * 2 = 2 * 1 が成立しない.. 何か変だ..\n" );
}
/* 0 〜 2 と 0 〜 3 のかけ算表を画面に表示 */
printf ( " * |" );
for ( j = 0; j < 4; j++ ) {
printf ( "%2d", j );
}
printf ( "\n" );
printf ( "---+---------\n" );
for ( i = 0; i < 3; i++ ) {
printf ( " %1d |", i );
for ( j = 0; j < 4; j++ ) {
printf ( "%2d", a[i][j] );
}
printf ( "\n" );
}
return 0;
}
$ ./sample-001.exe 2 * 1 = 2 1 * 2 = 2 * 1 が成立 * | 0 1 2 3 ---+--------- 0 | 0 0 0 0 1 | 0 1 2 3 2 | 0 2 4 6 $
Download : sample-002.c
/*
* 2019/11/22 sample-002.c
*/
/*
* 集合の操作は操作の集合
*
* 利用方法
* コンパイル
* cc -c sample-002.c
* リンク
* cc -o sample-002.exe sample-002.c
* 実行
* ./sample-002.exe
*/
#include <stdio.h>
/*
* main
*
*/
#define ARRAY_SIZE 5 /* 配列のサイズを 5 とする */
int main( int argc, char *argv[] )
{
int a[ARRAY_SIZE]; /* ARRAY_SIZE の配列の宣言 */
int i;
for ( i = 0; i < ARRAY_SIZE; i++ ) {
a[i] = 2 * i; /* 一桁の偶数の表を作る */
/* a = { 0, 2, 4, 6, 8 } */
}
/* 偶数を出力 */
for ( i = 0; i < ARRAY_SIZE; i++ ) {
printf ( "%d ", a[i] );
}
printf ( "\n" );
/* 全ての要素に 1 を加えれば奇数の表になる */
/* { 0, 2, 4, 6, 8 } -> { 1, 3, 5, 7, 9 } */
for ( i = 0; i < ARRAY_SIZE; i++ ) {
a[i] = a[i] + 1;
}
/* 奇数を出力 */
for ( i = 0; i < ARRAY_SIZE; i++ ) {
printf ( "%d ", a[i] );
}
printf ( "\n" );
return 0;
}
$ ./sample-002.exe 0 2 4 6 8 1 3 5 7 9 $
Download : sample-003.c
/*
* 2019/11/22 sample-003.c
*/
/*
* 文字配列と文字列 (1)
*
* 利用方法
* コンパイル
* cc -c sample-003.c
* リンク
* cc -o sample-003.exe sample-003.c
* 実行
* ./sample-003.exe
*/
#include <stdio.h>
/*
* main
*
*/
#define CSIZE 10
#define EOS '\0' /* End Of String */
int main( int argc, char *argv[] )
{
char cary[CSIZE];
cary[0] = 'a';
cary[1] = 'b';
cary[2] = 'c';
cary[3] = EOS;
/*
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
cary|'a'|'b'|'c'|EOS| ? | ? | ? | ? | ? | ? |
*/
printf ( "普通に文字列 \"abc\" を出力してみる : %s\n", "abc" );
/* 文字列を出力する場合の書式は「%s」を利用する */
printf ( "文字列の代りに文字配列を出力してみる : %s\n", cary );
/* 文字列の代りに文字配列名が使える */
return 0;
}
$ ./sample-003.exe 普通に文字列 "abc" を出力してみる : abc 文字列の代りに文字配列を出力してみる : abc $
Download : sample-004.c
/*
* 2019/11/22 sample-004.c
*/
/*
* 文字配列と文字列 (2)
*
* 利用方法
* コンパイル
* cc -c sample-004.c
* リンク
* cc -o sample-004.exe sample-004.c
* 実行
* ./sample-004.exe
*/
#include <stdio.h>
/*
* main
*
*/
#define CSIZE 10
#define EOS '\0'
int main( int argc, char *argv[] )
{
char cary[CSIZE] = { 'a', 'b', 'c', 'd', 'e', EOS };
/* 配列も「初期化」可能 (全ての要素を指定する必要はない) */
/*
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
cary|'a'|'b'|'c'|'d'|'e'|EOS| ? | ? | ? | ? |
*/
int i;
int l;
/*
* 文字列と文字配列
*/
printf ( "最初の cary = %s\n", cary );
/*
* 文字の変更
*/
cary[2] = 'A'; /* 文字列の途中の文字を差し替える */
/*
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
cary|'a'|'b'|'A'|'d'|'e'|EOS| ? | ? | ? | ? |
*/
printf ( "文字列の途中の文字を変更すると cary = %s\n", cary );
/*
* 文字の尻尾を切断
*/
cary[3] = EOS; /* 文字列の後ろを切断 */
/*
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
cary|'a'|'b'|'A'|EOS|'e'|EOS| ? | ? | ? | ? |
*/
printf ( "文字列を途中で切ると cary = %s\n", cary );
/*
* 文字を尻尾に追加
*/
cary[3] = 'X';
cary[5] = 'Y';
cary[6] = 'Z';
cary[7] = EOS; /* 文字列の最後に EOS を忘れずに !! */
/*
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
cary|'a'|'b'|'A'|'X'|'e'|'Y'|'Z'|EOS| ? | ? |
*/
printf ( "文字列の後ろに文字を追加すると cary = %s\n", cary );
/*
* 文字配列の出力
*/
printf ( "printf を使わず、文字配列を文字列のように出力すると : " );
for ( i = 0; cary[i] != EOS; i++ ) {
putchar ( cary[i] );
}
printf ( "と、なります。\n" );
/* 文字列の長さを求める */
for ( l = 0; cary[l] != EOS; l++ ) {
/* やる事は何もない (l を増やす事が目的) */
}
/* cary の中の文字列の長さは、変数 l に入る */
printf ( "文字列 %d の長さは %d です。\n", cary, l );
/*
* 途中の文字を削除
*/
for ( i = 3; cary[i] != EOS; i++ ) {
cary[i] = cary[i+1];
}
/* 文字列の途中(4 文字目)の文字('X')を削除 */
/*
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
cary|'a'|'b'|'A'|'X'|'e'|'Y'|'Z'|EOS| ? | ? |
| | | / / / /
|'a'|'b'|'A'|'e'|'Y'|'Z'|EOS|EOS| ? | ? |
*/
printf ( "文字列の途中の文字を削除すると cary = %s\n", cary );
return 0;
}
$ ./sample-004.exe 最初の cary = abcde 文字列の途中の文字を変更すると cary = abAde 文字列を途中で切ると cary = abA 文字列の後ろに文字を追加すると cary = abAXeYZ printf を使わず、文字配列を文字列のように出力すると : abAXeYZと、なります。 文字列 -1045675920 の長さは 7 です。 文字列の途中の文字を削除すると cary = abAeYZ $
Download : sample-005.c
/*
* 2019/11/22 sample-005.c
*/
/*
* 配列の要素の参照
*
* 利用方法
* コンパイル
* cc -c sample-005.c
* リンク
* cc -o sample-005.exe sample-005.c
* 実行
* ./sample-005.exe
*/
#include <stdio.h>
/*
* main
*
*/
#define ARRAY_SIZE 10
int main( int argc, char *argv[] )
{
int iary[ARRAY_SIZE];
int i;
/* 配列の初期化 */
/* iary[i] = i*i */
for ( i = 0; i < ARRAY_SIZE; i++ ) {
iary[i] = i*i;
}
/*
これで、iary は i=0〜9 なら、関数 f(x)=x^2 と同じ振舞いをする
*/
/*
配列参照 : 普通の「添字参照」の場合
*/
for ( i = 0; i < ARRAY_SIZE; i++ ) {
printf ( "iary[%d]=%d\n", i, iary[i] );
}
/*
配列参照 : 「間接参照("*" の利用)」の場合
*(iary + i) == iary[i]
*/
for ( i = 0; i < ARRAY_SIZE; i++ ) {
printf ( "*(iary + %d)=%d\n", i, *(iary + i) );
}
/*
配列参照 : 配列名を使った計算 ( 添字を 1 からスタート )
(iary-1)[i] = *((iary - 1) + i) == *(iary + (i-1)) = iary[i-1]
*/
for ( i = 1; i <= ARRAY_SIZE; i++ ) {
printf ( "(iary-1)[i]=%d, iary[i-1]=%d\n", i, (iary-1)[i], i, iary[i-1] );
}
return 0;
}
$ ./sample-005.exe iary[0]=0 iary[1]=1 iary[2]=4 iary[3]=9 iary[4]=16 iary[5]=25 iary[6]=36 iary[7]=49 iary[8]=64 iary[9]=81 *(iary + 0)=0 *(iary + 1)=1 *(iary + 2)=4 *(iary + 3)=9 *(iary + 4)=16 *(iary + 5)=25 *(iary + 6)=36 *(iary + 7)=49 *(iary + 8)=64 *(iary + 9)=81 (iary-1)[i]=1, iary[i-1]=0 (iary-1)[i]=2, iary[i-1]=1 (iary-1)[i]=3, iary[i-1]=4 (iary-1)[i]=4, iary[i-1]=9 (iary-1)[i]=5, iary[i-1]=16 (iary-1)[i]=6, iary[i-1]=25 (iary-1)[i]=7, iary[i-1]=36 (iary-1)[i]=8, iary[i-1]=49 (iary-1)[i]=9, iary[i-1]=64 (iary-1)[i]=10, iary[i-1]=81 $
Download : sample-006.c
/*
* 2019/11/22 sample-006.c
*/
/*
* 配列名の関数への引渡し
*
* 利用方法
* コンパイル
* cc -c sample-006.c
* リンク
* cc -o sample-006.exe sample-006.c
* 実行
* ./sample-006.exe
*/
#include <stdio.h>
/*
* 配列サイズ
*/
#define ARRAY_SIZE 10
/*
* 引数に配列を持つ関数
*/
void print_array ( int a[ARRAY_SIZE] ) {
int i;
for ( i = 0; i < ARRAY_SIZE; i++ ) {
printf ( "a[%d]=%d, %d*%d = %d\n", i, a[i], i, i, i*i );
}
}
/*
* main
*
*/
int main( int argc, char *argv[] )
{
int iary[ARRAY_SIZE];
int i;
/* 配列の初期化 */
/* iary[i] = i*i */
for ( i = 0; i < ARRAY_SIZE; i++ ) {
iary[i] = i*i;
}
/*
これで、iary は i=0〜9 なら、関数 f(x)=x^2 と同じ振舞いをする
*/
print_array ( iary ); /* 関数の引数に「配列名」を指定できる */
return 0;
}
$ ./sample-006.exe a[0]=0, 0*0 = 0 a[1]=1, 1*1 = 1 a[2]=4, 2*2 = 4 a[3]=9, 3*3 = 9 a[4]=16, 4*4 = 16 a[5]=25, 5*5 = 25 a[6]=36, 6*6 = 36 a[7]=49, 7*7 = 49 a[8]=64, 8*8 = 64 a[9]=81, 9*9 = 81 $
Download : sample-007.c
/*
* 2019/11/22 sample-007.c
*/
/*
* 配列名の関数への引渡し(2)
*
* 利用方法
* コンパイル
* cc -c sample-007.c
* リンク
* cc -o sample-007.exe sample-007.c
* 実行
* ./sample-007.exe
*/
#include <stdio.h>
/*
* 配列サイズ
*/
#define I_ARRAY_SIZE 10
#define J_ARRAY_SIZE 5
/*
* 配列のサイズは、省略可能
* サイズの異る配列に対しても同じ関数が利用できる !!
*/
void print_n_array ( int a[], int size ) {
int i;
for ( i = 0; i < size; i++ ) {
printf ( "a[%d]=%d\n", i, a[i] );
}
}
/*
* main
*
*/
int main( int argc, char *argv[] )
{
int iary[I_ARRAY_SIZE];
int jary[J_ARRAY_SIZE];
int i;
/* 配列の初期化 */
/* iary[i] = i*i */
for ( i = 0; i < I_ARRAY_SIZE; i++ ) {
iary[i] = i*i;
}
/* jary[i] = i*i*i */
for ( i = 0; i < J_ARRAY_SIZE; i++ ) {
jary[i] = i*i*i;
}
printf ( "iary: 0 〜 %d\n", I_ARRAY_SIZE - 1 );
print_n_array ( iary, I_ARRAY_SIZE ); /* iary の内容を出力 */
printf ( "jary: 0 〜 %d\n", J_ARRAY_SIZE - 1 );
print_n_array ( jary, J_ARRAY_SIZE ); /* jary の内容を出力 */
/* 配列の一部の表示も可能 */
printf ( "iary: 0 〜 %d\n", J_ARRAY_SIZE - 1 );
print_n_array ( iary, J_ARRAY_SIZE );
/* 配列の途中からの表示も可能 */
printf ( "iary: %d 〜 %d\n", J_ARRAY_SIZE, I_ARRAY_SIZE - 1 );
print_n_array ( iary + J_ARRAY_SIZE, I_ARRAY_SIZE - J_ARRAY_SIZE );
return 0;
}
$ ./sample-007.exe iary: 0 〜 9 a[0]=0 a[1]=1 a[2]=4 a[3]=9 a[4]=16 a[5]=25 a[6]=36 a[7]=49 a[8]=64 a[9]=81 jary: 0 〜 4 a[0]=0 a[1]=1 a[2]=8 a[3]=27 a[4]=64 iary: 0 〜 4 a[0]=0 a[1]=1 a[2]=4 a[3]=9 a[4]=16 iary: 5 〜 9 a[0]=25 a[1]=36 a[2]=49 a[3]=64 a[4]=81 $
Download : sample-008.c
/*
* 2019/11/22 sample-008.c
*/
/*
* 配列名の関数への引渡し(3)
*
* 利用方法
* コンパイル
* cc -c sample-008.c
* リンク
* cc -o sample-008.exe sample-008.c
* 実行
* ./sample-008.exe
*/
#include <stdio.h>
/*
* 配列サイズ
*/
#define I_ARRAY_SIZE 10
/*
* 1 次元配列 (a[]) の仮引数変数宣言は、「*a」形の宣言でも良い
*/
void print_n_array ( int *a, int size ) {
int i;
for ( i = 0; i < size; i++ ) {
printf ( "a[%d]=%d\n", i, a[i] );
}
}
/*
* main
*
*/
int main( int argc, char *argv[] )
{
int iary[I_ARRAY_SIZE];
int i;
/* 配列の初期化 */
/* iary[i] = i*i */
for ( i = 0; i < I_ARRAY_SIZE; i++ ) {
iary[i] = i*i;
}
printf ( "iary: 0 〜 %d\n", I_ARRAY_SIZE - 1 );
print_n_array ( iary, I_ARRAY_SIZE ); /* iary の内容を出力 */
return 0;
}
$ ./sample-008.exe iary: 0 〜 9 a[0]=0 a[1]=1 a[2]=4 a[3]=9 a[4]=16 a[5]=25 a[6]=36 a[7]=49 a[8]=64 a[9]=81 $
Download : sample-009.c
/*
* 2019/11/22 sample-009.c
*/
/*
* 配列名の関数への引渡し(4)
*
* 利用方法
* コンパイル
* cc -c sample-009.c
* リンク
* cc -o sample-009.exe sample-009.c
* 実行
* ./sample-009.exe
*/
#include <stdio.h>
/*
* 配列サイズ
*/
#define I_ARRAY_SIZE 10
/*
* 1 次元配列 (a[]) の仮引数変数宣言は、「*a」形の宣言でも良い
*/
void print_n_array ( int *a, int size ) {
int i;
for ( i = 0; i < size; i++ ) {
printf ( "a[%d]=%d\n", i, a[i] );
}
}
/*
* 配列引数の要素の値を書き換える
*/
void change_at ( int *a, int pos, int value ) {
a[pos] = value;
}
/*
* main
*
*/
int main( int argc, char *argv[] )
{
int iary[I_ARRAY_SIZE];
int i;
/* 配列の初期化 */
/* iary[i] = i*i */
for ( i = 0; i < I_ARRAY_SIZE; i++ ) {
iary[i] = i*i;
}
printf ( "iary: 0 〜 %d\n", I_ARRAY_SIZE - 1 );
print_n_array ( iary, I_ARRAY_SIZE ); /* iary の内容を出力 */
printf ( "%d 番目の要素を %d に書き換える\n", 5, 100 );
change_at ( iary, 5, 100 );
printf ( "iary: 0 〜 %d\n", I_ARRAY_SIZE - 1 );
print_n_array ( iary, I_ARRAY_SIZE ); /* iary の内容を出力 */
return 0;
}
$ ./sample-009.exe iary: 0 〜 9 a[0]=0 a[1]=1 a[2]=4 a[3]=9 a[4]=16 a[5]=25 a[6]=36 a[7]=49 a[8]=64 a[9]=81 5 番目の要素を 100 に書き換える iary: 0 〜 9 a[0]=0 a[1]=1 a[2]=4 a[3]=9 a[4]=16 a[5]=100 a[6]=36 a[7]=49 a[8]=64 a[9]=81 $
Download : sample-011.c
/*
* 2019/11/22 sample-011.c
*/
/*
* 文字列の入力\n *\tscanf の「%s」で文字列を入力する事ができる
*
* 利用方法
* コンパイル
* cc -c sample-011.c
* リンク
* cc -o sample-011.exe sample-011.c
* 実行
* ./sample-011.exe
*/
#include <stdio.h>
/*
* main 関数
*/
#define LINE_SIZE 128 /* 入力する文字列より大きなサイズにする */
int main ( int argc, char *argv[] ) {
char line[LINE_SIZE]; /* 入力する文字列を収める文字型配列 */
printf ( "キーボードから、「空白(' ')を含んだ、適当な長さの文字列」と入力して Enter キーを押してください。: " );
scanf ( "%s", line ); /* 書式は「%s」で、文字型配列名を直接使う(&)は不要 */
printf ( "あなたが入力した文字列は「%s」です。\n", line );
/* 空白文字(空白/タブ/改行)があると、「文字列の区切」とみなされる */
return 0;
}
空白(' ')を含んだ、適当な長さの文字列
$ ./sample-011.exe < sample-011.in
キーボードから、「空白(' ')を含んだ、適当な長さの文字列」と入力して Enter キーを押してください。: 空白('
あなたが入力した文字列は「空白('」です。
$
Download : sample-012.c
/*
* 2019/11/22 sample-012.c
*/
/*
* 文字列の入力 (2)
* gets で文字列を入力する事ができる
*
* 利用方法
* コンパイル
* cc -c sample-012.c
* リンク
* cc -o sample-012.exe sample-012.c
* 実行
* ./sample-012.exe
*/
#include <stdio.h>
/*
* main 関数
*/
#define LINE_SIZE 128 /* 入力する文字列より大きなサイズにする */
int main ( int argc, char *argv[] ) {
char line[LINE_SIZE]; /* 入力する文字列を収める文字型配列 */
printf ( "キーボードから、「空白(' ')を含んだ、適当な長さの文字列」と入力して Enter キーを押してください。: " );
gets ( line );
/* gets では、「一行(改行の直前迄:改行含まず)」の文字列が入力される */
printf ( "あなたが入力した文字列は「%s」です。\n", line );
/* gets は一行(改行)までを入力する */
return 0;
}
空白(' ')を含んだ、適当な長さの文字列
$ ./sample-012.exe < sample-012.in
キーボードから、「空白(' ')を含んだ、適当な長さの文字列」と入力して Enter キーを押してください。: 空白(' ')を含んだ、適当な長さの文字列
あなたが入力した文字列は「空白(' ')を含んだ、適当な長さの文字列」です。
$
Download : sample-013.c
/*
* 2019/11/22 sample-013.c
*/
/*
* 文字列の入力 (3)\n *\tfgets で文字列を入力する事ができる
*
* 利用方法
* コンパイル
* cc -c sample-013.c
* リンク
* cc -o sample-013.exe sample-013.c
* 実行
* ./sample-013.exe
*/
#include <stdio.h>
/*
* main 関数
*/
#define LINE_SIZE 128 /* 入力する文字列より大きなサイズにする */
int main ( int argc, char *argv[] ) {
char line[LINE_SIZE]; /* 入力する文字列を収める文字型配列 */
printf ( "キーボードから、「空白(' ')を含んだ、適当な長さの文字列」と入力して Enter キーを押してください。: " );
fgets ( line, LINE_SIZE, stdin );
/* 入力先は、「標準入力 (stdin)」となる */
/* fgets では、文字列サイズが指定できる (安全) */
/* 指定したサイズより長い文字列は、入力が「待たされ」る */
printf ( "あなたが入力した文字列は「%s」です。\n", line );
/* 入力文字列内には、「改行」も含まれる */
return 0;
}
空白(' ')を含んだ、適当な長さの文字列
$ ./sample-013.exe < sample-013.in
キーボードから、「空白(' ')を含んだ、適当な長さの文字列」と入力して Enter キーを押してください。: 空白(' ')を含んだ、適当な長さの文字列
あなたが入力した文字列は「空白(' ')を含んだ、適当な長さの文字列
」です。
$
Download : sample-021.c
/*
* 2019/11/22 sample-021.c
*/
/*
* sizeof 演算子\n *\t型名を指定する事により、そのサイズ(byte 単位)を得る事ができる
*
* 利用方法
* コンパイル
* cc -c sample-021.c
* リンク
* cc -o sample-021.exe sample-021.c
* 実行
* ./sample-021.exe
*/
#include <stdio.h>
/*
* main 関数
*/
int main ( int argc, char *argv[] ) {
printf ( "sizeof ( char ) = %d\n", sizeof ( char ) );
printf ( "sizeof ( int ) = %d\n", sizeof ( int ) );
printf ( "sizeof ( double ) = %d\n", sizeof ( double ) );
return 0;
}
$ ./sample-021.exe sizeof ( char ) = 1 sizeof ( int ) = 4 sizeof ( double ) = 8 $
Download : sample-022.c
/*
* 2019/11/22 sample-022.c
*/
/*
* sizeof 演算子 (2)\n *\t変数名を指定する事により、そのサイズ(byte 単位)を得る事ができる
*
* 利用方法
* コンパイル
* cc -c sample-022.c
* リンク
* cc -o sample-022.exe sample-022.c
* 実行
* ./sample-022.exe
*/
#include <stdio.h>
/*
* main 関数
*/
int main ( int argc, char *argv[] ) {
char cvar;
int ivar;
double dvar;
printf ( "sizeof ( cvar ) = %d\n", sizeof ( cvar ) );
printf ( "sizeof ( ivar ) = %d\n", sizeof ( ivar ) );
printf ( "sizeof ( dvar ) = %d\n", sizeof ( dvar ) );
return 0;
}
$ ./sample-022.exe sizeof ( cvar ) = 1 sizeof ( ivar ) = 4 sizeof ( dvar ) = 8 $
Download : sample-023.c
/*
* 2019/11/22 sample-023.c
*/
/*
* sizeof 演算子 (3)\n *\t配列名を指定する事により、そのサイズ(byte 単位)を得る事ができる
*
* 利用方法
* コンパイル
* cc -c sample-023.c
* リンク
* cc -o sample-023.exe sample-023.c
* 実行
* ./sample-023.exe
*/
#include <stdio.h>
/*
* main 関数
*/
int main ( int argc, char *argv[] ) {
char cary[100];
int iary[100];
double dary[100];
printf ( "sizeof ( cary ) = %d\n", sizeof ( cary ) );
printf ( "sizeof ( iary ) = %d\n", sizeof ( iary ) );
printf ( "sizeof ( dary ) = %d\n", sizeof ( dary ) );
return 0;
}
$ ./sample-023.exe sizeof ( cary ) = 100 sizeof ( iary ) = 400 sizeof ( dary ) = 800 $
Download : sample-024.c
/*
* 2019/11/22 sample-024.c
*/
/*
* sizeof 演算子 (4)\n *\t値を指定する事もできる
*
* 利用方法
* コンパイル
* cc -c sample-024.c
* リンク
* cc -o sample-024.exe sample-024.c
* 実行
* ./sample-024.exe
*/
#include <stdio.h>
/*
* main 関数
*/
int main ( int argc, char *argv[] ) {
printf ( "sizeof ( 'a' ) = %d\n", sizeof ( 'a' ) );
/* sizeof ( int ) [整数] になっている */
printf ( "sizeof ( 123 ) = %d\n", sizeof ( 123 ) );
printf ( "sizeof ( 12.3 ) = %d\n", sizeof ( 12.3 ) );
return 0;
}
$ ./sample-024.exe sizeof ( 'a' ) = 4 sizeof ( 123 ) = 4 sizeof ( 12.3 ) = 8 $
Download : sample-025.c
/*
* 2019/11/22 sample-025.c
*/
/*
* sizeof 演算子 (5)\n *\t式のサイズも得られる\n *\tchar 型のデータは、計算の時に、int 型に昇格する
*
* 利用方法
* コンパイル
* cc -c sample-025.c
* リンク
* cc -o sample-025.exe sample-025.c
* 実行
* ./sample-025.exe
*/
#include <stdio.h>
/*
* main 関数
*/
int main ( int argc, char *argv[] ) {
char ch;
char dh;
printf ( "sizeof ( ch ) = %d\n", sizeof ( ch ) );
/* sizeof ( char ) [文字] になっている */
printf ( "sizeof ( ch + dh ) = %d\n", sizeof ( ch + dh ) );
/* sizeof ( int ) [整数] になっている */
/* 無条件の型の昇格がおきている */
return 0;
}
$ ./sample-025.exe sizeof ( ch ) = 1 sizeof ( ch + dh ) = 4 $
Download : sample-026.c
/*
* 2019/11/22 sample-026.c
*/
/*
* 型の昇格\n *\tint 型から double 型への変換
*
* 利用方法
* コンパイル
* cc -c sample-026.c
* リンク
* cc -o sample-026.exe sample-026.c
* 実行
* ./sample-026.exe
*/
#include <stdio.h>
/*
* main 関数
*/
int main ( int argc, char *argv[] ) {
int num;
int mum;
printf ( "sizeof ( num ) = %d\n", sizeof ( num ) );
printf ( "sizeof ( num + 'A' ) = %d\n", sizeof ( num + 'A' ) );
printf ( "sizeof ( num + mum ) = %d\n", sizeof ( num + mum ) );
printf ( "sizeof ( num + 1.0 ) = %d\n", sizeof ( num + 1.0 ) );
return 0;
}
$ ./sample-026.exe sizeof ( num ) = 4 sizeof ( num + 'A' ) = 4 sizeof ( num + mum ) = 4 sizeof ( num + 1.0 ) = 8 $
Download : sample-027.c
/*
* 2019/11/22 sample-027.c
*/
/*
* 型の変換\n *\t代入では、必要に応じて型変換が行わる
*
* 利用方法
* コンパイル
* cc -c sample-027.c
* リンク
* cc -o sample-027.exe sample-027.c
* 実行
* ./sample-027.exe
*/
#include <stdio.h>
/*
* main 関数
*/
int main ( int argc, char *argv[] ) {
char ch = 'A'; /* そもそも 'A' は int 型 */
int num = 'A';
double fp = 'A'; /* int 型から double 型へ */
ch = ch - 'A' + 'a'; /* int 型から char 型へ */
ch = num; /* int 型から char 型へ */
num = fp; /* double 型から int 型へ */
printf ( "ch = %c\n", ch );
printf ( "num = %d\n", num );
printf ( "fp = %f\n", fp );
return 0;
}
$ ./sample-027.exe ch = A num = 65 fp = 65.000000 $
Download : sample-028.c
/*
* 2019/11/22 sample-028.c
*/
/*
* 型の変換 (2)\n *\tサイズの大きい方から、小さい方への変換は危険
*
* 利用方法
* コンパイル
* cc -c sample-028.c
* リンク
* cc -o sample-028.exe sample-028.c
* 実行
* ./sample-028.exe
*/
#include <stdio.h>
/*
* main 関数
*/
int main ( int argc, char *argv[] ) {
char ch = 'A';
int num = 'A';
double fp = 'A';
/* 個々に適切な値を入れれば問題はない */
printf ( "[適切な値]\n" );
printf ( "\tch = '%c' [%d]\n", ch, ch );
printf ( "\tnum = %d\n", num );
printf ( "\tfp = %f\n", fp );
/* char 型に収まらないサイズの値を代入すると ?? */
num = 1000; /* 1000 > 255 なので、1000 は char 型に収まらない */
ch = num; /* 代入を行うとどうなるか */
printf ( "[char に大きな値]\n" );
printf ( "\tch = '%c' [%d]\n", ch, ch );
printf ( "\tnum = %d\n", num );
/* int 型に収まらないサイズの値を代入すると ?? */
fp = 1000000000000;
num = fp;
ch = fp;
printf ( "[int に大きな値]\n" );
printf ( "\tch = '%c' [%d]\n", ch, ch );
printf ( "\tnum = %d\n", num );
printf ( "\tfp = %f\n", fp );
return 0;
}
$ ./sample-028.exe [適切な値] ch = 'A' [65] num = 65 fp = 65.000000 [char に大きな値] ch = '?' [-24] num = 1000 [int に大きな値] ch = ' ' [0] num = -2147483648 fp = 1000000000000.000000 $
/*
* 課題 20191108-03
*
* 20191108 20191108-03-QQQQ.c
*
* 3 次元ベクトルの差の計算
* => 構造体を利用している
*
*/
#include <stdio.h>
/*
* 3 次元ベクトル
*/
typedef struct { /* 3 次元ベクトル */
double x; /* x 要素 */
double y; /* y 要素 */
double z; /* z 要素 */
} Vector3D; /* 新しい型 : Vector3D */
/*
* void print_Vector3D ( Vector3D v )
* ベクトルの内容を書き出す
* Vector3D v; 書き出すベクトル
*/
void print_Vector3D ( Vector3D v ) {
printf ( " %f\n", v.x ); /* v の x 要素の出力 */
printf ( "( %f )\n", v.y ); /* v の y 要素の出力 */
printf ( " %f\n", v.z ); /* v の z 要素の出力 */
/* TeX で表現するならば、
printf ( "\\left(\\begin{array}{c} %f \\\\ %f \\\ %f \\end{array}\\right)\n", v.x, v.y, v.z );
などととすればよい。
*/
}
/*
* Vector3D sub_Vector3D ( Vector3D dst, Vector3D src )
* 二つのベクトルの差を計算する
* Vector3D dst; 引かれるベクトル
* Vector3D src; 引くベクトル
* 帰り値 二つのベクトルの差となるベクトル
*/
Vector3D sub_Vector3D ( Vector3D dst, Vector3D src ) {
Vector3D result; /* 計算結果(差)を收める変数 */
/*
dst.x
dst : Vector3D <-> ( dst.y )
dst.z
dst.x src.z dst.x - src.x
dst - src <-> ( dst.y ) - ( src.y ) = ( dst.y - src.y )
dst.z src.z dst.z - src.z
*/
result.x = dst.x - src.x;
/* x 成分の計算 */
result.y = dst.y - src.y;
/* y 成分の計算 */
result.z = dst.z - src.z;
/* z 成分の計算 */
return result; /* 計算した結果を値として返す */
}
/*
* main
*/
int main( int argc, char *argv[] )
{
Vector3D dst;
Vector3D src;
dst.x = 1.2; /* 1.2 */
dst.y = 2.3; /* dst = ( 2.3 ) */
dst.z = 3.4; /* 3.4 */
src.x = -9.8; /* -9.8 */
src.y = 8.7; /* dst = ( 8.7 ) */
src.z = 0.0; /* 0.0 */
print_Vector3D ( dst ); /* dst の出力 */
printf ( "と\n" );
print_Vector3D ( src ); /* src の出力 */
printf ( "の差は\n" );
print_Vector3D ( sub_Vector3D ( dst, src ) );
/* 構造体を引数に渡したり、関数の返り値にする事ができる */
/* これは、代入文(と同じ)なので、値のコピーが行われる */
/* !!! 引数に指定した値はコピーされる */
/* !!! 実引数に変数名を指定して、対応した仮引数変数の値を変更しても、元変数の値は変わらない */
printf ( "となります。\n" );
return 0;
}
/*
* 課題 20181214-01
*
* 20181214 20181214-01-QQQQ.c
*
* 浮動小数点数の配列の要素内の数値の総和を求める。
* => 配列名を関数の引数に渡す事により、(間接的に..) 配列の要素を関数内で参照する
*/
#include <stdio.h>
/*
* 浮動小数点数の配列の要素内の数値の総和を求める。
*
* 利用方法
* コンパイル
* cc -o BASENAME.exe 20181214-01-QQQQ.c
* 実行
* ./BASENAME.exe
*/
#include <stdio.h>
/*
* double dsum ( double ary[], int size )
* 浮動小数点数の配列の要素内の数値の総和を求める関数
* double ary[]; 総和を求める要素を含む配列
* int size; 配列のサイズ
*/
double dsum ( double ary[], int size ) {
/* 配列名が持つ値を保持する仮引数変数の宣言では、
配列の宣言と同様に、配列名の後ろに「[]」をつけるが、
配列の宣言とは異なり、そこには、サイズを記述する必要はない */
/* => この仮引数は、あたかも配列名と同じよう利用できる */
/* => サイズは ? */
/* <= サイズは、別に指定するので、ここの「[]」中のサイズは、無視される */
/* この例では、二つ目の引数に指定された整数値が、配列のサイズだとして扱う */
/* => 普通は、[] の中は省略 */
double sum = 0.0; /* 総和は最初は 0 */
int i; /* 配列の要素を参照する添字変数 */
for ( i = 0; i < size; i++ ) { /* i = 0 〜 sum - 1 の間.. */
sum = sum + ary[i]; /* sum += ary[i] */
/* 仮引数 ary は、配列名と同じようにして
配列要素を参照するために利用可能 */
/* 「sum += ary[i]」とも書きける */
}
return sum; /* 結果を返す */
}
/*
* main
*/
#define ARY_SIZE 5
int main( int argc, char *argv[] )
{
double data[ARY_SIZE]; /* 大きさ ARY_SIZE の配列の宣言 */
int i; /* 配列の要素を参照する添字変数 */
double sum; /* 総和の計算結果を保持する */
printf ( "%d 個のデータを入力します。\n", ARY_SIZE );
for ( i = 0; i < ARY_SIZE; i++ ) {
printf ( "%d 番目の数値を入力してください : ", i + 1 );
scanf ( "%lf", & data[i] ); /* &(data[i]) と解釈され (&date)[i] ではない */
}
sum = dsum ( data, ARY_SIZE ); /* 引数に「配列名」を指定している */
/* !!! 「配列サイズ」は、わからない */
/* !!! わざわざ、サイズを別の引数で指定している */
/* !!! 良し悪し */
/* !!! [悪し] 配列には、配列サイズが不可欠なので、 */
/* !!! それをわざわざ、指定しなければならないのは不便 */
/* !!! [良し] それを指定しなければならないが、指定できるので、*/
/* !!! 普段と異なる値を指定する事もできる */
printf ( "入力されたデータの総和は %f です。\n", sum );
return 0;
}
#include <stdio.h>
int main(int argc, char *argv[]) {
int a0 = 0; /* 単純な変数の集まり */
int a1 = 1;
int a2 = 2;
int no;
printf ( "変更したい変数の番号を指定してください : " );
scanf ( "%d", &no ); /* 番号の入力 */
switch ( no ) {
case 0:
a0 = a0 + 10; /* a0 という変数の値を変更する (確定) */
break;
case 1:
a1 = a1 + 10; /* もし、a0 と異なる a1 変数の値を変更するなら別に命令を書く必要がある */
break;
case 2:
a2 = a2 + 10;
break;
default:
printf ( "番号は、0-2 で入力してください\n" );
break;
}
printf ( "a0 = %d, a1 = %d, a2 = %d\n", a0, a1, a2 );
return 0;
}
#include <stdio.h>
int main(int argc, char *argv[]) {
int a[3] = {0,1,2}; /* 配列 : a[0], a[1], a[2] が宣言され */
int no; /* それぞれ 0, 1, 2 で初期化可能 */
printf ( "変更したい変数の番号を指定してください : " );
scanf ( "%d", &no ); /* 番号の入力 */
if ( 0 <= no ) {
if ( no < 3 ) {
a[no] = a[no] + 10; /* どの変数の値が変更されるかを no という添え字を利用して指定している */
/* どの変数の値が変更されるかは、実行時に決まる(プログラム時には決まらない) */
} else {
printf ( "番号は、0-2 で入力してください\n" );
}
} else {
printf ( "番号は、0-2 で入力してください\n" );
}
printf ( "a0 = %d, a1 = %d, a2 = %d\n", a[0], a[1], a[2] );
return 0;
}
#include <stdio.h>
/*
配列と for 構文の相性
フィボナッチ数列の最初の 10 要素をもつ fib[10] を考える
1 ( n = 0, 1 )
fib(n) = {
fib(n-1)+fib(n-2) ( n > 1 )
*/
#define N_SIZE 10
int main(int argc, char *argv[]) {
int fib[N_SIZE]; /* fib[0] ? fib[9] */
int n;
fib[0] = 1;
fib[1] = 1;
for ( n = 2; n < N_SIZE; n++ ) {
fib[n] = fib[n-1] + fib[n-2];
}
/* 配列と for 構文の典型的な組み合わせ */
for ( n = 0; n < N_SIZE; n++ ) { /* 添え字変数を 0 で初期化し、サイズ-1を上限とする */
printf ( "fib[%d]=%d\n", n, fib[n] ); /* 配列 fib のすべての要素に対して処理 */
}
return 0;
}
#include <stdio.h>
void sub( int x ) {
printf ( "in Sub:\n" );
printf ( "\tx = %d\n", x );
x = x + 10; /* 関数の中で仮引数変数の値を変更する */
printf ( "\tx = %d\n", x ); /* 関数の中では、その値の変更が反映されている */
}
int main(int argc, char *argv[]) {
int x = 1;
printf ( "in Main:\n" );
printf ( "\tx = %d\n", x );
sub ( x ); /* 関数の引数に変数を指定する事をしても.. */
printf ( "in Main:\n" ); /* 呼び出し元には影響しない */
printf ( "\tx = %d\n", x );
return 0;
}
#include <stdio.h>
void sub( int x ) {
printf ( "in Sub:\n" );
printf ( "\tx = %d\n", x );
x = x + 10; /* 関数の中で仮引数変数の値を変更する */
printf ( "\tx = %d\n", x ); /* 関数の中では、その値の変更が反映されている */
}
int main(int argc, char *argv[]) {
int x[3] = {0,1,2}; /* 配列宣言 x[0], x[1], x[2] <= 0,1,2 */
/* int x1 = 1; と同様 */
printf ( "in Main:\n" );
printf ( "\tx[1] = %d\n", x[1] );
sub ( x[1] ); /* 関数の引数に変数を指定する事をしても.. */
printf ( "in Main:\n" ); /* 呼び出し元には影響しない */
printf ( "\tx[1] = %d\n", x[1] );
return 0;
}
#include <stdio.h>
void sub( int x ) {
printf ( "in Sub:\n" );
printf ( "\tx = %d\n", x );
x = x + 10; /* 関数の中で仮引数変数の値を変更する */
printf ( "\tx = %d\n", x ); /* 関数の中では、その値の変更が反映されている */
}
typedef struct {
int x0;
int x1;
int x2;
} ThreeMember;
int main(int argc, char *argv[]) {
ThreeMember tm;
tm.x1 = 1;
printf ( "in Main:\n" );
printf ( "\ttm.x1 = %d\n", tm.x1 );
sub ( tm.x1 ); /* 関数の引数に変数を指定する事をしても.. */
printf ( "in Main:\n" ); /* 呼び出し元には影響しない */
printf ( "\tm.x1 = %d\n", tm.x1 );
return 0;
}
#include <stdio.h>
typedef struct {
int x0;
int x1;
int x2;
} ThreeMember;
void sub( ThreeMember tm ) {
printf ( "in Sub:\n" );
printf ( "\ttm.x1 = %d\n", tm.x1 );
tm.x1 = tm.x1 + 10; /* 関数の中で仮引数変数の値を変更する */
printf ( "\ttm.x1 = %d\n", tm.x1 ); /* 関数の中では、その値の変更が反映されている */
}
int main(int argc, char *argv[]) {
ThreeMember tm;
tm.x1 = 1;
printf ( "in Main:\n" );
printf ( "\ttm.x1 = %d\n", tm.x1 );
sub ( tm ); /* 関数の引数に変数を指定する事をしても.. */
printf ( "in Main:\n" ); /* 呼び出し元には影響しない */
printf ( "\tm.x1 = %d\n", tm.x1 );
return 0;
}
#include <stdio.h>
void sub( int x[3] ) {
printf ( "in Sub:\n" );
printf ( "\tx[1] = %d\n", x[1] );
x[1] = x[1] + 10; /* 関数の中で仮引数変数の値を変更する */
printf ( "\tx[1] = %d\n", x[1] ); /* 関数の中では、その値の変更が反映されている */
}
int main(int argc, char *argv[]) {
int x[3] = { 0, 1, 2 };
printf ( "in Main:\n" );
printf ( "\tx[1] = %d\n", x[1] );
sub ( x ); /* 関数の引数に『配列名』を指定している */
/* 「x[3]」 ではない */
/* 「x[0-2]」 ではない */
/* 「x[1]」 は可能だが。これは「要素」の指定 */
/* 「配列を渡している」わけではない */
printf ( "in Main:\n" ); /* 呼び出し元には影響しない */
printf ( "\tx[1] = %d\n", x[1] );
/* 予想 : p-004 ? p-007 の結果を鑑みるに、答えは 1 だろう.. */
return 0;
}
#include <stdio.h>
void sub( int y[3] ) {
printf ( "in Sub:\n" );
printf ( "\ty[1] = %d\n", y[1] );
y[1] = y[1] + 10; /* 関数の中で仮引数変数の値を変更する */
printf ( "\ty[1] = %d\n", y[1] ); /* 関数の中では、その値の変更が反映されている */
}
int main(int argc, char *argv[]) {
int x[3] = { 0, 1, 2 };
printf ( "in Main:\n" );
printf ( "\tx[1] = %d\n", x[1] );
sub ( x ); /* 関数の引数に『配列名』を指定している */
/* 「x[3]」 ではない */
/* 「x[0-2]」 ではない */
/* 「x[1]」 は可能だが。これは「要素」の指定 */
/* 「配列を渡している」わけではない */
printf ( "in Main:\n" ); /* 呼び出し元には影響しない */
printf ( "\tx[1] = %d\n", x[1] );
/* 予想 : p-004 ? p-007 の結果を鑑みるに、答えは 1 だろう.. */
return 0;
}
/*
* 課題 20181214-01
*
* 20181214 20181214-01-QQQQ.c
*
* 浮動小数点数の配列の要素内の数値の総和を求める。
* => 配列名を関数の引数に渡す事により、(間接的に..) 配列の要素を関数内で参照する
*/
#include <stdio.h>
/*
* 浮動小数点数の配列の要素内の数値の総和を求める。
*
* 利用方法
* コンパイル
* cc -o BASENAME.exe 20181214-01-QQQQ.c
* 実行
* ./BASENAME.exe
*/
#include <stdio.h>
/*
* double dsum ( double ary[], int size )
* 浮動小数点数の配列の要素内の数値の総和を求める関数
* double ary[]; 総和を求める要素を含む配列
* int size; 配列のサイズ
*/
double dsum ( double ary[], int size ) {
/* 配列名が持つ値を保持する仮引数変数の宣言では、
配列の宣言と同様に、配列名の後ろに「[]」をつけるが、
配列の宣言とは異なり、そこには、サイズを記述する必要はない */
/* => この仮引数は、あたかも配列名と同じよう利用できる */
/* => サイズは ? */
/* <= サイズは、別に指定するので、ここの「[]」中のサイズは、無視される */
/* この例では、二つ目の引数に指定された整数値が、配列のサイズだとして扱う */
/* => 普通は、[] の中は省略 */
double sum = 0.0; /* 総和は最初は 0 */
int i; /* 配列の要素を参照する添字変数 */
for ( i = 0; i < size; i++ ) { /* i = 0 〜 sum - 1 の間.. */
sum = sum + ary[i]; /* sum += ary[i] */
/* 仮引数 ary は、配列名と同じようにして
配列要素を参照するために利用可能 */
/* 「sum += ary[i]」とも書きける */
}
return sum; /* 結果を返す */
}
/*
* main
*/
#define ARY_SIZE 5
int main( int argc, char *argv[] )
{
double data[ARY_SIZE]; /* 大きさ ARY_SIZE の配列の宣言 */
int nod; /* Number of Data [データの個数] */
int i; /* 配列の要素を参照する添字変数 */
double sum; /* 総和の計算結果を保持する */
printf ( "総和の計算をしたいデータの個数を入力してください : " );
scanf ( "%d", &nod ); /* 入力したいデータ個数 */
/* 1 <= nod <= ARY_SIZE である事は、仮定する */
printf ( "%d 個のデータを入力します。\n", nod );
for ( i = 0; i < nod; i++ ) {
printf ( "%d 番目の数値を入力してください : ", i + 1 );
scanf ( "%lf", & data[i] ); /* &(data[i]) と解釈され (&date)[i] ではない */
}
sum = dsum ( data, nod ); /* 引数に「配列名」を指定している */
/* nod は、配列サイズでなく、配列の中の有効な範囲 */
/* あるいは、dsum で参照してほしい範囲 (0 ? nod-1) を指定している */
/* !!! 「配列サイズ」は、わからない */
/* !!! わざわざ、サイズを別の引数で指定している */
/* !!! 良し悪し */
/* !!! [悪し] 配列には、配列サイズが不可欠なので、 */
/* !!! それをわざわざ、指定しなければならないのは不便 */
/* !!! [良し] それを指定しなければならないが、指定できるので、*/
/* !!! 普段と異なる値を指定する事もできる */
printf ( "入力されたデータの総和は %f です。\n", sum );
return 0;
}
2019/11/22
# 実は.. 今日は、「今日から、この講義は新しい局面に入った」で始める予定だった..
# でも、まあ、.. 電車が遅れているようなので、時間稼ぎ
[やりそこねていた内容(試験に関係部分)]
2019/09/27 の squash の話
c:\usr\c の所に、squash.zip をダウンロード
windows から、右クリックして[すべて展開]をする
squash というフォルダが作られる
ubuntus
cd c/squash
make
パスワードをきかれたら、いつものように「soft」と入力
うまくいったら..
make test
スカッシュゲームが開始される
操作方法など ( readme.txt を参照 )
[l] -> 右に移動
[h] -> 左に移動
[q] -> ゲーム終了
ゲームとしては、キーボードを利用して、パドルを左右に操作し、
ボールを打ち返す
[squash.c の説明]
必要なライブラリ
curses : text ベースで、画面描画操作を行うためのライブラリ
# printf は、画面に新しい文字列を追加する事しかできない
# <-> curses を利用すると、画面の任意の文字が上書きできる
# => charactor base のゲームを作る事ができる
## [いいたいこと]
## curses というおもしろいライブラリの紹介
## 色々機能が、ライブラリの形で提供されているので、探してみよう
curses の API (Application Program Interface : ライブラリを使うプログラムとライブラリの間の約束事
: ライブラリの使い方)
move(Y,X) : カーソル(次に文字を表示する)位置を Y 行 X 桁にする
refresh(); : 画面の更新を行う
# curses を利用して描画命令をおくっても、実は、かくれ画面の内容が
# 更新されるだけで、実際の画面には、反映されない(ちらつきを避けるため)
# refresh() によって、変更した内容を、画面に反映させる事ができる
# printf はカーソルの位置(表画面に直接)
addch( ch ) : 現在のカーソルの位置に、文字 ch を表示する
画面の初期化の命令がいくつか
initscr(); /* 画面を初期化 (クリアされる) */
cbreak(); /* 文字の入力をリアルタイムにする */
入力命令が実行されたとき(普通は、入力があるまで待つが..)、
この関数(1度だけ最初に呼ぶだけで、以降..) またなくなる
noecho(); /* 文字の入力をエコーバックしない */
timeout(0); /* 文字の入力がなければ直ぐにかえる */
getch() : キーボードから、入力して入力された文字コードを返す関数
getchar() とはちがい、初期化の設定に従って、
入力がなければ、すぐに、終了して、\0 (入力なし)を返す
endwin(); /* curses の後始末 */
特に、入力関係などの設定、標準状態にもどしてくれる
==
[前回まで]
# C 言語の習得の二大課題(ポインターと再帰呼び出し)
# 今日の内容から「ポインター」を理解するための準備を始める
[配列]
複数の変数をまとめて、扱う事ができる(データ構造)
int a[3]; /* a という整数型の要素を持つ配列を宣言 */
/* -> a[0], a[1], a[2] という三つ変数が利用できるようになる */
/* int a0;
int a1;
int a3;
と、三つの変数を宣言すると同じ.. */
a[0] = 1; /* a0 = 1 */
a[1] = a[0]+2; /* a1 = a0 + 2 */
/* 配列 a に対して、a[0], a[1], a[2] を配列の要素と呼ぶ */
/* 配列の要素を参照する場合、[]の中(添え字)には「整数式」が利用できる */
/* 間接参照(添え字を指定して、変数を選択している) */
/* <=> 直接参照(変数を「変数名」を直接指定する事により選択している) */
/* !! 配列では、添え字を利用して間接参照できる事が、
!! 単なる「変数の集まり」とは異なる
!! !! => 「ポインター」が強力な理由も同じ
*/
/* 間接参照ができる => 参照先を実行時に計算で求める事できる */
/* <= 直接参照の場合は、プログラム時に決まってしまう */
配列の要素が、添え字を利用して、参照できる
=> for 構文の相性が非常によくなる
# for 構文は、配列を利用するためにしつらえた構文
[今日の話]
「配列の引数渡し」
復習 : 課題 2019/11/08 課題 3
関数の引数には、配列名を指定する事ができる
=> あたかも、(他の例では、引数に指定したもののコピーが渡されるように見えるにも変わらず)
「配列そのもの」が渡されるように、見える
!! 関数の引数は、「値」が渡されるので、「変数そのもの」が渡るわけではない
!! => にも関わらず、「配列名」を指定した場合に、「配列の要素そのもの」が渡されるように見える仕組みは何か ?
!! # 「変数そのもの」 <=> 「関数内での変数の値への変更が、呼び出し元に反映される」
改めて、「配列の要素の参照」
int a[3]; /* a[0], a[1], a[2] */
a[1]; /* 添え字を配列名に指定すると、その要素が参照できる */
*(a+1) /* 「a[1]」 <-> 「*(a+1)」 */
/* 「もし」、「a(配列名)」が何等かの「値」をもっている */
/* 引数に指定しれば、その「値」(のコピー)が渡される */
void sub ( int y[3] ) { /* y という「配列」ではなく、「配列名が表す値を保持する変数」だと解釈すると */
y[1] => *(y+1) => *(a+1) => a[1] と同じ振る舞いをする事になる
}
sub ( a ); /* 配列名を指定すると a の値が y に代入される */
/* !!!! 「配列名」を指定しても、「配列のサイズ」は決まらない */
関数の引数に、「配列名」を指定すると
関数の中で、その「『配列名』が表す値」を利用する事できて、
その「『配列名』が表す値」を利用して、間接的に、「配列の要素」を変更する事ができる
=> 関数呼び出しによって、呼び出す側の変数(配列の要素)の値が変更される事がおきるうる
[まとめ]
関数の引数に、「配列名」を指定する事ができる
関数の中では、その「関数名が持っている『要素を参照するために必要な値』」を利用して、
その「配列名が表す『配列の要素』を参照(値を取り出すだけでなく、値の変更[代入]も)可能」
=>
この結果、
関数では、配列のサイズと独立して動く機能が実現できる
そのために、処理の範囲(配列のサイズである事が多いが、それに限らない) を別に指定する必要がある
!! [副作用]
!! 悪し : 関数の呼び出し元と、関数内での配列(の要素)が「共有」される
!! 良し : コピーがおきないので、効率が良い
課題プログラム内の「/*名前:ここ*/」の部分を書き換え「/*この部分を完成させなさい*/」の部分にプログラムを追加して、プログラムを完成させます。
Download : 20191122-01.c
/*
* 課題 20181214-01
*
* 20181214 20181214-01-QQQQ.c
*
* 浮動小数点数の配列の要素内の数値の総和を求める。
*/
#include <stdio.h>
/*
* 浮動小数点数の配列の要素内の数値の総和を求める。
*
* 利用方法
* コンパイル
* cc -o BASENAME.exe 20181214-01-QQQQ.c
* 実行
* ./BASENAME.exe
*/
#include <stdio.h>
/*
* double dsum ( double ary[], int size )
* 浮動小数点数の配列の要素内の数値の総和を求める関数
* double ary[]; 総和を求める要素を含む配列
* int size; 配列のサイズ
*/
double dsum ( double ary[], int size ) {
double sum = 0.0; /* 総和は最初は 0 */
int i; /* 配列の要素を参照する添字変数 */
for ( i = 0; i < size; i++ ) { /* i = 0 〜 sum - 1 の間.. */
/*
** この部分を完成させなさい
*/
/* 「sum += ary[i]」とも書きける */
}
return sum; /* 結果を返す */
}
/*
* main
*/
#define ARY_SIZE 5
int main( int argc, char *argv[] )
{
double data[ARY_SIZE]; /* 大きさ ARY_SIZE の配列の宣言 */
int i; /* 配列の要素を参照する添字変数 */
double sum; /* 総和の計算結果を保持する */
printf ( "%d 個のデータを入力します。\n", ARY_SIZE );
for ( i = 0; i < ARY_SIZE; i++ ) {
printf ( "%d 番目の数値を入力してください : ", i + 1 );
/*
** この部分を完成させなさい
*/
}
sum = dsum ( data, ARY_SIZE );
printf ( "入力されたデータの総和は %f です。\n", sum );
return 0;
}
2.3 9.1 5.9 2.7 3.2
$ ./20181214-01-QQQQ.exe 5 個のデータを入力します。 1 番目の数値を入力してください : 2.300000 2 番目の数値を入力してください : 9.100000 3 番目の数値を入力してください : 5.900000 4 番目の数値を入力してください : 2.700000 5 番目の数値を入力してください : 3.200000 入力されたデータの総和は 23.200000 です。 $
Download : 20191122-02.c
/*
* 課題 20181214-02
*
* 20181214 20181214-02-QQQQ.c
*
* 文字列の途中に文字を挿入する
*
* 利用方法
* コンパイル
* cc -o BASENAME.exe 20181214-02-QQQQ.c
* 実行
* ./BASENAME.exe
*/
#include <stdio.h>
/*
*
*/
/*
* main
*
*/
#define CSIZE 10
#define EOS '\0'
int main( int argc, char *argv[] )
{
char cary[CSIZE] = { 'a', 'b', 'c', 'd', 'e', EOS };
/*
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
cary|'a'|'b'|'c'|'d'|'e'|EOS| ? | ? | ? | ? |
*/
int i;
int l;
printf ( "最初の cary = %s\n", cary );
/*
文字列 "abcde" の入った文字配列 cary の
3 文字目 ('c') と 4 文字目 'd' の間に、一文字 'X' を入れる
*/
/* 文字列の長さを求める */
/*
** この部分を完成させなさい
*/
/* cary の中の文字列の長さは、変数 l に入る */
for ( i = l; 3 <= i; i-- ) { /* 後ろからコピーする必要がある */
/*
** この部分を完成させなさい
*/
}
cary[3] = 'X'; /* 空けた場所に 'X' を入れる */
/*
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
cary|'a'|'b'|'c'|'d'|'e'|EOS| ? | ? | ? | ? |
| | | \ \ \
cary|'a'|'b'|'c'|'X'|'d'|'e'|EOS| ? | ? | ? | ? |
*/
printf ( "'X' を挿入した結果 : %s\n", cary );
return 0;
}
123 987 456
$ ./20191122-02-QQQQ.exe 最初の cary = abcde 'X' を挿入した結果 : abcXde $
Download : 20191122-03.c
/*
* 20181214-03-QQQQ.c
* 一行分の文字列を入力して、その中の文字列を全て大文字に変換する
*/
#include <stdio.h>
/*
* islower (ch) : 指定された文字が、小文字かどうかを判定する
*/
int islower ( int ch ) {
return 'a' <= ch && ch <= 'z'; /* 'a' 〜 'z' なら小文字 */
}
/*
* toupper ( ch ) : 指定された文字が、小文字なら大文字に変換
*/
int toupper ( int ch ) {
if ( islower ( ch ) ) { /* 小文字だった.. */
/*
** この部分を完成させなさい
*/
} else { /* そうでないなら */
return ch; /* そのまま返す */
}
}
/*
* main
*/
#define EOS '\0' /* EOS を定義 */
#define LINE_SIZE 128 /* 入力するのに十分に大きなサイズにする */
int main ( void ) {
char line[LINE_SIZE];
int i;
printf ( "小文字を含んだ文字列を入力してください : " );
/*
** この部分を完成させなさい
*/
for ( i = 0; line[i] != EOS; i++ ) {
line[i] = toupper ( line[i] ); /* 小文字を大文字に変換 */
}
printf ( "結果 : %s", line );
return 0;
}
aBcd123[]
$ ./20191122-03-QQQQ.exe 小文字を含んだ文字列を入力してください : 結果 : ABCD123[] $