Download : sample-001.c
/*
* 2018/12/21 sample-001.c
*
* ポインター型変数の利用
*
*/
#include <stdio.h>
#include <malloc.h>
/*
* 利用方法
* コンパイル
* cc -o sample-001.exe sample-001.c
* 実行
* ./sample-001.exe
*/
/*
* main 関数
*/
int main ( int argc, char *argv[] ) {
int v; /* 整数型の変数を確保 */
int *p = &v; /* ポインター型変数 p に v のポインター値を代入する */
/* *p は、変数 v と全く同じに振る舞う */
*p = 1;
printf ( "*p = %d\n", *p );
printf ( "v = %d\n", v );
*p = *p + 10;
printf ( "*p = %d\n", *p );
printf ( "v = %d\n", v );
return 0;
}
$ ./sample-001.exe *p = 1 v = 1 *p = 11 v = 11 $
Download : sample-002.c
/*
* 2018/12/21 sample-002.c
*
* 動的領域の確保 (単純変数)
*
*/
#include <stdio.h>
#include <malloc.h> /* calloc/free を利用する場合に必要 */
/*
* 利用方法
* コンパイル
* cc -o sample-002.exe sample-002.c
* 実行
* ./sample-002.exe
*/
/*
* main 関数
*/
int main ( int argc, char *argv[] ) {
int *p;
/* 整数型変数の領域を 1 つ分確保 */
p = (int *)calloc ( 1, sizeof(int) );
if ( p == NULL ) { /* メモリの確保に失敗した場合は NULL が返る */
printf ( "整数領域のメモリ確保に失敗しました。\n" );
} else {
/* 以下は、*p を普通の整数型変数と同じ様に利用できる */
*p = 1;
printf ( "*p = %d\n", *p );
*p = *p + 10;
printf ( "*p = %d\n", *p );
/* 動的に確保したメモリは最後に必ず、free で解放する */
free ( p );
}
return 0;
}
$ ./sample-002.exe *p = 1 *p = 11 $
Download : sample-003.c
/*
* 2018/12/21 sample-003.c
*
* ポインター型変数の利用(2)
*
*/
#include <stdio.h>
/*
* 利用方法
* コンパイル
* cc -o sample-003.exe sample-003.c
* 実行
* ./sample-003.exe
*/
/*
* main 関数
*/
int main ( int argc, char *argv[] ) {
int a[10]; /* 整数型の配列を確保 */
int *p = a; /* ポインター型変数 p に a の先頭の要素のポインター値を代入する */
/* p は、配列名 a と全く同じに振る舞う */
p[2] = 1;
printf ( "p[2] = %d\n", p[2] );
printf ( "a[2] = %d\n", a[2] );
p[4] = p[2] + 10;
printf ( "p[4] = %d\n", p[4] );
printf ( "a[4] = %d\n", a[4] );
return 0;
}
$ ./sample-003.exe p[2] = 1 a[2] = 1 p[4] = 11 a[4] = 11 $
Download : sample-004.c
/*
* 2018/12/21 sample-004.c
*
* 動的領域の確保 (配列)
*
*/
#include <stdio.h>
#include <malloc.h>
/*
* 利用方法
* コンパイル
* cc -o sample-004.exe sample-004.c
* 実行
* ./sample-004.exe
*/
/*
* main 関数
*/
int main ( int argc, char *argv[] ) {
int *p;
/* 整数型変数の領域を 10 つ分確保 */
p = (int *)calloc ( 10, sizeof(int) );
if ( p == NULL ) { /* メモリの確保に失敗した場合は NULL が返る */
printf ( "整数領域のメモリ確保に失敗しました。\n" );
} else {
/* 以下は、p を普通の整数型配列名と同じ様に利用できる */
p[2] = 1;
printf ( "p[2] = %d\n", p[2] );
p[4] = p[2] + 10;
printf ( "p[4] = %d\n", p[4] );
/* 動的に確保したメモリは最後に必ず、free で解放する */
free ( p );
}
return 0;
}
$ ./sample-004.exe p[2] = 1 p[4] = 11 $
Download : sample-005.c
/*
* 2018/12/21 sample-005.c
*
* 不定長の入力 (最大値が存在)
*
*/
#include <stdio.h>
/*
* 利用方法
* コンパイル
* cc -o sample-005.exe sample-005.c
* 実行
* ./sample-005.exe
*/
#define MAX_OF_INPUT_SIZE 10 /* 入力できるデータ数 */
/*
* main 関数
*/
int main ( int argc, char *argv[] ) {
int array[MAX_OF_INPUT_SIZE]; /* 整数型の配列を確保 */
int n; /* 入力される整数値の個数 */
int i;
printf ( "データ数を入力してください : " );
scanf ( "%d", &n );
if ( ( 0 <= n ) && ( n < MAX_OF_INPUT_SIZE ) ) {
for ( i = 0; i < n; i++ ) {
printf ( "%d 番目の数値を入力してください : ", i + 1 );
scanf ( "%d", &array[i] );
}
printf ( "入力された内容は以下の通りです。\n" );
for ( i = 0; i < n; i++ ) {
printf ( "%d 番目の数値は %d です。\n", i + 1, array[i] );
}
} else {
printf ( "データ数(%d)が異常です。\n", n );
}
return 0;
}
5 453 32 -239 0 294
$ ./sample-005.exe < sample-005.in データ数を入力してください : 5 1 番目の数値を入力してください : 453 2 番目の数値を入力してください : 32 3 番目の数値を入力してください : -239 4 番目の数値を入力してください : 0 5 番目の数値を入力してください : 294 入力された内容は以下の通りです。 1 番目の数値は 453 です。 2 番目の数値は 32 です。 3 番目の数値は -239 です。 4 番目の数値は 0 です。 5 番目の数値は 294 です。 $
Download : sample-006.c
/*
* 2018/12/21 sample-006.c
*
* 不定長の入力 (動的に領域を確保)
*
*/
#include <stdio.h>
#include <malloc.h>
/*
* 利用方法
* コンパイル
* cc -o sample-006.exe sample-006.c
* 実行
* ./sample-006.exe
*/
/*
* main 関数
*/
int main ( int argc, char *argv[] ) {
int *parray; /* 整数型の配列の先頭 */
int n; /* 入力される整数値の個数 */
int i;
printf ( "データ数を入力してください : " );
scanf ( "%d", &n );
if ( 0 <= n ) {
if ( ( parray = (int *)calloc( n, sizeof(int) ) ) != NULL ) {
for ( i = 0; i < n; i++ ) {
printf ( "%d 番目の数値を入力してください : ", i + 1 );
scanf ( "%d", &parray[i] );
}
printf ( "入力された内容は以下の通りです。\n" );
for ( i = 0; i < n; i++ ) {
printf ( "%d 番目の数値は %d です。\n", i + 1, parray[i] );
}
free ( parray );
} else {
printf ( "整数領域のメモリ確保に失敗しました。\n" );
}
} else {
printf ( "データ数(%d)が異常です。\n", n );
}
return 0;
}
15 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
$ ./sample-006.exe < sample-006.in データ数を入力してください : 15 1 番目の数値を入力してください : 1 2 番目の数値を入力してください : 2 3 番目の数値を入力してください : 3 4 番目の数値を入力してください : 4 5 番目の数値を入力してください : 5 6 番目の数値を入力してください : 6 7 番目の数値を入力してください : 7 8 番目の数値を入力してください : 8 9 番目の数値を入力してください : 9 10 番目の数値を入力してください : 0 11 番目の数値を入力してください : 1 12 番目の数値を入力してください : 2 13 番目の数値を入力してください : 3 14 番目の数値を入力してください : 4 15 番目の数値を入力してください : 5 入力された内容は以下の通りです。 1 番目の数値は 1 です。 2 番目の数値は 2 です。 3 番目の数値は 3 です。 4 番目の数値は 4 です。 5 番目の数値は 5 です。 6 番目の数値は 6 です。 7 番目の数値は 7 です。 8 番目の数値は 8 です。 9 番目の数値は 9 です。 10 番目の数値は 0 です。 11 番目の数値は 1 です。 12 番目の数値は 2 です。 13 番目の数値は 3 です。 14 番目の数値は 4 です。 15 番目の数値は 5 です。 $
#include <stdio.h>
int main(int argc, char *argv[]) {
int i;
int j;
int k;
printf ( "&i = %p\n", &i ); /* %p は、アドレスを16進表示する */
printf ( "&j = %p\n", &j );
printf ( "&k = %p\n", &k );
return 0;
}
#include <stdio.h>
int main(int argc, char *argv[]) {
int a[3];
printf ( "&a[0] = %p\n", &a[0] );
printf ( "&a[1] = %p\n", &a[1] );
printf ( "&a[2] = %p\n", &a[2] );
/* 「&」: アドレス演算子
=> 変数の前につけることにより、変数に対応した
メモリセルのアドレスを取り出す */
/*
C 言語 メモリ
a +-------+ ===== +---+
| a[0] | | | 4 つのセル(4byte)
+-------+ ==* +---+ が一つ変数a[0] に対応
| a[1] | | | | => 次の a[1] は、4 つ先
+-------+ | +---+
| a[2] | | | |
+-------+ | +---+
<- int -> *== | |
4byte +---+
1byte
*/
return 0;
}
#include <stdio.h>
void sub ( int a, int b ) {
printf ( "&a = %p\n", &a );
printf ( "&b = %p\n", &b );
printf ( "a = %d\n", a );
/* 仮引数変数 a には、呼び出し側の実引数の i の値「1」が
コピーされているので、同じく 1 になる */
/* しかし、これは、たんに「値」がコピー(渡)されているだけ
「変数そのもの」が渡されているわけではない */
/* その証拠に、アドレス値が異なる */
}
int main(int argc, char *argv[]) {
int i = 1;
int j = 2;
printf ( "&i = %p\n", &i );
printf ( "&j = %p\n", &j );
sub ( i, j );
return 0;
}
#include <stdio.h>
void sub ( int a, int b ) {
printf ( "&a = %p\n", &a );
printf ( "&b = %p\n", &b );
printf ( "a = %d\n", a );
}
void sub2 ( int x, int y ) {
printf ( "&x = %p\n", &x );
printf ( "&y = %p\n", &y );
printf ( "x = %d\n", x );
}
int main(int argc, char *argv[]) {
int i = 1;
int j = 2;
printf ( "&i = %p\n", &i );
printf ( "&j = %p\n", &j );
sub ( i, j );
sub2 ( i, j );
return 0;
}
#include <stdio.h>
void sub ( int a, int b ) {
int c;
printf ( "c = %d\n", c ); /* 変数 c は初期化していない
=> どんな値になるかは不明 */
printf ( "&a = %p\n", &a );
printf ( "&b = %p\n", &b );
printf ( "&b = %p\n", &c );
printf ( "a = %d\n", a );
c = 1234567; /* 変数に値を代入してみる .. */
}
void sub2 ( int x, int y ) {
int z;
printf ( "z = %d\n", z ); /* 変数 z は初期化していない
=> どんな値になるかは不明なはず */
printf ( "&x = %p\n", &x );
printf ( "&y = %p\n", &y );
printf ( "&z = %p\n", &z );
printf ( "x = %d\n", x );
}
int main(int argc, char *argv[]) {
int i = 1;
int j = 2;
printf ( "&i = %p\n", &i );
printf ( "&j = %p\n", &j );
sub ( i, j );
sub2 ( i, j );
return 0;
}
#include <stdio.h>
/*
sum(n) は、 n + (n-1) + ... + 2 + 1 = n(n+1)/2
*/
int sum(int n) {
printf ( "n = %d\n", n );
printf ( "&n = %p\n", &n );
if ( n == 0 ) {
return 0;
} else {
return sum ( n - 1 ) + n;
/* sum(10) = sum(10-1) + 10 */
/* sum(10-1) = sum(9) => sum(9) の計算では n が 9 になっている */
}
}
int main(int argc, char *argv[]) {
printf ( "sum(10)=%d\n", sum(10) );
return 0;
}
#include <stdio.h>
int main(int argc, char *argv[] ) {
char vc;
int vi;
double vd;
printf ( "sizeof(vc) = %d\n", sizeof ( vc ) );
printf ( "sizeof(vi) = %d\n", sizeof ( vi ) );
printf ( "sizeof(vd) = %d\n", sizeof ( vd ) );
/* sizeof を利用して、変数が占めるメモリのサイズが得られる */
return 0;
}
#include <stdio.h>
int main(int argc, char *argv[] ) {
char vc;
int vi;
double vd;
printf ( "sizeof(vc) = %d\n", sizeof ( vc ) );
printf ( "sizeof(vi) = %d\n", sizeof ( vi ) );
printf ( "sizeof(vd) = %d\n", sizeof ( vd ) );
/* sizeof を利用して、変数が占めるメモリのサイズが得られる */
/* メモリモデルを意識したプログラムを作るため */
/* この値がシステムによって異なる */
printf ( "&vc = %p\n", &vc );
printf ( "&vi = %p\n", &vi );
printf ( "&vd = %p\n", &vd );
printf ( "&vc + 1 = %p\n", (&vc) + 1 );
printf ( "&vi + 1 = %p\n", (&vi) + 1 );
printf ( "&vd + 1 = %p\n", (&vd) + 1 );
/*
それぞれ、アドレス値が、sizeof(型)だけ増えている
それぞれの値が、型情報を持っている
具体的には、
&vc は(変数 vc が char 型なので..) (char *)型
&vi は(変数 vi が int 型なので..) (int *)型
などとなる
値だけででなく「型」をもっている
*/
return 0;
}
#include <stdio.h>
int main(int argc, char *argv[] ) {
int vi;
printf ( "sizeof(vi) = %d\n", sizeof ( vi ) );
printf ( "&vi = %p\n", &vi );
printf ( "&vi + 1 = %p\n", (&vi) + 1 );
/* この結果は、1 ではなく 4 (sizeof(int)) だけ
アドレス値が変化 */
return 0;
}
#include <stdio.h>
int main(int argc, char *argv[] ) {
int ai[2];
printf ( "sizeof(ai[0]) = %d\n", sizeof ( ai[0] ) );
printf ( "&ai[0] = %p\n", &ai[0] );
printf ( "&ai[0] + 1 = %p\n", (&ai[0]) + 1 );
return 0;
}
#include <stdio.h>
int main(int argc, char *argv[] ) {
int ai[2];
printf ( "sizeof(ai[0]) = %d\n", sizeof ( ai[0] ) );
printf ( "&ai[0] = %p\n", &ai[0] );
/*
&ai[0] => &(*(ai+0))
where ai[i] <=> *(ai+i)
=> &(*(ai))
=> ai
where * と & は逆演算なので、対消滅する
---> 配列名が、実は先頭の要素の「ポインタ値」になる
*/
printf ( "&ai[0] + 1 = %p\n", (&ai[0]) + 1 );
/*
(&ai[0]) + 1
=> ai + 1
=> &*(ai + 1)
=> &(*(ai + 1))
=> &(ai[1])
=> ai[1] のポインタ値(アドレス値)
配列の次の要素のアドレスだから、サイズだけずれてないと困る
*/
return 0;
}
/*
???????A(int *)?^??l???w????
=> ?????\???A?h???X????????????e?? 1 ?????
*/
void set_one ( int *p ) {
*p = 1;
/* ??яo??????A&i ???w?????????A
p == &i
????
*p == *(&i) == i
????
=> ????d?g???p???? scanf ???????l???X???????
*/
}
/*
???????A(char *)?^??l???w????
=> ?????\???A?h???X????????????e?? 1 ?????
*/
void set_one ( char *p ) {
/* p-012-1.c ??????A??????^???? */
/* p-012-1.c ???A(int *) ?^?????A???????A(char *)?^ */
*p = 1;
/*
1000
= 768 + 43
= 256 * 3 + 32
int = 4 byte
+-------+ +-------+
| 32 | Low | 1 |
+-------+ +-------+
| 3 | | 0 |
+-------+ +-------+
| 0 | | 0 |
+-------+ +-------+
| 0 | Highg | 0 |
+-------+ +-------+
p-012-1.c ???
char 1 byte
1000 1 769
+-------+ +-------+ +-------+
| 32 | Low | 1 | | 1 |
+-------+ +-------+ +-------+
| 3 | | 3 |
+-------+ +-------+
| 0 | | 0 |
+-------+ +-------+
| 0 | Highg | 0 |
+-------+ +-------+
p-012-2.c ???
*/
}
#include <stdio.h>
int main(int argc, char *argv[]) {
int i;
i = 1000;
printf ( "i = %d\n", i );
set_one ( &i ); /* ??????A??? i ??|?C???^?l??????? */
/* set_one ???A????????l?? 1 ???X???? */
printf ( "i = %d\n", i );
return 0;
}
#include <stdio.h>
int main(int argc, char *argv[]) {
int i;
printf ( "&i = %p\n", &i ); /* &i は (int *) 型のポインタ値 */
printf ( "&i + 1 = %p\n", &i + 1 );
/* &i + 1 のアドレス値は、
sizeof (int) だけ増える */
printf ( "(char *)&i = %p\n", (char *)(&i) );
/* キャスト : 式の前に「(型名)」と記述する事により、
その式の値の型を強制的に、その指定した型にする事ができる */
printf ( "((char *)&i) + 1 = %p\n", ((char *)&i) + 1 );
/* ((char *)&i) + 1 のアドレス値は、
sizeof (char) だけ増える */
return 0;
}
#include <stdio.h>
int main(int argc, char *argv[]) {
char line[10]; /* 文字の配列 : 文字列を保存するために利用 */
gets ( line ); /* キーボードから一行入力して、line に保存 */
/* 文字列の入力 */
printf ( "%s\n", line ); /* 入力した文字列の表示 */
/* puts( line ) でもよい */
/* 保存するための領域は 10 byte ( 9 文字の長さ ) しか
用意されていないのに、それ以上の文字がにゅうりょくできて
しまう .. */
return 0;
/*
準備していない領域も書き換えられる(ポインタを利用しているから)
gets は、その意味で「危険」な関数
fgets を利用するか、scanf で、文字列サイズを指定..
だからといって、利用される領域のサイズをあらかじめ予測するのは難しい
配列のサイズは、コンパイル時に決定されている必要があるので、
予測不能なサイズの情報を保持するのには適さない。
=> 実行時に必要なサイズを確保する方法がある
=> malloc / free (動的なメモリ確保)
*/
}
#include <stdio.h>
#include <malloc.h> /* malloc/free を利用するためのヘッダ */
int main(int argc, char *argv[]) {
char *line; /* (char *) 型の変数 : ポインタ値を保持 */
int len; /* 文字列の長さ */
printf ( "入力する文字列の長さを入力してください : " );
scanf ( "%d\n", &len );
line = malloc ( len + 1 ); /* 文字 + EOS のサイズ */
/* 動的に、メモリを確保 */
fgets ( line, len + 1, stdin ); /* キーボードから文字列を入力 */
printf ( "「%s」", line ); /* \n がないのは、fgets が改行も読み込むので.. */
free ( line ); /* 確保した領域を解放 */
/*
記憶領域は、動的(プログラム実行時)に決める事も可能(malloc/free)
確保したら、開放する必要がある
*/
return 0;
}
[前回まで] メモリモデル # メモリ:実在するものをモデル化 # アドレスで操作ができる # サイズ持っている # 情報を記録できる # => 「変数」という「概念」につながってゆく メモリを操作するには、アドレスがあればよい アドレス => C 言語では、「変数名」に相当する メモリ : 1 byte のセルが並んでいる 個々のセルは、アドレスで区別できる 個々のセルは 1 byte の情報を個別に記録可能 read/write 可能 メモリ C 言語 情報の記録 メモリセル 変数 区別 アドレス 名前 区別の形 数値 ラベル?(区別はできても操作できない) 処理 色々可能 区別しかできない 計算 関数の引数に渡せる 関数の値にできる C 言語では、基本は「変数」という抽象化がおこなれている => ほとんどの場合は、その背景である、メモリを意識する必要がない needs : メモリモデルを意識しないとできない事がある 文字列に + 1 すると、長さが短くなる理由 scanf で、変数の前に & を付ける理由 最初は、おまじない => メモリモデルを利用するとわかる seeds : メモリモデルを具体的に処理する機能が用意されている C 言語では、 変数名からそのアドレスを取り出す演算 & 逆に アドレスから、変数のように値を参照したり、変更可能にする演算 * が用意さている。 => メモリモデルを意識したプログラムが作れる [今日の話] メモリを意識したプログラミング & を利用する事により、変数のアドレスを見ることができる 値は、 %p で表示して、確認できる p-001.c ? p-005.c 基本、変数が異なれば、アドレスも異なる => 個々の変数は、別々に値を保持できる(独立) 特に、関数の呼び出し側と呼び出される側も、異なるメモリを利用 => 互いに独立 <= 「値」を共有するために、「引数変数」に「値」がコピーされる 変数に対応する領域は、「再利用」される 関数の中の変数は、関数呼び出しが行わた時点で有効(他の用途に利用されない事が保証される..)になり、関数から帰ると、無効(その領域は、再利用可能な形になる..)になる。 => 変数の「生存時間」と呼ぶ => 変数に対応するメモリ領域は、何度か再利用される => 「前の利用のごみが残っている」ので「初期化忘れ」が問題となる 再帰呼び出し 関数の呼び出しがあるたびに、関数で利用される変数には、 別のメモリ領域が割り当てられる => 再帰呼び出しを可能とする原理 「アドレス値」 メモリ上のアドレスを表す値(%p)で表示されたもの 「ポインター値」 数値の大きさとしては、アドレス値を持つが、それと一緒に、 「型」情報を持っている !! & 演算子 : 変数からアドレス値をとる => 変数から、ポインタ値を取り出す演算子 int 型の変数に & を付けた結果得られる値(ポインタ値)の型は、 (int *) 型になる # 「int *pi」と書くと、変数 pi は(int *) 型になる # これは、 「*pi が、int 型になる」という意味 # 「int *p」=> 「(int *)p」なので、p は(int *)型 # 「int *p」=> 「int (*p)」とすると(*p) が(int)型 ポインタ型の値は、アドレス値と同時にそれがどの型の 変数のアドレスかの(型)情報を保持している # アドレス値は、単なるアドレスなので、 # そのさしている先が、何の型かの情報を持っていない 「ポインター値」 = アドレス値 + 型 = サイズ + 演算の手段 !! 「型」: コンパイル時(C 言語)の概念 !! アドレス値(サイズ) : 実行時(メモリモデル/CPU)の概念 !! => コンパイルによって、これらの情報は失われる(別の形になる) !! 特に !! 関数の引数に渡されるものは、「値」(型情報はない) !! 関数の呼び側と受け側が異なるように扱えててしまう !! # 利点と欠点がある(ほぼ欠点だが..) ポインタ値の操作 アドレス値の操作 ( 加算・減算 ) 型情報の操作 キャスト [まとめ] ポインター値 変数の保存されているメモリのアドレス(アドレス値)と、 その変数の型の情報の組み合わせの事 ただし、型情報はコンパイル時のみ保持され、実行時は、アドレス値しかない 関数の値として、渡されるのは、アドレス値だけ => 両側で、型情報の了解が必要 T 型の値を保持する変数のポインタ値の型は (T *) 型となる 操作としては、 アドレス値の変更 (加算減算) 型情報の変更(キャスト) が可能 変数から、ポインター値(&:アドレス演算子) ポインター値から変数(*:間接参照演算子) の双方向の変換が可能 特に、関数間で、「変数」そのものを渡す事ができないが、 「変数」の「ポインター値」は渡せる => 関数内で、ポインター値を経由する事により、 関数の外の変数の値も(参照と)変更が可能 ==
課題プログラム内の「/*名前:ここ*/」の部分を書き換え「/*この部分を完成させなさい*/」の部分にプログラムを追加して、プログラムを完成させます。
Download : 20190111-01.c
/*
* 課題 CNAME-01
*
* 2019/01/11 FILENAME
*
* 三角形の形をした配列
*
*/
/*
* 利用方法
* コンパイル
* cc -o BASENAME.exe FILENAME
* 実行
* ./BASENAME.exe
*/
#include <stdio.h>
#define ARRAY_SIZE_N 10
/*
*
* 0 a[0][0]
* 1 a[1][0], a[1][1]
* 3 a[2][0], a[2][1], a[2][2]
* 6 ..
* a[9][0], a[9][1], a[9][2], .., a[9][9]
*
*/
int get_tri ( int *ary, int n, int m ) {
/*
** この部分を完成させなさい
*/
}
void set_tri ( int *ary, int n, int m, int value ) {
/*
** この部分を完成させなさい
*/
}
/*
* main
*/
int main ( int argc, char *argv[] ) {
int triary[ARRAY_SIZE_N*(ARRAY_SIZE_N+1)/2];
int n;
int m;
int i;
for ( n = 0; n < ARRAY_SIZE_N; n++ ) {
for ( m = 0; m <= n; m++ ) {
set_tri ( triary, n, m, n * 100 + m );
}
}
for ( i = 0; i < ARRAY_SIZE_N*(ARRAY_SIZE_N+1)/2; i++ ) {
printf ( "triary[%d] = %d\n", i, triary[i] );
}
for ( n = 0; n < ARRAY_SIZE_N; n++ ) {
for ( m = 0; m <= n; m++ ) {
printf ( "triary[%d][%d] = %d\n", n, m, get_tri( triary, n, m ) );
}
}
return 0;
}
$ ./20190111-01-QQQQ.exe triary[0] = 0 triary[1] = 100 triary[2] = 101 triary[3] = 200 triary[4] = 201 triary[5] = 202 triary[6] = 300 triary[7] = 301 triary[8] = 302 triary[9] = 303 triary[10] = 400 triary[11] = 401 triary[12] = 402 triary[13] = 403 triary[14] = 404 triary[15] = 500 triary[16] = 501 triary[17] = 502 triary[18] = 503 triary[19] = 504 triary[20] = 505 triary[21] = 600 triary[22] = 601 triary[23] = 602 triary[24] = 603 triary[25] = 604 triary[26] = 605 triary[27] = 606 triary[28] = 700 triary[29] = 701 triary[30] = 702 triary[31] = 703 triary[32] = 704 triary[33] = 705 triary[34] = 706 triary[35] = 707 triary[36] = 800 triary[37] = 801 triary[38] = 802 triary[39] = 803 triary[40] = 804 triary[41] = 805 triary[42] = 806 triary[43] = 807 triary[44] = 808 triary[45] = 900 triary[46] = 901 triary[47] = 902 triary[48] = 903 triary[49] = 904 triary[50] = 905 triary[51] = 906 triary[52] = 907 triary[53] = 908 triary[54] = 909 triary[0][0] = 0 triary[1][0] = 100 triary[1][1] = 101 triary[2][0] = 200 triary[2][1] = 201 triary[2][2] = 202 triary[3][0] = 300 triary[3][1] = 301 triary[3][2] = 302 triary[3][3] = 303 triary[4][0] = 400 triary[4][1] = 401 triary[4][2] = 402 triary[4][3] = 403 triary[4][4] = 404 triary[5][0] = 500 triary[5][1] = 501 triary[5][2] = 502 triary[5][3] = 503 triary[5][4] = 504 triary[5][5] = 505 triary[6][0] = 600 triary[6][1] = 601 triary[6][2] = 602 triary[6][3] = 603 triary[6][4] = 604 triary[6][5] = 605 triary[6][6] = 606 triary[7][0] = 700 triary[7][1] = 701 triary[7][2] = 702 triary[7][3] = 703 triary[7][4] = 704 triary[7][5] = 705 triary[7][6] = 706 triary[7][7] = 707 triary[8][0] = 800 triary[8][1] = 801 triary[8][2] = 802 triary[8][3] = 803 triary[8][4] = 804 triary[8][5] = 805 triary[8][6] = 806 triary[8][7] = 807 triary[8][8] = 808 triary[9][0] = 900 triary[9][1] = 901 triary[9][2] = 902 triary[9][3] = 903 triary[9][4] = 904 triary[9][5] = 905 triary[9][6] = 906 triary[9][7] = 907 triary[9][8] = 908 triary[9][9] = 909 $
Download : 20190111-02.c
/*
* 課題 CNAME-02
*
* 2019/01/11 FILENAME
*
* 動的なメモリの確保
* キーボードより正の整数を幾つか入力して、その要素が入った配列を返す
* 0 以下の整数が入力されたら、終了とする
* 配列のサイズは、正の整数の個数 + 1 とし、最後の要素には 0 を入れる
*/
/*
* 利用方法
* コンパイル
* cc -I ~/c/include -o BASENAME.exe FILENAME
* 実行
* ./BASENAME.exe
*/
#include <stdio.h>
#include <malloc.h> /* calloc/free を利用するので必要 */
/*
* read_n_integers
*/
int *read_n_integers( int size ) {
int num; /* キーボードから入力された数値を保存する */
int *value; /* 確保された配列の先頭要素へのポインター */
printf ( "正の整数値を入力してください(0 以下だと入力を終了します):" );
scanf ( "%d", &num );
if ( num <= 0 ) { /* 入力が全部終ったので、配列を作成する */
/* 配列のサイズは、引数で指定された個数 + 1 となる */
if ( ( value = (int *)calloc ( size + 1, sizeof ( int ) ) ) != NULL ) {
/* 動的メモリは取り出せるとは限らないので、結果をチェック */
value[ size ] = 0; /* 最後の要素として 0 を代入 */
} /* else {} */ /* NULL が帰った場合は、そのまま、値として返す */
} else { /* 入力が終っていないので、更に、値を読むために再帰呼び出し */
if ( ( value = read_n_integers( size + 1 ) ) != NULL ) {
/* 結果が NULL でなければ、配列が作られている */
/* size 番目の要素を配列に記録 */
/*
** この部分を完成させなさい
*/
} /* else {} */ /* NULL が帰った場合は、そのまま、値として返す */
}
/* いずれの場合でも value を返す */
/*
** この部分を完成させなさい
*/
}
/*
* main
*/
int main ( int argc, char *argv[] ) {
int *array; /* n 個数の要素をもつ配列の先頭をもつ */
int i;
/* read_n_integers を呼び出して、n 個の整数値を入力する */
/* 引数には、入力済のデータ数を指定するので、最初は 0 を指定する */
if ( ( array = read_n_integers( 0 ) ) != NULL ) {
/* read_n_integers は、NULL を返す可能性がある */
/* 入力された要素を画面に出力 */
for ( i = 0; array[i] > 0; i++ ) {
printf ( "%d th data = %d\n", i, array[i] );
}
/* malloc/calloc で確保したメモリは、必ず free で解放する */
/*
** この部分を完成させなさい
*/
} /* else {} */ /* NULL の場合はエラーなので、何もしない */
return 0;
}
12 34 5 6 90 -1
$ ./20190111-02-QQQQ.exe 正の整数値を入力してください(0 以下だと入力を終了します):12 正の整数値を入力してください(0 以下だと入力を終了します):34 正の整数値を入力してください(0 以下だと入力を終了します):5 正の整数値を入力してください(0 以下だと入力を終了します):6 正の整数値を入力してください(0 以下だと入力を終了します):90 正の整数値を入力してください(0 以下だと入力を終了します):-1 0 th data = 12 1 th data = 34 2 th data = 5 3 th data = 6 4 th data = 90 $