Download : sample-001.c ( utf8 版 )
/*
* 2016/11/18 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 ( utf8 版 )
/*
* 2016/11/18 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 ( utf8 版 )
/*
* 2016/11/18 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 ( utf8 版 )
/*
* 2016/11/18 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 ( utf8 版 )
/*
* 2016/11/18 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 ( utf8 版 )
/*
* 2016/11/18 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>
void subfunc( int a[] ) {
/* 関数の仮引数を、配列として宣言できる(サイズは不要[無意味]) */
/* 渡された「位置情報(ポインター)」を利用して、
配列の要素を「間接的に」参照 */
/* 添え字を利用して、配列の要素の値が読み出せる */
printf ( "a[0] = %d\n", a[0] );
printf ( "a[1] = %d\n", a[1] );
a[2] = a[0] + a[1]; /* 配列の要素の値を変更可能 */
/* これは、関数の呼び出し元の配列の要素の
値を変更している */
/*
呼び出す側の関数が、呼び出される関数の引数に配列名を
指定することにより、この二つの関数(呼び出す側と呼び出される側)
で、配列を「共有」できる
*/
}
int main(int argc, char *argv[]) {
int array[10];
array[0] = 10;
array[1] = 20;
/* 値を設定する */
subfunc ( array ); /* 配列名を関数の引数として渡す */
/* 配列の先頭の要素の「位置情報(ポインター値)」がコピーされて
渡される */
/* 配列(の要素)のコピーが渡されるわけではない */
printf ( "array[2]=%d\n", array[2] );
/* subfunc の中で、設定した値が反映されている */
return 0;
}
/*
メモリモデル
*/
#include <stdio.h>
#include "s_memory.h"
int main(int argc, char *argv[]) {
/*
変数名 番地
int a; -> 100
int b; -> 101
int c; -> 102
*/
set_memory_value_at ( 100, 10 );
/* 100 番地に、10 を設定 */
/* a = 10 */
set_memory_value_at ( 101, 20 );
/* 101 番地に、20 を設定 */
/* b = 20 */
set_memory_value_at (
102,
get_memory_value_at ( 100 )
+
get_memory_value_at ( 101 )
);
/* 102 番地に、100 番地と 101 番地の内容の和をいれる */
/* c = a + b */
printf ( "memory[102]=%d\n", get_memory_value_at ( 102 ) );
/* 102 番地の内容を表示 */
/* printf ( "%d\n", c ) */
}
/*
メモリモデル
*/
#include <stdio.h>
#include "s_memory.h"
void addnum ( int addr3, int addr1, int addr2 ) {
set_memory_value_at (
addr3,
get_memory_value_at ( addr1 )
+
get_memory_value_at ( addr2 )
);
/* addr3 番地に、addr1 番地と addr2 番地の内容の和をいれる */
/* c = a + b */
}
int main(int argc, char *argv[]) {
/*
変数名 番地
int a; -> 100
int b; -> 101
int c; -> 102
*/
set_memory_value_at ( 100, 10 );
/* 100 番地に、10 を設定 */
/* a = 10 */
set_memory_value_at ( 101, 20 );
/* 101 番地に、20 を設定 */
/* b = 20 */
addnum ( 102, 100, 101 );
/* 番地を引数に渡すことによって、
その番地の内容を参照したり、
その番地の内容を変更したりできる
=> 配列名を関数の引数に渡すのとよくにている
*/
printf ( "memory[102]=%d\n", get_memory_value_at ( 102 ) );
/* 102 番地の内容を表示 */
/* printf ( "%d\n", c ) */
}
/*
メモリモデル
番地を指定して、値を取り出したり、設定できる
それしかできないプリミティブ(原子的)な操作
これの組み合わせで、C 言語の代入などの操作が実現できる
*/
#include <stdio.h>
#include "s_memory.h"
void addnumarray ( int addr3, int addr1, int addr2 ) {
set_memory_value_at (
addr3,
get_memory_value_at ( addr1 )
+
get_memory_value_at ( addr2 )
);
/* addr3 番地に、addr1 番地と addr2 番地の内容の和をいれる */
/* c[0] = a[0] + b[0] */
set_memory_value_at (
addr3 + 1, /* 先頭の番地がわかれば、次の番地も判る */
get_memory_value_at ( addr1 + 1 )
+
get_memory_value_at ( addr2 + 1 )
);
/* addr3 + 1 番地に、addr1 + 1 番地と addr2 +1 番地の内容の和をいれる */
/* c[1] = a[1] + b[1] */
}
int main(int argc, char *argv[]) {
/*
変数名 番地
int a[2]; -> 100, 101
int b[2]; -> 102, 103
int c[2]; -> 104, 105
*/
set_memory_value_at ( 100, 10 );
/* 100 番地に、10 を設定 */
/* a = 10 */
set_memory_value_at ( 101, 20 );
/* 101 番地に、20 を設定 */
/* b = 20 */
set_memory_value_at ( 102, 30 );
/* 102 番地に、30 を設定 */
/* a = 10 */
set_memory_value_at ( 103, 40 );
/* 101 番地に、20 を設定 */
/* b = 20 */
addnumarray ( 104, 100, 102 );
/* 番地を引数に渡すことによって、
その番地の内容を参照したり、
その番地の内容を変更したりできる
=> 配列名を関数の引数に渡すのとよくにている
*/
printf ( "memory[104]=%d\n", get_memory_value_at ( 104 ) );
/* 104 番地の内容を表示 */
/* printf ( "%d\n", c[0] ) */
printf ( "memory[105]=%d\n", get_memory_value_at ( 105 ) );
/* 105 番地の内容を表示 */
/* printf ( "%d\n", c[1] ) */
}
#include <stdio.h>
int main(int argc, char *argv[]) {
int array[10];
char str[10];
array[0] = 10; /* 配列 array の先頭要素に 10 を代入 */
printf ( "array[0] = %d\n", array[0] );
/* 先頭の要素の内容(値)が表示される */
printf ( "*array = %d\n", *array );
/* 先頭の要素の内容(値)が表示される */
*array = 20; /* array[0] と *array はどこでも、交換可能 */
printf ( "*array = %d\n", *array );
printf ( "array[0] = %d\n", array[0] );
/*
一般に、
array[n] と *(array + n)
も交換可能
*/
array[3] = 100;
printf ( "*(array+3) = %d\n", *(array + 3) );
/*
*(array+3) <-> array[3]
array+3 <-> array[3] の場所同じ >1 byte<
array +-------+
0x7fffbf29f860 array[0] | | sizeof(int)=4
+-------+
| |
+-------+
| |
+-------+
| |
+-------+
0x7fffbf29f860+4=0x7fffbf29f864 array[1] | |
+-------+
| |
+-------+
| |
+-------+
| |
+-------+
0x7fffbf29f860+8=0x7fffbf29f868 array[2] | |
+-------+
| |
+-------+
| |
+-------+
| |
+-------+
0x7fffbf29f860+c=0x7fffbf29f86c array[3] | |
+-------+
| |
+-------+
| |
+-------+
| |
+-------+
*/
printf ( "array = %p\n", array );
printf ( "array + 3 = %p\n", array + 3 );
printf ( "str = %p\n", str );
printf ( "str + 3 = %p\n", str + 3 );
return 0;
}
#include <stdio.h>
void sub ( int a[] ) {
*a = *a * 2; /* 配列 a の先頭の要素を二倍する */
}
int main(int argc, char *argv[]) {
int array[10];
/*
array[0] ? array[9] までの 10 個の変数の宣言
array は、 array[0] のポインター値を表す
*/
int svar;
/*
svar のポインター値は ?
-> &svar
によって、単純変数 svar のポインター値が取り出せる
単純変数 サイズ 1 の配列
宣言 svar onearray[1]
操作 svar onearray[0] / *onearray
ポインター値 &svar onearray
*&svar <-> svar *onearray
*/
int onearray[1];
/*
1 つの変数 onearray[0] を宣言
-> onearray は、onearray[0] のポインター値
*/
array[0] = 10;
sub ( array );
printf ( "array[0] = %d\n", array[0] );
onearray[0] = 10;
sub ( onearray );
printf ( "onearray[0] = %d\n", onearray[0] );
svar = 10;
sub ( &svar );
printf ( "svar = %d\n", svar );
/*
scanf の時に、変数に & を付ける
今まで : 「ルール」としてきた
今回 : & をつけたのは、ポインター値を渡すため
scanf は、引数で与えられた、ポインター値から
「*」を付けて、間接参照する事により、
変数の値を書き換えていた
*/
return 0;
}
Download : 20161125-01.c ( utf8 版 )
/*
* 課題 CNAME-01
*
* 2016/11/25 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
$ ./20161125-01-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 $