このプログラムの大きな問題点は,
それで,最初から配列を大きくする方法もある.ただ,データ数が分からないと,それも 限界がある.とてつもなく大きな配列を用意することも考えられるが,そうすると次の問 題が生じる.
このようにデータ数が分からない場合,配列を使うのははなはだ無駄が生じやすい.
このプログラムは,おもに,
これは,コンパイルの作業を行う前に,ソースファイルに,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 |
著作者 | 紀平拓男・春日伸弥 |
出版社 | ソフトバンク パブリッシング株式会社 |