Download : sample-001.c
/*
* 2020/11/20 sample-001.c
*/
#include <stdio.h>
#include "s_memory.h" /* memory モデルを理解するための関数定義 */
/*
*
*/
int main ( void ) {
/*
* メモリの操作 ( 情報の記録 : set_memory_value_at )
*/
set_memory_value_at ( 100, 1 ); /* 100 番地のセルに 1 を記録する */
set_memory_value_at ( 101, 10 ); /* 101 番地のセルに 10 を記録する */
/*
* メモリの操作 ( 情報の参照 : get_memory_value_at )
*/
printf ( "100 番地のセルに記録されている数値は %d です。\n",
get_memory_value_at ( 100 )
);
printf ( "101 番地のセルに記録されている数値は %d です。\n",
get_memory_value_at ( 101 )
);
/*
*
*/
return 0;
}
/*
*
*/
$ ./sample-001.exe 100 番地のセルに記録されている数値は 1 です。 101 番地のセルに記録されている数値は 10 です。 $
Download : sample-002.c
/*
* 2021/11/26 sample-002.c
*/
#include <stdio.h>
#include "s_memory.h" /* memory モデルを理解するための関数定義 */
/*
* print_memory_value
* 指定された address の記憶セルの内容を画面に出力する
*/
void print_memory_value ( int address ) {
printf ( "%d 番地のセルに記録されている数値は %d です。\n",
address,
get_memory_value_at ( address ) /* 値の取出し */
);
}
/*
* print_memory_set
* メモリへの記憶操作を行い、それを報告する
*/
void print_memory_set ( int address, int value ) {
/* 動作の表示 */
printf ( "%d 番地のセルに %d を記録。\n",
address, value
);
/* address 番地に value を記録する */
set_memory_value_at ( address, value ); /* 値の設定 */
}
/*
* print_line
* 横棒を表示
*/
void print_line ( void ) {
printf ( "--------------------------------------\n" );
}
/*
*
*/
int main ( void ) {
/*
* メモリの参照 : 一度記録した情報は何度でも参照できる
*/
print_memory_set ( 100, 1 ); /* 100 番地のセルに 1 を記録する */
printf ( "一度目 : " );
print_memory_value ( 100 ); /* 100 番地のセルの内容を出力 (一度目) */
printf ( "二度目 : " );
print_memory_value ( 100 ); /* 二度目 */
printf ( "三度目 : " );
print_memory_value ( 100 ); /* 三度目 */
/*
* 参照は何度行っても、同じ情報が得られる
*/
print_line();
/*
* 記憶の破壊 : 新しい情報を記録すると以前の記録は失われる
*/
print_memory_set ( 100, 99 ); /* 100 番地のセルに 99 を記録する */
printf ( "変更後 : " );
print_memory_value ( 100 ); /* 100 番地のセルの内容を出力 */
/*
* 新しい情報を記憶すると以前の記録された情報は失われる
*/
/*
* 記録は最後のものだけ ( 参照の有無と無関係に最後のものだけを記録 )
*/
print_memory_set ( 100, 21 ); /* 100 番地のセルに 21 を記録する */
print_memory_set ( 100, 22 ); /* 100 番地のセルに 22 を記録する */
print_memory_set ( 100, 23 ); /* 100 番地のセルに 23 を記録する */
printf ( "現在値 : " );
print_memory_value ( 100 ); /* 100 番地のセルの内容を出力 */
/*
* 記録されている情報は最後に記録された物だけ
*/
/*
*
*/
return 0;
}
/*
*
*/
$ ./sample-002.exe 100 番地のセルに 1 を記録。 一度目 : 100 番地のセルに記録されている数値は 1 です。 二度目 : 100 番地のセルに記録されている数値は 1 です。 三度目 : 100 番地のセルに記録されている数値は 1 です。 -------------------------------------- 100 番地のセルに 99 を記録。 変更後 : 100 番地のセルに記録されている数値は 99 です。 100 番地のセルに 21 を記録。 100 番地のセルに 22 を記録。 100 番地のセルに 23 を記録。 現在値 : 100 番地のセルに記録されている数値は 23 です。 $
Download : sample-003.c
/*
* 2021/11/26 sample-003.c
*/
#include <stdio.h>
#include "s_memory.h" /* memory モデルを理解するための関数定義 */
/*
* print_memory_value
* 指定された address の記憶セルの内容を画面に出力する
*/
void print_memory_value ( int address ) {
printf ( "%d 番地のセルに記録されている数値は %d です。\n",
address,
get_memory_value_at ( address ) /* 値の取出し */
);
}
/*
* print_memory_set
* メモリへの記憶操作を行い、それを報告する
*/
void print_memory_set ( int address, int value ) {
/* 動作の表示 */
printf ( "%d 番地のセルに %d を記録。\n",
address, value
);
/* address 番地に value を記録する */
set_memory_value_at ( address, value ); /* 値の設定 */
}
/*
* print_line
* 横棒を表示
*/
void print_line ( void ) {
printf ( "--------------------------------------\n" );
}
/*
*
*/
int main ( void ) {
/*
* メモリセルの独立性 : 番地の異るセルは独立に振る舞う
*/
print_memory_set ( 100, 1 ); /* 100 番地のセルに 1 を記録する */
print_memory_set ( 101, 2 ); /* 101 番地のセルに 2 を記録する */
print_memory_value ( 100 ); /* 100 番地のセルの内容を出力 */
print_memory_value ( 101 ); /* 101 番地のセルの内容を出力 */
/*
* 番地が異れば、記録されている情報も異る
*/
/*
* 記憶の独立性
*/
print_memory_set ( 100, 99 ); /* 100 番地のセルに 99 を記録する */
print_memory_value ( 100 ); /* 100 番地のセルの内容を出力 */
print_memory_value ( 101 ); /* 101 番地のセルの内容を出力 */
print_line();
/*
* 100 番地の情報を書き換えても、101 番地の情報は影響しない
*/
print_memory_set ( 101, 88 ); /* 101 番地のセルに 88 を記録する */
print_memory_value ( 100 ); /* 100 番地のセルの内容を出力 */
print_memory_value ( 101 ); /* 101 番地のセルの内容を出力 */
/*
* 逆も真なり
*/
/*
*
*/
return 0;
}
/*
*
*/
$ ./sample-003.exe 100 番地のセルに 1 を記録。 101 番地のセルに 2 を記録。 100 番地のセルに記録されている数値は 1 です。 101 番地のセルに記録されている数値は 2 です。 100 番地のセルに 99 を記録。 100 番地のセルに記録されている数値は 99 です。 101 番地のセルに記録されている数値は 2 です。 -------------------------------------- 101 番地のセルに 88 を記録。 100 番地のセルに記録されている数値は 99 です。 101 番地のセルに記録されている数値は 88 です。 $
Download : sample-004.c
/*
* 2021/11/26 sample-004.c
*/
#include <stdio.h>
#include "s_memory.h" /* memory モデルを理解するための関数定義 */
/*
* print_memory_value
* 指定された address の記憶セルの内容を画面に出力する
*/
void print_memory_value ( int address ) {
printf ( "%d 番地のセルに記録されている数値は %d です。\n",
address,
get_memory_value_at ( address ) /* 値の取出し */
);
}
/*
* print_memory_set
* メモリへの記憶操作を行い、それを報告する
*/
void print_memory_set ( int address, int value ) {
/* 動作の表示 */
printf ( "%d 番地のセルに %d を記録。\n",
address, value
);
/* address 番地に value を記録する */
set_memory_value_at ( address, value ); /* 値の設定 */
}
/*
* print_line
* 横棒を表示
*/
void print_line ( void ) {
printf ( "--------------------------------------\n" );
}
/*
*
*/
int main ( void ) {
/*
* メモリセルの容量
*/
print_memory_set ( 100, 0 ); /* 100 番地のセルに 0 を記録する */
print_memory_value ( 100 ); /* 100 番地のセルの内容を出力 */
print_memory_set ( 100, 100 ); /* 100 番地のセルに 100 を記録する */
print_memory_value ( 100 ); /* 100 番地のセルの内容を出力 */
print_memory_set ( 100, 255 ); /* 100 番地のセルに 255 を記録する */
print_memory_value ( 100 ); /* 100 番地のセルの内容を出力 */
/*
* 0 〜 255 ならば、記録できる
*/
print_line();
/*
* メモリセルの容量オーバー
*/
print_memory_set ( 100, 300 ); /* 100 番地のセルに 300 を記録しようとした */
print_memory_value ( 100 ); /* 100 番地のセルの内容を出力 */
/*
* 300 は記憶されていない !!
* 実は 300 を 256 で割った余り ( 44 ) が記録されている
* 256 を越える(オーバーする)情報は捨てられる !!
*/
/*
*
*/
return 0;
}
/*
*
*/
$ ./sample-004.exe 100 番地のセルに 0 を記録。 100 番地のセルに記録されている数値は 0 です。 100 番地のセルに 100 を記録。 100 番地のセルに記録されている数値は 100 です。 100 番地のセルに 255 を記録。 100 番地のセルに記録されている数値は 255 です。 -------------------------------------- 100 番地のセルに 300 を記録。 100 番地のセルに記録されている数値は 44 です。 $
Download : sample-005.c
/*
* 2020/11/20 sample-005.c
*/
#include <stdio.h>
#include "s_variable.h" /* memory モデルを理解するための関数定義 */
/*
*
*/
int main ( void ) {
/*
* C 言語の変数のメモリモデルによる理解
*/
char cvar; /* char 型の変数 cvar の宣言 */
char dvar; /* char 型の変数 dvar の宣言 */
/*
* 変数はアドレスをもっている
*/
printf ( "変数 cvar のアドレスは 16 進数表現で %x です。\n",
get_variable_address( cvar )
);
printf ( "変数 dvar のアドレスは 16 進数表現で %x です。\n",
get_variable_address( dvar )
);
/*
* 変数名が異れば、番地も異っている
*/
/*
* 変数をアドレスを利用して参照
*/
cvar = 'c'; /* 変数 cvar に、値 'c' を代入 */
dvar = 'D'; /* 変数 Dvar に、値 'D' を代入 */
printf ( "変数 cvar に記録されている文字は %c です。\n",
get_variable_value_at ( get_variable_address( cvar ) )
);
printf ( "変数 dvar に記録されている文字は %c です。\n",
get_variable_value_at ( get_variable_address( dvar ) )
);
/*
* 変数の値をアドレスを利用して変更
*/
set_variable_value_at ( get_variable_address( cvar ), 'X' );
/* 変数 cvar の所に 'X' を記録 */
printf ( "cvar は %c です。\n", cvar );
set_variable_value_at ( get_variable_address( dvar ), 'y' );
/* 変数 dvar の所に 'y' を記録 */
printf ( "dvar は %c です。\n", dvar );
/*
*
*/
return 0;
}
/*
*
*/
10
$ ./sample-005.exe < sample-005.in 変数 cvar のアドレスは 16 進数表現で 74ddfabe です。 変数 dvar のアドレスは 16 進数表現で 74ddfabf です。 変数 cvar に記録されている文字は c です。 変数 dvar に記録されている文字は D です。 cvar は X です。 dvar は y です。 $
Download : sample-006.c
/*
* 2020/11/20 sample-006.c
*/
#include <stdio.h>
#include "s_variable.h" /* memory モデルを理解するための関数定義 */
/*
*
*/
int main ( void ) {
/*
* C 言語の文字列のメモリモデルによる理解
*/
/*
* 文字列はアドレスをもっている
*/
printf ( "文字列 \"abc\" のアドレスは 16 進数表現で %x です。\n",
get_string_address( "abc" )
);
/*
* 文字列の要素をアドレスを利用して参照
*/
printf ( "文字列 \"abc\" の先頭の文字は %c です。\n",
get_variable_value_at ( get_string_address( "abc" ) )
);
/*
* 文字列の要素の二つ目以後を取り出す
*/
printf ( "文字列 \"abc\" の先頭の次の文字は %c です。\n",
get_variable_value_at ( get_string_address( "abc" ) + 1 )
);
printf ( "文字列 \"abc\" の先頭の次の次の文字は %c です。\n",
get_variable_value_at ( get_string_address( "abc" ) + 2 )
);
/*
*
*/
return 0;
}
/*
*
*/
$ ./sample-006.exe 文字列 "abc" のアドレスは 16 進数表現で 401470 です。 文字列 "abc" の先頭の文字は a です。 文字列 "abc" の先頭の次の文字は b です。 文字列 "abc" の先頭の次の次の文字は c です。 $
Download : sample-007.c
/*
* 2020/11/20 sample-007.c
*/
#include <stdio.h>
#include "s_variable.h" /* memory モデルを理解するための関数定義 */
/*
*
*/
int main ( void ) {
/*
* C 言語の変数のメモリモデルによる理解
*/
char cvar; /* char 型の変数 cvar の宣言 */
char dvar; /* char 型の変数 dvar の宣言 */
char evar; /* char 型の変数 evar の宣言 */
/*
* 変数を並べてて宣言すると (偶然..) アドレスが連続していた..
*/
printf ( "変数 cvar のアドレスは 16 進数表現で %x です。\n",
get_variable_address( cvar )
);
printf ( "変数 dvar のアドレスは 16 進数表現で %x です。\n",
get_variable_address( dvar )
);
printf ( "変数 evar のアドレスは 16 進数表現で %x です。\n",
get_variable_address( evar )
);
/*
* 変数をアドレスを利用して参照
*/
cvar = 'c'; /* 変数 cvar に、値 'c' を代入 */
dvar = 'D'; /* 変数 dvar に、値 'D' を代入 */
evar = '\0'; /* 変数 evar に、値 '\0' を代入 */
printf ( "cvar の所から記録されている文字列は (%s) です。\n",
get_variable_address( cvar )
);
/*
* アドレス経由で、変数の内容を変更
*/
set_variable_value_at ( get_variable_address( cvar ) + 1, 'x' );
/* 変数 cvar のアドレスの次のアドレスは dvar のアドレスなので.. */
printf ( "cvar に記録されている文字は %c です。\n",
cvar
);
/* 結果的に、dvar の内容が書き変わる */
printf ( "dvar に記録されている文字は %c です。\n",
dvar
);
/*
*
*/
return 0;
}
/*
*
*/
$ ./sample-007.exe 変数 cvar のアドレスは 16 進数表現で fba3427d です。 変数 dvar のアドレスは 16 進数表現で fba3427e です。 変数 evar のアドレスは 16 進数表現で fba3427f です。 cvar の所から記録されている文字列は (cD) です。 cvar に記録されている文字は c です。 dvar に記録されている文字は x です。 $
Download : sample-008.c
/*
* 2020/11/20 sample-008.c
*/
#include <stdio.h>
#include "s_variable.h" /* memory モデルを理解するための関数定義 */
/*
*
*/
int main ( void ) {
/*
* C 言語の変数のメモリモデルによる理解
*/
char carray[3]; /* char 型の一次元配列 carray の宣言 (サイズは 3) */
/*
意味的には
char carry[0]; -- cvar
char carry[1]; -- dvar
char carry[2]; -- evar
のように考えて良い (cf. sample-007.c)
*/
/*
* 配列の要素のアドレスは連続している事が保証される
*/
printf ( "変数 carray[0] のアドレスは 16 進数表現で %x です。\n",
get_variable_address( carray[0] )
);
printf ( "変数 carray[1] のアドレスは 16 進数表現で %x です。\n",
get_variable_address( carray[1] )
);
printf ( "変数 carray[2] のアドレスは 16 進数表現で %x です。\n",
get_variable_address( carray[2] )
);
/*
* 変数をアドレスを利用して参照
*/
carray[0] = 'c'; /* 変数 carray[0] に、値 'c' を代入 */
carray[1] = 'D'; /* 変数 carray[1] に、値 'D' を代入 */
carray[2] = '\0'; /* 変数 carray[2] に、値 '\0' を代入 */
printf ( "carray[0] の所から記録されている文字列は (%s) です。\n",
get_variable_address( carray[0] )
);
/*
* アドレス経由で、変数の内容を変更
*/
set_variable_value_at ( get_variable_address( carray[0] ) + 1, 'x' );
/* 変数 carray[0] のアドレスの次のアドレスは carray[1] のアドレスなので.. */
printf ( "carray[0] に記録されている文字は %c です。\n",
carray[0]
);
/* 結果的に、carray[1] の内容が書き変わる */
printf ( "carray[1] に記録されている文字は %c です。\n",
carray[1]
);
/*
*
*/
return 0;
}
/*
*
*/
$ ./sample-008.exe 変数 carray[0] のアドレスは 16 進数表現で 4410b3c0 です。 変数 carray[1] のアドレスは 16 進数表現で 4410b3c1 です。 変数 carray[2] のアドレスは 16 進数表現で 4410b3c2 です。 carray[0] の所から記録されている文字列は (cD) です。 carray[0] に記録されている文字は c です。 carray[1] に記録されている文字は x です。 $
Download : sample-009.c
/*
* 2020/11/20 sample-009.c
*/
#include <stdio.h>
#include "s_variable.h" /* memory モデルを理解するための関数定義 */
/*
*
*/
int main ( void ) {
/*
*
*/
char carray[3]; /* char 型の一次元配列 carray の宣言 (サイズは 3) */
/*
* 配列の要素のアドレスは連続している事が保証される
*/
carray[0] = 'c'; /* 変数 carray[0] に、値 'c' を代入 */
carray[1] = 'D'; /* 変数 carray[1] に、値 'D' を代入 */
carray[2] = '\0'; /* 変数 carray[2] に、値 '\0' を代入 */
printf ( "carray[0] の所から記録されている文字列は (%s) です。\n",
get_variable_address( carray[0] )
);
/*
* 配列名は、文字列と同じように扱える
*/
printf ( "carray が表現している文字列は (%s) です。\n",
carray
);
/*
* 文字列の一部を変更する事ができる
*/
carray[1] = 'U'; /* ニ文字目を 'U' に変更 */
printf ( "carray が表現している文字列は (%s) です。\n",
carray
);
carray[0] = 'p'; /* 一字目を 'p' に変更 */
printf ( "carray が表現している文字列は (%s) です。\n",
carray
);
/*
*
*/
return 0;
}
/*
*
*/
$ ./sample-009.exe carray[0] の所から記録されている文字列は (cD) です。 carray が表現している文字列は (cD) です。 carray が表現している文字列は (cU) です。 carray が表現している文字列は (pU) です。 $
Download : sample-010.c
/*
* 2020/11/20 sample-010.c
*/
#include <stdio.h>
/*
*
*/
int main ( void ) {
/*
* 文字配列の初期化
*/
char carray[3] = "AB";
/*
carray[0] = 'A';
carray[1] = 'B';
carray[2] = '\0';
*/
printf ( "carray[0] は %c です。\n",
carray[0]
);
printf ( "carray[1] は %c です。\n",
carray[1]
);
/*
*
*/
return 0;
}
/*
*
*/
$ ./sample-010.exe carray[0] は A です。 carray[1] は B です。 $
Download : sample-011.c
/*
* 2020/11/20 sample-011.c
*/
#include <stdio.h>
/*
*
*/
int main ( void ) {
/*
* アドレス演算子「&」と間接演算子「*」
*/
char carray[3] = "AB";
/*
* 添字による参照
*/
printf ( "carry[0] = %c\n", carry[0] );
printf ( "carry[1] = %c\n", carry[1] );
/*
* 間接演算子による参照
*/
printf ( "*carry = %c\n", *carry );
printf ( "*(carry+1) = %c\n", *(carry+1) );
/*
* address の比較
*/
s_print_string ( "&carry[0] = %x\n", &carry[0] );
s_print_string ( "carry = %x\n", carry );
/*
* 「&」と「*」は逆演算子
*/
s_print_string ( "carry = %x\n", carry );
s_print_string ( "&*carry = %x\n", &*carry );
s_print_string ( "carry[0] = %c\n", carry[0] );
s_print_string ( "*&carry[0] = %c\n", *&carry[0] );
/*
*
*/
return 0;
}
/*
*
*/
$ ./sample-011.exe carray[0] は A です。 carray[1] は B です。 $
Download : sample-012.c
/*
* 2020/11/20 sample-012.c
*/
#include <stdio.h>
#include "s_memory.h" /* memory モデルを理解するための関数定義 */
/*
* ◯×ゲームのボード (一次元版)
*
* y
* 0 1 2 (y,t)
* +-----+-----+-----+ +-----+
* 0 |(0,0)|(0,1)|(0,2)| |(0,0)| 0 = 0*3+0 = t*3+y
* +-----+-----+-----+ +-----+
* t 1 |(1,0)|(1,1)|(1,2)| |(0,1)| 1 = 0*3+1 = t*3+y
* +-----+-----+-----+ +-----+
* 2 |(2,0)|(2,1)|(2,2)| |(0,2)| 2 = 0*3+2 = t*3+y
* +-----+-----+-----+ +-----+
* |(1,0)| 3 = 1*3+0 = t*3+y
* +-----+
* |(1,1)| 4 = 1*3+1 = t*3+y
* +-----+
* |(1,2)| 5 = 1*3+2 = t*3+y
* +-----+
* |(2,0)| 6 = 2*3+0 = t*3+y
* +-----+
* |(2,1)| 7 = 2*3+1 = t*3+y
* +-----+
* |(2,2)| 8 = 2*3+2 = x*3+y
* +-----+
*
*/
#define BOARD_SIZE 3 /* ボードのサイズ */
#define SENTE_MARK 'o' /* 先手は 'o' (マル) */
#define GOTE_MARK 'x' /* 後手は 'x' (バツ) */
int main ( void ) {
/*
*
*/
char board[BOARD_SIZE*BOARD_SIZE]; /* サイズは 3 × 3 */
int t; /* 縱 */
int y; /* 横 */
/*
* ある局面
*
* oxx
* xoo
* oox
*/
board[0*BOARD_SIZE+0] = 'o'; /* (0,0) */
board[0*BOARD_SIZE+1] = 'x'; /* (0,1) */
board[0*BOARD_SIZE+2] = 'x'; /* (0,2) */
board[1*BOARD_SIZE+0] = 'x'; /* (1,0) */
board[1*BOARD_SIZE+1] = 'o'; /* (1,1) */
board[1*BOARD_SIZE+2] = 'o'; /* (1,2) */
board[2*BOARD_SIZE+0] = 'o'; /* (2,0) */
board[2*BOARD_SIZE+1] = 'x'; /* (2,1) */
board[2*BOARD_SIZE+2] = 'x'; /* (2,2) */
/*
*
*/
t = 0;
while ( t < BOARD_SIZE ) {
y = 0;
while ( y < BOARD_SIZE ) {
printf ( "%c", board[t*BOARD_SIZE+y] );
y = y + 1;
}
printf ( "\n" );
t = t + 1;
}
/*
*
*/
return 0;
}
/*
*
*/
$ ./sample-012.exe oxx xoo oxx $
Download : sample-013.c
/*
* 2020/11/20 sample-013.c
*/
#include <stdio.h>
/*
* ◯×ゲームのボード (一次元版)
*
* y
* 0 1 2 (y,t)
* +-----+-----+-----+ +-----+
* 0 |(0,0)|(0,1)|(0,2)| |(0,0)| 0 = 0*3+0 = t*3+y
* +-----+-----+-----+ +-----+
* t 1 |(1,0)|(1,1)|(1,2)| |(0,1)| 1 = 0*3+1 = t*3+y
* +-----+-----+-----+ +-----+
* 2 |(2,0)|(2,1)|(2,2)| |(0,2)| 2 = 0*3+2 = t*3+y
* +-----+-----+-----+ +-----+
* |(1,0)| 3 = 1*3+0 = t*3+y
* +-----+
* |(1,1)| 4 = 1*3+1 = t*3+y
* +-----+
* |(1,2)| 5 = 1*3+2 = t*3+y
* +-----+
* |(2,0)| 6 = 2*3+0 = t*3+y
* +-----+
* |(2,1)| 7 = 2*3+1 = t*3+y
* +-----+
* |(2,2)| 8 = 2*3+2 = x*3+y
* +-----+
*
*/
#define BOARD_SIZE 3 /* ボードのサイズ */
#define SENTE_MARK 'o' /* 先手は 'o' (マル) */
#define GOTE_MARK 'x' /* 後手は 'x' (バツ) */
/*
* 二次元の座標を一次元に変換する関数
*/
int index2d ( int t, int y ) {
return t * BOARD_SIZE + y;
}
int main ( void ) {
/*
*
*/
char board[BOARD_SIZE*BOARD_SIZE]; /* サイズは 3 × 3 */
int t; /* 縱 */
int y; /* 横 */
/*
* ある局面
*
* oxx
* xoo
* oox
*/
board[index2d(0,0)] = 'o'; /* (0,0) */
board[index2d(0,1)] = 'x'; /* (0,1) */
board[index2d(0,2)] = 'x'; /* (0,2) */
board[index2d(1,0)] = 'x'; /* (1,0) */
board[index2d(1,1)] = 'o'; /* (1,1) */
board[index2d(1,2)] = 'o'; /* (1,2) */
board[index2d(2,0)] = 'o'; /* (2,0) */
board[index2d(2,1)] = 'x'; /* (2,1) */
board[index2d(2,2)] = 'x'; /* (2,2) */
/*
*
*/
t = 0;
while ( t < BOARD_SIZE ) {
y = 0;
while ( y < BOARD_SIZE ) {
printf ( "%c", board[index2d(t,y)] );
y = y + 1;
}
printf ( "\n" );
t = t + 1;
}
/*
*
*/
return 0;
}
/*
*
*/
$ ./sample-013.exe oxx xoo oxx $
Download : sample-014.c
/*
* 2020/11/20 sample-014.c
*/
#include <stdio.h>
/*
* ◯×ゲームのボード (二次元版)
*
* y
* 0 1 2
* +-----+-----+-----+
* 0 |(0,0)|(0,1)|(0,2)|
* +-----+-----+-----+
* t 1 |(1,0)|(1,1)|(1,2)|
* +-----+-----+-----+
* 2 |(2,0)|(2,1)|(2,2)|
* +-----+-----+-----+
*
*/
#define BOARD_SIZE 3 /* ボードのサイズ */
#define SENTE_MARK 'o' /* 先手は 'o' (マル) */
#define GOTE_MARK 'x' /* 後手は 'x' (バツ) */
int main ( void ) {
/*
*
*/
char board[BOARD_SIZE][BOARD_SIZE]; /* サイズは 3 × 3 */
int t; /* 縱 */
int y; /* 横 */
/*
* ある局面
*
* oxx
* xoo
* oox
*/
board[0][0] = 'o'; /* (0,0) */
board[0][1] = 'x'; /* (0,1) */
board[0][2] = 'x'; /* (0,2) */
board[1][0] = 'x'; /* (1,0) */
board[1][1] = 'o'; /* (1,1) */
board[1][2] = 'o'; /* (1,2) */
board[2][0] = 'o'; /* (2,0) */
board[2][1] = 'x'; /* (2,1) */
board[2][2] = 'x'; /* (2,2) */
/*
*
*/
t = 0;
while ( t < BOARD_SIZE ) {
y = 0;
while ( y < BOARD_SIZE ) {
printf ( "%c", board[t][y] );
y = y + 1;
}
printf ( "\n" );
t = t + 1;
}
/*
*
*/
return 0;
}
/*
*
*/
$ ./sample-014.exe oxx xoo oxx $
Download : sample-015.c
/*
* 2020/11/20 sample-015.c
*/
#include <stdio.h>
/*
* ◯×ゲームのボード (一次元版)
*
* y
* 0 1 2 (y,t)
* +-----+-----+-----+ +-----+
* 0 |(0,0)|(0,1)|(0,2)| |(0,0)| 0 = 0*3+0 = t*3+y
* +-----+-----+-----+ +-----+
* t 1 |(1,0)|(1,1)|(1,2)| |(0,1)| 1 = 0*3+1 = t*3+y
* +-----+-----+-----+ +-----+
* 2 |(2,0)|(2,1)|(2,2)| |(0,2)| 2 = 0*3+2 = t*3+y
* +-----+-----+-----+ +-----+
* |(1,0)| 3 = 1*3+0 = t*3+y
* +-----+
* |(1,1)| 4 = 1*3+1 = t*3+y
* +-----+
* |(1,2)| 5 = 1*3+2 = t*3+y
* +-----+
* |(2,0)| 6 = 2*3+0 = t*3+y
* +-----+
* |(2,1)| 7 = 2*3+1 = t*3+y
* +-----+
* |(2,2)| 8 = 2*3+2 = x*3+y
* +-----+
*
*/
#define BOARD_SIZE 3 /* ボードのサイズ */
#define SENTE_MARK 'o' /* 先手は 'o' (マル) */
#define GOTE_MARK 'x' /* 後手は 'x' (バツ) */
int main ( void ) {
/*
*
*/
char board[BOARD_SIZE][BOARD_SIZE]; /* サイズは 3 × 3 */
int t; /* 縱 */
int y; /* 横 */
/*
*
*/
printf ( "sizeof ( board[0][0] ) = %d\n",
sizeof ( board[0][0] )
);
printf ( "sizeof ( board[0] ) = %d\n",
sizeof ( board[0] )
);
printf ( "\n" );
for ( t = 0; t < BOARD_SIZE; t++ ) {
printf ( "board[%d]=%x\n", t, &board[t] );
for ( y = 0; y < BOARD_SIZE; y++ ) {
/* アドレスの表示 */
printf ( "\t(%d,%d)=%x\n", t, y, &board[t][y] );
}
printf ( "\n" );
}
/*
*
*/
return 0;
}
/*
*
*/
$ ./sample-015.exe sizeof ( board[0][0] ) = 1 sizeof ( board[0] ) = 3 board[0]=173def50 (0,0)=173def50 (0,1)=173def51 (0,2)=173def52 board[1]=173def53 (1,0)=173def53 (1,1)=173def54 (1,2)=173def55 board[2]=173def56 (2,0)=173def56 (2,1)=173def57 (2,2)=173def58 $
Download : sample-017.c
/*
* 2020/11/20 sample-017.c
*/
#include <stdio.h>
/*
* 再帰を利用した階乗の計算(既出)
*
* 1 ( n < 1 )
* n! = {
* n * { (n-1)! }
*/
int fact ( int n ) {
if ( n < 1 ) { // n が 0 の時
return 1;
} else {
return fact ( n - 1 ) * n; // 再帰を利用して計算
}
}
int main ( void ) {
/*
*
*/
int n = 5;
/*
*
*/
printf ( "fact(%d)=%d\n", n, fact(n) );
/*
*
*/
return 0;
}
/*
*
*/
$ ./sample-017.exe fact(5)=120 $
Download : sample-018.c
/*
* 2020/11/20 sample-018.c
*/
#include <stdio.h>
/*
* 仮引数変数 n のアドレスと値はどうなっているか ?
*/
int fact ( int n ) {
int f;
printf ( "(fact:前) n = %d, &n = %x\n", n, &n );
if ( n < 1 ) {
f = 1;
} else {
f = fact ( n - 1 ) * n;
}
printf ( "(fact:後) n = %d, &n = %x\n", n, &n );
return f;
}
int main ( void ) {
/*
*
*/
int n = 5;
int f;
/*
*
*/
printf ( "(main) n = %d, &n = %x\n", n, &n );
/*
*
*/
f = fact(n);
printf ( "fact(%d)=%d\n", n, f );
/*
*
*/
return 0;
}
/*
*
*/
$ ./sample-018.exe (main) n = 5, &n = 27c8c3c8 (fact:前) n = 5, &n = 27c8c39c (fact:前) n = 4, &n = 27c8c36c (fact:前) n = 3, &n = 27c8c33c (fact:前) n = 2, &n = 27c8c30c (fact:前) n = 1, &n = 27c8c2dc (fact:前) n = 0, &n = 27c8c2ac (fact:後) n = 0, &n = 27c8c2ac (fact:後) n = 1, &n = 27c8c2dc (fact:後) n = 2, &n = 27c8c30c (fact:後) n = 3, &n = 27c8c33c (fact:後) n = 4, &n = 27c8c36c (fact:後) n = 5, &n = 27c8c39c fact(5)=120 $
Download : sample-019.c
/*
* 2020/11/20 sample-019.c
*/
#include <stdio.h>
/*
* 引数のアドレスは ? ( 引数の順に並んいる )
*/
int subfunc ( int a, int b ) {
printf ( "a = %d, &a = %x\n", a, &a );
printf ( "b = %d, &b = %x\n", b, &b );
}
int main ( void ) {
/*
*
*/
subfunc ( 2, 4 );
/*
*
*/
return 0;
}
/*
*
*/
$ ./sample-019.exe a = 2, &a = b7edab7c b = 4, &b = b7edab78 $
Download : sample-020.c
/*
* 2020/11/20 sample-020.c
*/
#include <stdio.h>
/*
* 一つの引数変数から(ポインター経由で..)他の引数変数を参照する事ができる
*/
int subfunc ( int a, int b ) {
printf ( "a = %d, &a = %x\n", a, &a );
printf ( "b = %d, &b = %x\n", b, &b );
/*
* 変数 b を利用して変数 a の値が参照できる
*/
printf ( "*(&b-1) = %d, &b-1 = %x\n", *(&b-1), &b-1 );
/*
* 変数 b を利用して変数 a の値を変更(代入)できる
*/
*(&b-1) = 10;
printf ( "a = %d\n", a );
}
int main ( void ) {
/*
*
*/
subfunc ( 2, 4 );
/*
*
*/
return 0;
}
/*
*
*/
$ ./sample-020.exe a = 2, &a = 4153ca6c b = 4, &b = 4153ca68 *(&b-1) = 0, &b-1 = 4153ca64 a = 2 $
Download : sample-021.c
/*
* 2020/11/20 sample-021.c
*/
#include <stdio.h>
/*
* 先頭の引数のポインタを利用して、残りの引数を参照する
*/
int subfunc ( int a, ... ) {
printf ( "a = %d, &a = %x\n", a, &a );
printf ( "*(&a+1) = %d, &a + 1 = %x\n", *(&a+1), &a+1 );
printf ( "*(&a+2) = %d, &a + 2 = %x\n", *(&a+2), &a+2 );
}
int main ( void ) {
/*
*
*/
subfunc ( 1,2,3,4,5 );
/*
*
*/
return 0;
}
/*
*
*/
$ ./sample-021.exe a = 1, &a = e023163c *(&a+1) = 1724570528, &a + 1 = e0231640 *(&a+2) = 11051, &a + 2 = e0231644 $
Download : sample-022.c
/*
* 2020/11/20 sample-022.c
*/
#include <stdio.h>
/*
* 引数をアドレス経由で参照する
* 最初の引数 n は、他の引数の個数としての情報を担う
* 関数(のプログラム作成時)側では、
* (実行時の呼出の時に)幾つの引数が指定されるかを知る術がない
* 最初の引数 n の「値」を信じて振る舞うしかない
*/
int subfunc ( int n, ... ) {
int i;
for ( i = 0; i < n; i++ ) {
printf ( "arg[%d]=%d\n", i, *(&n+1+i) );
}
}
int main ( void ) {
/*
*
*/
printf ( "subfunc ( 5,1,2,3,4,5 );\n" );
subfunc ( 5,1,2,3,4,5 ); // 1 から 5 の追加の引数の個数を適切に指定
printf ( "subfunc ( 3,9,8,7,6 );\n" );
subfunc ( 3,9,8,7,6 ); // 4 つの追加の引数があるのに 3 としているので、最後の値は利用されない
/*
*
*/
return 0;
}
/*
*
*/
$ ./sample-022.exe subfunc ( 5,1,2,3,4,5 ); arg[0]=0 arg[1]=0 arg[2]=0 arg[3]=3 arg[4]=135889920 subfunc ( 3,9,8,7,6 ); arg[0]=0 arg[1]=0 arg[2]=0 $
Download : sample-023.c
/*
* 2020/11/20 sample-023.c
*/
#include <stdio.h>
#include "s_print.h"
/*
* 最初の引数に指定した文字列の中に 「%」があったら、後の引数の値に置き換える
*/
int print_int_with_format ( char *fmt, int a, ... ) {
int i;
int j;
j = 0;
i = 0;
while ( fmt[i] != '\0' ) { /* 文字列の終わりがくるまで */
if ( fmt[i] == '%' ) { /* '%' がきたら特別処理
printf ( "%d", *(&a+j) ); /* 追加引数の値を取り出し出力 */
j = j + 1; /* 次の引数の準備 */
} else { /* '%' 以外は.. */
s_print_char ( fmt[i] ); /* その文字をそのまま出力 */
}
i = i + 1; /* 次の文字 */
}
}
int main ( void ) {
/*
*
*/
print_int_with_format ( "%\n", 99 );
print_int_with_format ( "i = %, j = %\n", 10, 20 );
print_int_with_format ( "1 st = %, 2nd = %, 3rd = % \n", 10, 20, 90 );
/*
*
*/
return 0;
}
/*
*
*/
$ ./sample-023.exe i = , j = 1 st = , 2nd = , 3rd = $
Download : sample-024.c
/*
* 2020/11/20 sample-024.c
*/
#include <stdio.h>
#include "s_print.h"
/*
*
*/
int main ( void ) {
/*
*
*/
// printf ( "..." ); /* これまで printf は「文字列出力」専門だった */
/* 実は、もっと、凄い機能がある */
printf ( "%d\n", 99 );
// 文字列の中に「%d」をいれると、これは、その後の引数の
// 整数値引数の値に書き変わる
/*
* 引数の個数は可変長
*/
printf ( "i=%d, j=%d, k=%d\n", 10, 20, 90 );
/*
* 上と同じ事をする命令列 ( いままでは面倒な事をしていた )
*/
s_print_string ( "i=" );
s_print_int ( 10 );
s_print_string ( ", j=" );
s_print_int ( 20 );
s_print_string ( ", k=" );
s_print_int ( 90 );
s_print_newline();
/*
*
*/
return 0;
}
/*
*
*/
$ ./sample-024.exe 99 i=10, j=20, k=90 i=10, j=20, k=90 $
Download : sample-025.c
/*
* 2020/11/20 sample-025.c
*/
#include <stdio.h>
#include "s_print.h"
/*
* printf を利用してみる
*/
int main ( void ) {
/*
*
*/
printf ( "abc\n" ); /* いままでと同じ */
/* 文字列がそのままでる */
printf ( "i=%d\n", 10 );
/* 文字列の中の 「%d」の部分が、二つ目の引数
10 に変る */
printf ( "i=%d, j=%d\n", 10, 20 );
/* 「%d」が二度でれば二度めは三つ目の引数の値を利用 */
printf ( "a=%f\n", 12.34 );
/* 実数(浮動小数点数) の場合は 「%f」を使う */
printf ( "i=%d, a=%f, c=%c, s=%s\n", 123, 12.34, 'a', "abc" );
/* 混在も可能
%c が文字
%s が文字列(文字型へのポインタ値)
*/
/*
*
*/
return 0;
}
/*
*
*/
$ ./sample-025.exe abc i=10 i=10, j=20 a=12.340000 i=123, a=12.340000, c=a, s=abc $
Download : sample-026.c
/*
* 2020/11/20 sample-026.c
*/
#include <stdio.h>
#include "s_print.h"
/*
* printf の更なる機能 : 書式付きの出力
*/
int main ( void ) {
/*
* 同じ数値を異る形式(書式 / format)で出力できる
*/
printf ( "a=%10.6f\n", -12.34 );
/* 出力する形式を指定できる 10.6 は、全体 10 桁、小数点以下 6 桁の意味 */
printf ( "a=%20.10f\n", -12.34 );
/* 出力する形式を指定できる 20.10 は、全体 20 桁、小数点以下 10 桁の意味 */
/*
*
*/
return 0;
}
/*
*
*/
$ ./sample-026.exe a=-12.340000 a= -12.3400000000 $
Download : sample-027.c
/*
* 2020/11/20 sample-027.c
*/
#include <stdio.h>
#include "s_print.h"
/*
* scanf, printf (出力関数) の入力版
*/
int main ( void ) {
/*
*
*/
int i;
/*
*
*/
printf ( "i の値を入力してください " );
scanf ( "%d", &i ); /* '%d' --> printf と同じ */
/* i = s_input_int(); */
/*
i = 99;
の時
scanf ( "%d", i );
は、
scanf ( "%d", 99 );
の意味。
これでは、scanf はどうやっても i の値を得る事ができない。
そこで、「&i」を指定 ( i のポインタ値がわかれば、 i の値が変更できる )
*/
/*
*
*/
printf ( "入力された i の値は %d でした\n", i );
/*
*
*/
return 0;
}
/*
*
*/
10
$ ./sample-027.exe < sample-027.in i の値を入力してください 10 入力された i の値は 10 でした $
/*
* 課題 20211119-02
*
* 20211119 20211119-02-QQQQ.c
*
* 文字列の途中に文字を挿入する
*
* 利用方法
* コンパイル
* cc -o BASENAME.exe 20211119-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| ? | ? | ? | ? |
"abcde" => "abcXde"
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
cary|'a'|'b'|'c'|'X'|'d'|'e'|EOS| ? | ? | ? |
cary|'a'|'b'|'c'|'d'|'e'|EOS| ? | ? | ? | ? |
↓ ↓ ↓ \ \ \
cary|'a'|'b'|'c'|'X'|'d'|'e'|EOS| ? | ? | ? |
cary[4] <- cary[3] ('d')
cary[5] <- cary[4] ('e')
cary[6] <- cary[5] (EOS)
[だめ]
cary[4] = cary[3]
cary[5] = cary[4]
cary[6] = cary[5]
=> 'd' がたくさんコピーされる
cary|'a'|'b'|'c'|'d'|'d'|'d'|'d'| ? | ? | ? |
[適切]
cary[6] = cary[5]
cary[5] = cary[4]
cary[4] = cary[3]
うしろから、コピーを開始する必要がある
*/
int i;
int l;
printf ( "最初の cary = %s\n", cary );
/*
汎用ではないが、思い通りに動くコード
cary[6] = cary[5];
cary[5] = cary[4];
cary[4] = cary[3];
cary[3] = 'X';
*/
/*
文字列 "abcde" の入った文字配列 cary の
3 文字目 ('c') と 4 文字目 'd' の間に、一文字 'X' を入れる
*/
/* 文字列の長さを求める */
/* 後ろからコピーするので、「一番後ろ文字」の位置 */
/* l に文字列の長さ ( l = 5 になる ) */
/* EOS のある場所(添え字)が、長さ */
for ( l = 0; cary[l] != EOS; l++ ) {
/* なにもしなくてよい.. (l++) が目的なので.. 何もなし */
}
/*
for 構文を終了するのは、くり返し条件
cary[l] != EOS
が成立しなかった場合なので、現時点で、
cary[l] == EOS
が成立している
l が cary が表す文字列の長さを表している
*/
/* cary の中の文字列の長さは、変数 l に入る */
for ( i = l; 3 <= i; i-- ) { /* 後ろからコピーする必要がある */
/* i = (l =) 5,4,3 */
cary[i+1] = cary[i];
/*
cary[5+1] = cary[5] ( cary[6] = cary[5] )
cary[4+1] = cary[4] ( cary[5] = cary[4] )
cary[3+1] = cary[3] ( cary[4] = cary[3] )
*/
}
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;
}
/*
* 20211119-03-QQQQ.c
* 一行分の文字列を入力して、その中の英小文字を全て英大文字に変換する
*/
#include <stdio.h>
/*
* islower (ch) : 指定された文字が、英小文字かどうかを判定する
*/
int islower ( int ch ) {
/*
char 型は小さな整数
その値を変数でうけるときには、
int 型にする事が多い
*/
return 'a' <= ch && ch <= 'z'; /* 'a' 〜 'z' なら小文字 */
/*
if 構文の所の条件の式
C 言語では、「条件式」は、「整数式」
0 => 偽 (False) / 不成立
0 以外 => 真(True)/成立
&& : 論理積 ( A && B : A と B がともに真(0でない)時に真(1)になる )
*/
}
/*
* toupper ( ch ) : 指定された文字が、英小文字なら英大文字に変換
*/
int toupper ( int ch ) {
if ( islower ( ch ) ) { /* 小文字だった.. */
/*
ch 返す値
'a' (97) 'A' (65) 97 -> 65 (-32)
'b' (98) 'B' (66) 98 -> 66 (-32)
..
'z' (122) 'Z' (90) 122 -> 90 (-32)
英小文字の時には、
元の文字の ASCII コードから 32 を引いた値を返せばよい
それ以外は ch の値をそのまま返す
*/
return ch - ( 'a' - 'A' ); /* ch = 'a' の時
'a' - ( 'a' - 'A' )
= 'a' - 'a' + 'A'
= ('a' - 'a') + 'A'
= 0 + 'A'
= 'A'
*/
} else { /* そうでないなら */
return ch; /* そのまま返す */
}
}
/*
* main
*/
#define EOS '\0' /* EOS を定義 */
#define LINE_SIZE 128 /* 入力するのに十分に大きなサイズにする */
int main ( void ) {
char line[LINE_SIZE];
int i;
printf ( "小文字を含んだ文字列を入力してください : " );
/* 改行が入力されるまで、文字を読み込み、
読み込んだ文字を、配列に保存する */
i = 0;
line[i] = getchar(); /* 一文字読み込む */
while ( line[i] != '\n' ) {
i++;
line[i] = getchar(); /* 次の文字を読み込む */
}
/*
line[i] には、'\n' が入っている
0?i-1 には、読み込んだ文字が入っている
i は、読み込んだ文字の個数を表す.
例:
キーボードから「abc[Enter]」とすると
i = 3
line[0] = 'a'
line[1] = 'b'
line[2] = 'c'
line[3:i] = '\n'
*/
line[i] = EOS; /* 改行を削って、文字列として扱えるようにする */
for ( i = 0; line[i] != EOS; i++ ) {
line[i] = toupper ( line[i] ); /* 小文字を大文字に変換 */
}
printf ( "結果 : 「%s」\n", line );
return 0;
}
/*
* 20211126-01-QQQQ.c
* キーボードから一行の文字列を入力し、その中にある 'a' の個数を出力する
*/
#include <stdio.h>
#define LINE_SIZE 128 /* 入力する文字列の長さ */
#define EOS '\0' /* End Of String (文字列の終り) */
/*
* main
*/
int main ( void ) {
char line[LINE_SIZE]; /* 入力する文字列を保存する文字配列 */
/* EOS を含め LINE_SIZE だけ入力する */
int colomun; /* 現在、見ている文字列の中の文字の位置 */
int count = 0; /* 文字列内に含まれる 'a' の個数 */
printf ( "キーボードから一行の文字列を入力してください : " );
/* 標準入力(stdin : キーボード)から一行入力する */
/*
コードの差し替え
gets(line);
お勧めしない
お勧めは
fgets(line,LINE_SIZE,stdin)
これは、まだ、説明しそこねた回の内容なので、
今日は、紹介できない
*/
i = 0;
line[i] = getchar(); /* 一文字読み込む */
while ( line[i] != '\n' ) {
i++;
line[i] = getchar(); /* 次の文字を読み込む */
}
/*
このコードは gets と同じで、良くない。
理由:
配列サイズより長い文字列が入力されると、
(宣言していない要素まで参照しようとするので..)
よくない
*/
for ( colomun = 0; colomun < LINE_SIZE; colomun++ ) {
/* 入力された文字列の最初(0)から最後(LINE_SIZE-1)まで.. */
/* 実際は、途中に EOS があるので、途中で抜けてしまう.. */
if ( line[colomun] == EOS ) {
/* 途中で、EOS を発見したら.. (文字列の終りなので..) */
break; /* for 構文から抜けてしまう */
/* この部分の説明は、後日 */
} else if ( line[colomun] == 'a' ) {
/* 'a' を発見したので.. */
/* 個数を増やす */
count++; /* count = count + 1 */
/*
文字列の中の要素(文字)を処理するのに、
文字配列を活用する事ができる
*/
} /* else {} */ /* 他の文字の場合は何もしない.. */
}
printf ( "入力の中には %d 個の 'a' が含まれていました\n", count );
return 0;
}
/*
C 言語において、文字列の処理を行う場合は、
文字配列を利用するのが定番になっている
!! Fortran/Basic/Pascal <= 数値を処理する言語
!! => C 言語
!! 文字列が処理できる言語
!! => 情報処理が可能
*/
#include <stdio.h>
int main(int argc, char *argv[]) {
int a[3];
int i;
/*
配列の要素を添え字([式])を利用して参照
*/
for ( i = 0; i < 3; i++ ) {
a[i] = i * 10;
/*
a[0] = 0*10 = 0
a[1] = 1*10 = 10
a[2] = 2*10 = 20
*/
}
for ( i = 0; i < 3; i++ ) {
printf ( "a[%d] = %d\n", i, a[i] );
}
/*
「*」と、「整数を加える操作」を組み合わせる
配列名[式] <=> *( 配列名 + (式) )
*/
for ( i = 0; i < 3; i++ ) {
printf ( "*(a+%d) = %d\n", i, *(a+i) );
}
*(a+1) = 100; /* *(a+1) <-> a[1] */
printf ( "a[1] = %d\n", a[1] );
return 0;
}
#include <stdio.h>
/*
指定された整数型の配列の内容を表示する
*/
void print_ary ( int ary[3], int size ) {
/*
一つ目の引数は、
配列名
である事を示すが、その配列サイズは未定でよい
二つ目の引数は、
表示する要素の個数
を表す。
=> 配列のサイズとは独立に指定できる
!! 配列のサイズより小さい必要はある
*/
int i;
for ( i = 0; i < size; i++ ) {
printf ( "配列[%d] = %d\n", i, ary[i] );
}
}
int main(int argc, char *argv[]) {
int a[3];
int i;
for ( i = 0; i < 3; i++ ) {
a[i] = i * 10;
}
printf ( "size = 3\n" );
print_ary ( a, 3 ); /* 配列名と配列のサイズ */
printf ( "\nsize = 2\n" );
print_ary ( a, 2 ); /* 配列名と表示する要素数 */
printf ( "\nsize = 4\n" );
print_ary ( a, 4 ); /* 配列のサイズより大きな個数を指定 */
/* ココでは、不適切な指定 */
return 0;
}
#include <stdio.h>
/*
指定された整数型の配列の内容を表示する
*/
#define ARRAY_SIZE 3
#define ARRAY_SIZE_2 5
/*
この print_ary の実装は、
配列のサイズを固定する事により、
配列の要素を、もとの配列のサイズを超えて参照するようなミスを
未然に防ぐ事
ができる
しかし、その結果として、柔軟性がなくなっている
1. 表示する個数が固定されている
2. 対応する配列も、その固定サイズより小さいものはダメ
*/
void print_ary ( int ary[ARRAY_SIZE] ) {
int i;
for ( i = 0; i < ARRAY_SIZE; i++ ) {
printf ( "配列[%d] = %d\n", i, ary[i] );
}
}
int main(int argc, char *argv[]) {
int a[ARRAY_SIZE];
int b[ARRAY_SIZE];
int c[ARRAY_SIZE_2]; /* サイズが a, b とことなる */
int i;
for ( i = 0; i < ARRAY_SIZE; i++ ) {
a[i] = i * 10;
b[i] = i * i;
}
for ( i = 0; i < ARRAY_SIZE_2; i++ ) {
c[i] = 100 - i;
}
printf ( "配列 a の内容\n" );
print_ary ( a ); /* 配列名だけを指定 */
/* サイズは固定(間違える要因がない) */
printf ( "配列 b の内容\n" );
print_ary ( b ); /* 配列名だけを指定 */
printf ( "配列 c の内容\n" );
print_ary ( c ); /* 配列名だけを指定 */
return 0;
}
#include <stdio.h>
/*
指定された整数型の配列の内容を表示する
*/
void print_ary ( int ary[], int size ) {
int i;
for ( i = 0; i < size; i++ ) {
printf ( "配列[%d] = %d\n", i, ary[i] );
}
}
void setup_ary ( int ary[], int size ) {
int i;
for ( i = 0; i < size; i++ ) {
ary[i] = i * i;
/*
ary[0] = 0;
ary[1] = 1;
ary[2] = 4;
*/
}
}
int main(int argc, char *argv[]) {
int a[3];
int i;
for ( i = 0; i < 3; i++ ) {
a[i] = i * 10;
/*
a[0] = 0;
a[1] = 10;
a[2] = 20;
*/
}
print_ary ( a, 3 );
/*
a[0] = 0;
a[1] = 10;
a[2] = 20;
*/
setup_ary ( a, 3 );
/*
関数で行った、配列要素の書きかえが
引数で指定した、配列の要素の書きかえになっている
!! これまでは、関数の引数はコピーなので、
!! それを書き替えても、呼び出し元には影響しない
!! この結果は、「あたかも、引数指定した配列の書きかえが起きている」ようにみえる
!! 実は、勘違い
!! 1. 「配列を渡す」ではなく
!! 「配列名(の値)」を渡している
!! # 確認の方法はともかく、
!! # 配列名の値は変化していない
!! !! ましてや、「配列の要素」を渡しているわけでもない
!! !!!! 最初の高級言語 Fortran で、すでに配列が導入される
!! !!!! この時は、「変数」が渡される
!! !!!! 引数に変数名を指定すると、
!! !!!! よびだした先でその引数の値を変更すると、
!! !!!! 呼び出し元の変数の値も変更される
!! 2. 配列の要素は、「配列名」を経由して、参照される
!! => これは、呼び出し元でも呼び出し先でも、同じものになるので、
!! # 引数では(直接は..)わたしていない
*/
print_ary ( a, 3 );
/*
a[0] = ?
a[1] = ?
a[2] = ?
*/
return 0;
}
#include <stdio.h>
int main(int argc,char *argv[]) {
char s[10];
/*
文字列 「"abc"」
=> 四つの文字からなる
'a', 'b', 'c', '\0' (EOS)
*/
s[0] = 'a';
s[1] = 'b';
s[2] = 'c';
s[3] = '\0'; /* EOS : End Of String */
printf ( "文字列 = 「%s」\n", "abc" );
/* 「%s」は、『文字列』を表示する書式 */
printf ( "文字配列 = 「%s」\n", s );
/* 文字配列は、文字列のようにふるまう */
printf ( "文字列[1]=%c\n", "abc"[1] );
printf ( "文字配列[1]=%c\n", s[1] );
/* 配列と文字列の類似性質 */
s[1] = 'B';
printf ( "文字配列 = 「%s」\n", s );
/* "abc"[1] = 'B';*/ /* <= これはだめ */
return 0;
}
#include <stdio.h>
#define EOS '\0'
void print_string ( char s[] ) {
/*
配列名は指定するが、サイズは指定していない
=> 表示する範囲は、EOS までなので、
表示するサイズを指定する事ができないし、する必要もない
*/
int i;
for ( i = 0; s[i] != EOS; i++ ) {
putchar ( s[i] );
}
}
int main(int argc, char *argv[]) {
char s[10];
s[0] = 'a';
s[1] = 'b';
s[2] = 'c';
s[3] = EOS;
/*
s[0] s[1] s[2] s[3]
'a' 'b' 'c' EOS
"abc"
*/
print_string ( s );
putchar ( '\n' );
print_string ( "abc" );
putchar ( '\n' );
s[1] = EOS;
/*
s[0] s[1] s[2] s[3]
'a' EOS 'c' EOS
"a"
*/
print_string ( s );
putchar ( '\n' );
s[1] = 'B';
/*
s[0] s[1] s[2] s[3]
'a' 'B' 'c' EOS
"aBc"
*/
print_string ( s );
putchar ( '\n' );
s[3] = 'x';
s[4] = EOS;
/*
s[0] s[1] s[2] s[3] s[4]
'a' 'B' 'c' 'x' EOS
"aBcx"
*/
print_string ( s );
putchar ( '\n' );
return 0;
}
/*
* 課題 20211119-02
*
* 20211119 20211119-02-QQQQ.c
*
* 文字列の途中に文字を挿入する
*
* 利用方法
* コンパイル
* cc -o BASENAME.exe 20211119-02-QQQQ.c
* 実行
* ./BASENAME.exe
*/
#include <stdio.h>
/*
*
*/
/*
* main
*
*/
#define CSIZE 10
#define EOS '\0'
void insert_char ( char cary[], int pos, char ch ) {
int i;
int l; /* 文字列の長さ */
for ( l = 0; cary[l] != EOS; l++ ) {
/* なにもしなくてよい.. (l++) が目的なので.. 何もなし */
}
for ( i = l; pos <= i; i-- ) {
cary[i+1] = cary[i];
}
cary[pos] = ch;
}
int main( int argc, char *argv[] )
{
char cary[CSIZE] = { 'a', 'b', 'c', 'd', 'e', EOS };
printf ( "最初の cary = %s\n", cary );
insert_char ( cary, 3, 'X' );
printf ( "'X' を挿入した結果 : %s\n", cary );
insert_char ( cary, 1, 'Y' );
printf ( "'Y' を挿入した結果 : %s\n", cary );
return 0;
}
[?O?????e]
?u?z??v?????? ?
?z???
int a[3];
1. a[0], a[1], a[2] ?O???????^???????g?????????
cf.
int v;
=> ????????^?????????p?????
2. ?ua?v??????w?z??x?????p?????
=> ?Y????(?u[??]?v)??z???????????A
?z???v?f a[0], a[1], a[2] ???Q??????
cf.
int v0, v1, v2;
=> ?O???????^?????????p????邪
?z??????????????
=> ?Y??????????????
# ?z?????p
# ?Y?????????u??(???)?v?????????
# => ?_??????鏈?????????
!!! ?u?@?\?v??????????????A
!!! ?u?R?[?h(?v???O????)?v???K?v
!!! ?u?R?[?h?v?????????u?f?[?^?v??S???鎖???????
!!! ?u?R?[?h?v:?v???O????????????????
!!! ?u?f?[?^?v:?v???O????????s???????????m????
!!! => ?@?\????????s???????鎖???????
!!! => ?@?\??u?_???v?????????鎖??
!!! <= ?f?[?^??u?_???v???炭??
?w?z??x??p????A?v?f???Q???????@
?z??[??] : ??{
?z??[??] <=> *(?z??+(??))
?u?z??[??]?v?????A?u?z??v???????????????????????
?u*(?z??+(??))?v?????A?u?z??v???u?v?Z????v?????????
??????w?l?x????????????u?l???鎖?v???????
=> ????? C ??????A?u?w?z??x???w?l???????????x?v
?w?l?x????A????????????A???l??????
??????????????
????????????A?z????w????????U????
?z???Y???????A
?z???T?C?Y??????????l???w???鎖???????????
!!!! <= ?z??T?C?Y???A????Y???????^???????????A
!!!! (?????A?????炭??s?K???w?????..) ?G???[?????`?F?b?N?????
!!!! ?????????A????????????????? ( ?? : java )
!!!! ?????AC ???????????A
!!!! ?Y?????????`?F?b?N??s?????
!!!! => ??????(?z???T?C?Y??????)?Y???????w??????A?G???[???????
!!!! <= ?v???O???}???A?Y??????????C???????K?v??????
!!!! => ????C???t????????X?N(???_)??????
!!!! <= ???X?N???e?C?N???鎖???????_??(?????b?g)??????
!!!! => ?????b?g: ?z????????????????A?z???T?C?Y???w??????????
??????????z????w?????
1. ?z???T?C?Y???????????????????
=> ?F?X??T?C?Y??z???A???p?????????????鎖???????
<= ?z??T?C?Y?????A???p??? ( ?T?C?Y????????K?v?????? ) ???????????(?]???? ? => ?K?{??.. ) ?w????
2. ?Y??????w??????A?z???T?C?Y????????????鎖??A
?v???O???}??d??
==
?z????????
?u??????v??? ?
????????т?????.. ?????????..
char ??????z??u??????v ?
???? Yes ??????? No ???????
Yes : ?u??????v?? ?uchar ??????z??v??u?????v????????
char ??????z??????邱???u??????v????????
?u??????v???uchar ??????z??v??*??*?????????
?v?f???X????????
?u?\???v: ?????f?[?^??????????A?Y??????Q??????
???????????????????A
?z??A?u????v????т????
?????
???????A?u???v?????
???????鎖???????
(?Q???d??)??????????A?u?????v(?????????????)???
?w??????x???A??????????????т?l???A
?z????????????e?????o?????????邪?A
??X???????
!! ?w??????x??AC ??????A
!! ???????^??z?????????????????A
!! ?z???T?C?Y??A?????????? + 1
!! ??X??v?f??A??????f?[?^???????A??X?????????????????
!! ??????????A?u??????^?v?????????
!! ????????????A?u???????????z??^?v????????
!! ?u????v??u(?l????X???????A???)????v
No : ?t??^?????(char ??????z??A?????????????)
?u??????????z??v???A?w??????x???????????A
?z???v?f???u?????v??l??????????????A
???????I????\?? EOS ??????????K?v??????
char ???????z???v?f?????????? EOS(\0)???????u?????????l??U?????v
C ?????R???p?C?????A?u??????v????????????????
??????z???p???鎖????A
?????????????F?X??\???
?z????????
?z?????????????A????v?f???????????鎖???????
<= ?u????v?????
????????????`????A?u??????v????鎖????????
?????A??????????????A???p?????
??????????v?f??l??????A{} ?????
?z??T?C?Y???A??????????l????????????A
?w????????????????????????A?c???s??
?????????s?????????A?z??T?C?Y???????\
??????A?z??T?C?Y??A??????????l????????
課題プログラム内の「/*名前:ここ*/」の部分を書き換え「/*この部分を完成させなさい*/」の部分にプログラムを追加して、プログラムを完成させます。
Download : 20211203-01.c
/*
* 20211203-01-QQQQ.c
* 文字列の並び(文字列列)
* 一つの文字配列に複数の文字列を保存する
* 大きな文字配列に(空文字列でない)複数の文字列を納める
* 文字列列の最後には空文字列をいれ、それは文字列列の一部としない
* 例:
* "abc", "x", "12" <=> "abc\0x\012\0"
*
*/
#include <stdio.h>
#include <string.h> /* strcmp を利用するので.. */
/*
*
*/
#define EOS '\0'
#define NO_STRING (-1) /* 「文字列がもうない」事を表す数値 */
/*
* print_string_seq
* 文字列列の出力
*/
void print_string_seq ( char sseq[] ) {
int i; /* 現在、参照している場所 */
for ( i = 0; sseq[i] != EOS; i++ ) { /* まだ文字列がある.. */
putchar ( '"' );
while ( sseq[i] != EOS ) { /* 文字列を出力する */
putchar ( sseq[i] ); /* 文字の出力 */
i++; /* 次の文字 */
}
putchar ( '"' );
if ( sseq[i+1] != EOS ) { /* 未だ、次の文字列がある */
printf ( ", " ); /* 区切り文字を出力 */
} else {
printf ( "\n" ); /* 行末の改行を出力 */
}
}
}
/*
* int next_string_seq ( char sseq[], int now )
* 次の文字列の場所を返す
*/
int next_string_seq ( char sseq[], int now ) {
if ( sseq[now] == EOS ) { /* 先頭が空文字列だった */
return now; /* それ以上は、進まない */
}
while ( sseq[now] != EOS ) { /* 先頭の文字列をスキップする */
/* 次の場所を見る */
/*
** この部分を完成させなさい
*/
}
/* ここで、now は、先頭の文字列の最後尾の EOS の位置 */
return now + 1; /* +1 する事により、次の文字列の先頭の場所となる */
}
/*
* int find_string_seq ( char sseq[], int now, char string[] )
* 文字列の場所を探す
*/
#define NOT_FOUND (-1) /* 「発見できなかった」事を表す数値 */
int find_string_seq ( char sseq[], int now, char string[] ) {
if ( string[0] == EOS ) { /* 探す文字列が空文字列 */
/* 定義(文字列列には、空文字列を含めない)より、含まれない */
return NOT_FOUND; /* 見付からなかった */
}
while ( sseq[now] != EOS ) { /* 空文字列でない限り */
if ( !strcmp ( sseq + now, string ) ) {
/* 文字列が一致した */
return now; /* 現在の場所を返す */
} else {
/* 次の場所を見る */
/*
** この部分を完成させなさい
*/
}
}
/* 最後までみたが、見付からないかった */
return NOT_FOUND;
}
/*
* main
*/
int main ( void ) {
char sseq[] = "12\0abc\0XY\0abc\0"; /* 文字列列を準備 */
int pos; /* 文字列の場所 */
printf ( "sseq = \"%s\"\n", sseq ); /* 先頭の文字列しか表示されない */
print_string_seq ( sseq ); /* 複数の文字列が表示される */
/* 文字列を一つずつ取り出して、場所の文字列の表示 */
for ( pos = 0; sseq[pos] != EOS; pos = next_string_seq ( sseq, pos ) ) {
printf ( "sseq %d = %s\n", pos, sseq + pos );
}
/* 文字文字列中に含まれる "abc" の場所を順に表示する */
for ( pos = 0; pos != NOT_FOUND; pos = find_string_seq ( sseq, pos, "abc" ) ) {
printf ( "%d\n", pos );
pos = next_string_seq ( sseq, pos );
}
return 0;
}
$ ./20211203-01-QQQQ.exe sseq = "12" "12", "abc", "XY", "abc" sseq 0 = 12 sseq 3 = abc sseq 7 = XY sseq 10 = abc 0 3 10 $