このプログラムの大きな問題点は,
それで,最初から配列を大きくする方法もある.ただ,データ数が分からないと,それも 限界がある.とてつもなく大きな配列を用意することも考えられるが,そうすると次の問 題が生じる.
このようにデータ数が分からない場合,配列を使うのははなはだ無駄が生じやすい.
このプログラムは,おもに,
これは,コンパイルの作業を行う前に,ソースファイルに,stdlib.hというヘッ ダーファイルを取り込む命令(プリプロセッサー) である.このプログラムでは, main関数の戻り値をEXIT_SUCCESSとしている.EXIT_SUCCESSの定義 がstdlib.hに書かれている.私のコンパイラーでは,
#define EXIT_SUCCESS 0
となっていた.戻り値を示すリスト1の32行目は,
return 0;
と同じである.
これもプリプロセッサーで,ソースプログラムをコンパイルする前に,文字列 NMAXを10に置き換える.文字列を置き換えるので,これを文字列置換と言う.いっ ぺんに多くの文字列や値を置き換えたいときに便利である.置き換える元の文字をすべ て大文字で書くのが習慣となっている.
これには,比較の演算子がない.変数bufの値の真/偽を判断することになる.最 初,if文を学習したときのことを思い出してほしい.C言語では,
となっていた.
代入演算子(=)は右辺から評価していく.このことから,この文は次のように解釈する.
リスト1 固定長の配列を使い合計を計算するプログラム(転載について)
1 #include <stdio.h>
2 #include <stdlib.h>
3
4 #define NMAX 10
5
6 int main(void)
7 {
8 int buf,sum,count,n;
9 int array[NMAX];
10
11 count=0;
12 do
13 {
14 printf("整数を入力してください(0を入力すると終了):");
15 scanf("%d",&buf);
16 if(buf)
17 {
18 array[count]=buf;
19 ++count;
20 }
21 } while(buf!=0);
22
23 /* 合計値を算出 */
24 printf("--入力されたのは以下の数です--\n");
25 for(sum=n=0;n<count;++n)
26 {
27 printf("%d \t",array[n]);
28 sum+=array[n];
29 }
30 printf("\n----\n以上の数の合計値は%dです。\n",sum);
31
32 return EXIT_SUCCESS;
33 }
ただし,最初に決めた配列をこえてのデータ入力ができない.ユーザーの気が変わって, データ数を増加させるときに問題が発生する.さらに,ユーザー自身,データの個数が分 からないときには,対応ができない.
このプログラムは,おもに,
少々複雑に見えるが,処理される順に見ていけば簡単である.
ポインターで宣言しているものを配列として使っている.これは,配列がどのように処 理されているか,考えればよく分かる.配列array[n]は,*(array+n)と評価 される.すなわち,配列array[n]は,ポインターarrayにn加算したポ インター(アドレス)が示す値と言うことである.このようなことから,配列で宣言して いなくても,配列のように使うことができるのである.
関数free()は,そのプログラムで使用しているメモリー領域を開放するた めにある.ここでは,12行目のmallocで確保された領域を解放している.
リスト2 最初に配列の サイズを決めてから値を代入するプログラム(転載について)
1 #include <stdio.h>
2 #include <stdlib.h>
3
4 int main(void)
5 {
6 int buf,sum,count,n,i;
7 int *array;
8
9 /* 入力するデータの個数を最初に聞いて,必要なメモリを確保 */
10 printf("何個の数値を入力しますか:");
11 scanf("%d",&count);
12 array=(int*)malloc(sizeof(int)*count);
13
14 n=0;
15 do
16 {
17 printf("整数を入力してください(0を入力すると終了):");
18 scanf("%d",&buf);
19 if(buf)
20 {
21 array[n]=buf;
22 ++n;
23 }
24 } while(buf!=0);
25
26 /* 合計値を算出 */
27 printf("--入力されたのは以下の数です--\n");
28 for(sum=i=0;i<n;++i)
29 {
30 printf("%d\t",array[i]);
31 sum += array[i];
32 }
33 printf("\n----\n以上の数の合計値は %d です。\n",sum);
34
35 free(array);
36 return EXIT_SUCCESS;
37 }
この方法も良さそうですが,以下のような問題があります.
このプログラムは,おもに,
このプログラムで使われている主なテクニックは,以下の通りである.
これは,30行目のmemcpy()関数を使うために必要で,その関数の宣言などが書か れている.
memcpy()関数は,MEMory CoPY(メモリー複写)の略で,メモリーの内容 をコピーする.ここでは,ポインターarrayが示す場所から4*sizeバイト分 のデータを,先頭をポインターtempが示す場所としてコピーする.
リスト3 実行時に配列 のサイズを拡張する方法(転載について)
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <memory.h>
4
5 int main(void)
6 {
7 int buf,sum,count,n,size;
8 int *array,*temp;
9
10 /* 最初の配列サイズは10 */
11 size=10;
12 array=(int*)malloc(sizeof(int)*size);
13
14 count=0;
15 do
16 {
17 printf("整数を入力してください(0を入力すると終了):");
18 scanf("%d",&buf);
19 if(buf)
20 {
21 array[count]=buf;
22 ++count;
23 /* 配列が満杯になったら,倍の大きさに拡張する */
24 if(count==size)
25 {
26 /* 新しい大きなメモリブロックを確保して,
27 元の内容をコピー。
28 realloc()を使っても同様の作業が行われる */
29 temp=(int*)malloc(sizeof(int)*size*2);
30 memcpy(temp,array,sizeof(int)*size);
31 free(array);
32 array=temp;
33 size*=2;
34 }
35 }
36 } while(buf!=0);
37
38 /* 合計値を算出 */
39 printf("--入力されたのは以下の数です--\n");
40 for(sum=n=0;n<count;++n)
41 {
42 printf("%d\t",array[n]);
43 sum+=array[n];
44 }
45 printf("\n----\n以上の数の合計値は%dです。\n",sum);
46
47 free(array);
48 return EXIT_SUCCESS;
49 }
[転載について]
このペー
ジ中のリスト1とリスト2,リスト3のプロ
グラムは,教科書として使用している以下の書籍
| 書名 | プログラミングの宝箱 アルゴリズムとデータ構造 ISBN4-7973-2419-8 |
| 著作者 | 紀平拓男・春日伸弥 |
| 出版社 | ソフトバンク パブリッシング株式会社 |