Download : sample-001.c ( utf8 版 )
/* * 2016/11/11 sample-001.c */ /* * sizeof 演算子 * 型名を指定する事により、そのサイズ(byte 単位)を得る事ができる * * 利用方法 * コンパイル * cc -I../include -o sample-001.exe sample-001.c * 実行 * ./sample-001.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-001.exe sizeof ( char ) = 1 sizeof ( int ) = 4 sizeof ( double ) = 8 $
Download : sample-002.c ( utf8 版 )
/* * 2016/11/11 sample-002.c */ /* * sizeof 演算子 * 変数名を指定する事により、そのサイズ(byte 単位)を得る事ができる * * 利用方法 * コンパイル * cc -I../include -o sample-002.exe sample-002.c * 実行 * ./sample-002.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-002.exe sizeof ( cvar ) = 1 sizeof ( ivar ) = 4 sizeof ( dvar ) = 8 $
Download : sample-003.c ( utf8 版 )
/* * 2016/11/11 sample-003.c */ /* * sizeof 演算子 * 配列名を指定する事により、そのサイズ(byte 単位)を得る事ができる * type array[SIZE] の時 sizeof( array ) = sizeof(type) * SIZE * * 利用方法 * コンパイル * cc -I../include -o sample-003.exe sample-003.c * 実行 * ./sample-003.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-003.exe sizeof ( cary ) = 100 sizeof ( iary ) = 400 sizeof ( dary ) = 800 $
Download : sample-004.c ( utf8 版 )
/* * 2016/11/11 sample-004.c */ /* * sizeof 演算子 * 値を指定する事もできる * * 利用方法 * コンパイル * cc -I../include -o sample-004.exe sample-004.c * 実行 * ./sample-004.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-004.exe sizeof ( 'a' ) = 4 sizeof ( 123 ) = 4 sizeof ( 12.3 ) = 8 $
Download : sample-005.c ( utf8 版 )
/* * 2016/11/11 sample-005.c */ /* * sizeof 演算子 * 式のサイズも得られる * char 型のデータは、計算の時に、int 型に昇格する * * 利用方法 * コンパイル * cc -I../include -o sample-005.exe sample-005.c * 実行 * ./sample-005.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-005.exe sizeof ( ch ) = 1 sizeof ( ch + dh ) = 4 $
Download : sample-006.c ( utf8 版 )
/* * 2016/11/11 sample-006.c */ /* * 型の昇格 * int 型から double 型への変換 * * 利用方法 * コンパイル * cc -I../include -o sample-006.exe sample-006.c * 実行 * ./sample-006.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-006.exe sizeof ( num ) = 4 sizeof ( num + 'A' ) = 4 sizeof ( num + mum ) = 4 sizeof ( num + 1.0 ) = 8 $
Download : sample-007.c ( utf8 版 )
/* * 2016/11/11 sample-007.c */ /* * 型の変換 * 代入では、必要に応じて型変換が行わる * * 利用方法 * コンパイル * cc -I../include -o sample-007.exe sample-007.c * 実行 * ./sample-007.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-007.exe ch = A num = 65 fp = 65.000000 $
Download : sample-008.c ( utf8 版 )
/* * 2016/11/11 sample-008.c */ /* * 型の変換 * サイズの大きい方から、小さい方への変換は危険 * * 利用方法 * コンパイル * cc -I../include -o sample-008.exe sample-008.c * 実行 * ./sample-008.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 => 256 なので、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-008.exe [適切な値] ch = 'A' [65] num = 65 fp = 65.000000 [char に大きな値] ch = '?' [-24] num = 1000 [int に大きな値] ch = ' ' [0] num = -2147483648 fp = 1000000000000.000000 $
/* * 課題 20161028-01 * * 2016/10/28 20161028-01-QQQQ.c * * 浮動小数点数の配列の要素内の数値の総和を求める。 */ #include <stdio.h> /* * 浮動小数点数の配列の要素内の数値の総和を求める。 * * 利用方法 * コンパイル * cc -o BASENAME.exe 20161028-01-QQQQ.c * 実行 * ./BASENAME.exe */ #include <stdio.h> /* * double dsum ( double ary[], int size ) * 浮動小数点数の配列の要素内の数値の総和を求める関数 * double ary[]; 総和を求める要素を含む配列 * int size; 配列のサイズ */ double dsum ( double ary[], int size ) { /* ary[] の中がかかれていない */ /* サイズは、別に渡す必要があり、その情報は、 第二引数の size で渡している */ /* ary には、先頭の場所に関する情報(ポインター値)だけしかわたらない */ double sum = 0.0; /* 総和は最初は 0 */ int i; /* 配列の要素を参照する添字変数 */ /* 目的: ary[0] + ary[1] + ... + ary[size-1] -> sum に記録したい もし、size が 3 であれば、 sum = ary[0] + ary[1] + ary[2] とすればよい。 一般的には sum = ary[0] + ary[1] + ... + ary[size-1] size は、その時によって異なる 後から指定する しなきゃいけないので、面倒だし、複雑になる その時にすればよいので、汎用性が高い [Step 0] sum = ary[0] + ary[1] + ... + ary[size-1] [Step 1] 命令の長さが可変なものは、プログラムでかけない 同じ長さの命令の繰り返しであらわす (そのかわりに、繰り返し回数を可変にする) sum = ary[0] sum = sum + ary[1] sum = sum + ary[2] ... sum = sum + ary[size-1] [Step 2] 繰り返しで、問題を解く場合は、例外を減らす sum = 0.0 sum = sum + ary[0] sum = sum + ary[1] sum = sum + ary[2] ... sum = sum + ary[size-1] [Step 3] 命令の中の変化する部分は、変数にしてしまう sum = 0.0 i = 0 sum = sum + ary[i] i = 1 sum = sum + ary[i] i = 2 sum = sum + ary[i] ... i = size-1 sum = sum + ary[i] [Step 4] 変数の変化を規則的な命令で実現する sum = 0.0 i = 0 sum = sum + ary[i] i = i + 1 sum = sum + ary[i] i = i + 1 sum = sum + ary[i] ... i = i + 1 sum = sum + ary[i] i = i + 1 [Step 5] while にしてしまう sum = 0.0 i = 0 while ( i < size ) { sum = sum + ary[i] i = i + 1 } [Step 6] for にしてしまう sum = 0.0 for ( i = 0: i < size; i = i + 1 ) { sum = sum + ary[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 ); /* ** この部分を完成させなさい */ scanf ( "%lf", &data[i] ); } sum = dsum ( data, ARY_SIZE ); /* 引数は、配列名(ポインター値) と、そのサイズの両方を指定する */ printf ( "入力されたデータの総和は %f です。\n", sum ); return 0; } /* 2, 4, 6, 8, ... 2 2 2 a_0 = 2 a_{n+1} = a_{n} + 2 a_{n} = 2n
/* * 課題 20161028-02 * * 20161028 20161028-02-QQQQ.c * * 文字列の途中に文字を挿入する * * 利用方法 * コンパイル * cc -o BASENAME.exe 20161028-02-QQQQ.c * 実行 * ./BASENAME.exe */ #include <stdio.h> /* * */ /* * main * */ #define CSIZE 10 #define EOS '\0' /* 課題 "abcd" -> "abXcd" */ 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| ? | ? | ? | ? | cary[3] に 'X' を入れたい そのためには、cary[3] を空き部屋にしたい cary[4] 以後を移動する必要がある cary|'a'|'b'|'c'| ? |'d'|'e'|EOS| ? | ? | ? | [step 0] cary[6] = EOS cary[5] = 'e' cary[4] = 'd' [step 1] cary[6] = cary[5] cary[5] = cary[4] cary[4] = cary[3] [step 2] i=5 cary[i+1] = cary[i] i = i - 1 cary[i+1] = cary[i] i = i - 1 cary[i+1] = cary[i] i = i - 1 [step 3] for ( i = 5; i >= 3; i-- ) { cary[i+1] = cary[i] } この 5 は、実は元の文字列の長さ 変数 l にいれる [step 3] for ( i = l; i >= 3; i-- ) { cary[i+1] = cary[i] } */ int i; int l; printf ( "最初の cary = %s\n", cary ); /* 文字列 "abcde" の入った文字配列 cary の 3 文字目 ('c') と 4 文字目 'd' の間に、一文字 'X' を入れる */ /* 新しい文字列の長さを求める */ /* 変数 l に入れる */ for ( l = 0; cary[l] != EOS; l++ ) { /* 中身の部分は空っぽでよい */ /* 変数 l の値を変更する事が目的 */ } /* l には、元の文字列の長さが入る */ /* cary の中の文字列の長さは、変数 l に入る */ for ( i = l; 3 <= i; i-- ) { /* 後ろからコピーする必要がある */ /* ** この部分を完成させなさい */ } /* | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | cary|'a'|'b'|'c'|'d'|'d'|'e'|EOS| ? | ? | ? | ? | ^ | ' X' cary|'a'|'b'|'c'|'X'|'d'|'e'|EOS| ? | ? | ? | ? | */ 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; }
/* p-001.c : 構造体のデータを関数に渡す */ #define ARRAY_SIZE 1000 typedef struct { int array[ARRAY_SIZE]; /* int array0; int array1; .. int array999; */ } Array; int add2 ( Array ary ) { /* 配列を要素とする、構造体(を利用して作った型)のデータを渡す */ return ary.array[0] + ary.array[1]; } int main(int argc, char *argv[] ) { Array a; printf ( "%d\n", add2( a ) ); }
/* p-002.c : 配列のデータを関数に渡す */ #define ARRAY_SIZE 1000 int add2 ( int ary[ARRAY_SIZE] ) { /* 配列を直接渡しているように見える */ return ary[0] + ary[1]; } int main(int argc, char *argv[] ) { int a[ARRAY_SIZE]; printf ( "%d\n", add2( a ) ); } /* 機能的は、確かに、 p-001.c (構造体) と p-002.c (配列) では、同じ 性能的には、ぜんぜん違う p-001.c のほうは、構造体のサイズが大きくなると、時間がかかる p-002.c のほうは、配列のサイズがおおきくなっても、時間は変化しない */
#include <stdio.h> /* データを組み合わせて、複雑な構造を持つデータ作る仕組み 構造体 : 異なる型(対象が同じなら同じ型)のものをまとめる 配列 : 同じ型のものまとめる 構造体: typedef を利用して、新しい型が作れる # 構造体は、型を作る仕組みとだけ利用する 配列: 同じ型を組み合わせただけけでなく、そのまま変数に利用する */ typedef struct { int age; /* 年齢 */ char *name; /* 名前 */ char *address; /* 住所 */ } Person; /* 個人情報 */ int main(int argc, char *argv[]) { Person kurino = { 0, "栗野俊一", "??" }; /* 構造体を使っているが、typedef 経由なので表にでない */ Person room2016[60] = { /* 学籍番号 1 */ { 19, "赤木..", "?? }, /* 学籍番号 2 */ { 19, "伊藤..", "?? }, ... }; /* 配列は、直接現れている */ /* typedef Person Romm[60]; Room room2016; と、typedef 経由で型定義をする事はできるのだが.. C 言語では、あまりしない */ }
#include <stdio.h> int sub ( int ary[100] ) { /* ????(????) ary ??A?z??????U???? */ return ary[0] + ary[1]; } int main(int argc, char *argv[] ) { int ary[100] = { 1, 2, }; printf ( "%d\n", sub ( ary ) ); /* ?z?? ?uary?v???????w???鎖??????? */ /* ??????????A ?l(????????????A?????l???v?Z?????)???w????B ??????????A????l???R?s?[????? => ary ????l?????? */ return 0; }
#include <stdio.h> void sub ( int a[100] ) { printf ( "a=%p\n", a ); printf ( "a[0]=%d\n", a[0] ); printf ( "a[1]=%d\n", a[1] ); } int main(int argc, char *argv[] ) { int ary1[100] = { 1, 2, }; int ary2[100] = { 100, 200, }; printf ( "ary1=%p\n", ary1 ); /* ?z?? ary1 ???u?l?v?????? */ printf ( "ary2=%p\n", ary2 ); sub ( ary1 ); sub ( ary2 ); return 0; } /* ?z?? : ?????????????????? ??????????u?????v?L?^????????? int ary[10]; ary[0], ary[1], .., ary[9] +-----------+ | ary[0] | ?z?????A?????????? +-----------+ | ary[1] | ?c??????A?v?Z???????A?w??????? +-----------+ | ...... | +-----------+ | ary[9] | +-----------+ */
#include <stdio.h> void sub ( char *str ) { printf ( "str の最初の文字は %c\n", *str ); /* 文字列には、頭に * をつけると、先頭の文字が取り出せる */ printf ( "str の最初の文字は %c\n", str[0] ); printf ( "str の次の文字は %c\n", str[1] ); /* str[n] == *(str + n) */ } int main(int argc, char *argv[]) { sub ( "abc" ); /* 文字列を関数に渡すことができる */ return 0; }
void sub ( char *str ) { printf ( "%s\n", str ); printf ( "%c\n", str[0] ); /* *(str+0) */ printf ( "%p\n", str ); } int main(int argc, char *argv[]) { char ary[4] = { 'a', 'b', 'c', '\0' }; /* ary[4] +------+ ary[0] | 'a' | 先頭の場所がわかれば、次は計算できる +------+ ary[1] | 'b' | +------+ ary[2] | 'c' | +------+ ary[3] | '\0 | +------+ */ sub ( "abc" ); /* 文字列を関数に渡すことができる */ sub ( ary ); ary[0] = 'A'; sub ( ary ); return 0; } /* 配列名は、 配列が記録されている「場所を表す情報(ポインター値)」 をもっていて、それを関数の引数として渡すことができる ポインター値を利用すると その場所にある(変数の)情報を、参照したり、変更する事ができる */
/* 型のサイズ その型の値を保存する変数がメモリ内に占める大きさ[byte 数](what:定義) 例 char -> 1 ( byte ) int -> ? ( byte ) : そのコンピュータに都合が良い数のサイズ コンピュータによって異なったり、 あるいは、C コンパイラによって異なることもある C 言語の int は、そのコンピュータでもっとも効率のよい計算をする 利点:効率の良いプログラムになる C 言語のプログラムは同じプログラムが、 欠点:システムによって、異なる振る舞いをする可能性がある プログラム内で、サイズを知る方法が与えられている それを利用して(必要なら)、欠点を補う sizeof */ #include <stdio.h> 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; }