例題 35 つの文字列を読み込み,入力順に配列 a へ格納しなさい. そして,それらを辞書式順に並び替えて出力しなさい.ただし,文字列の入力は 1 行で 1 つとし, その長さは改行を含めて 16 文字未満とする. 方針・アルゴリズムまず,文字列を 5 つ読み込み,それぞれ配列 a へ格納する.そして a[0], ..., a[4] を辞書式順に並び替える. 単一文字の比較と異なり,文字列の比較には strcmp 関数を利用する. いま,s1 と s2 の 2 つの文字列があり, s1 の方が s2 よりも辞書式順で先(数値でいえば小さい)とすると strcmp(s1, s2) の値が負の数になる. これを利用すれば文字列のソーティングができる.
コーディング例1 /* 2 * プログラミング演習 第 13 回 3 * [例題 3] 4 * (C) 2006 Hirohisa AMAN <aman@cs.ehime-u.ac.jp, aman@computer.org> 5 */ 6 #include <stdio.h> 7 #include <stdlib.h> 8 9 int main(void){ 10 char a[5][16]; 11 char tmp[16]; 12 int n, m, i, c; 13 14 for ( c = 0; c < 5; c++ ){ 15 printf("%d > ", c+1); 16 fgets(a[c], 16, stdin); 17 } 18 19 for ( n = 4; n >= 0; n-- ){ 20 m = 0; /* a[0] が辞書式順で一番後ろと仮定 */ 21 for ( i = 1; i <= n; i++ ){ 22 if ( strcmp(a[m], a[i]) < 0 ){ 23 m = i; /* 一番後ろ(最大)位置の更新 */ 24 } 25 } 26 if ( m < n ){ /* a[m] と a[n] の値を交換 */ 27 strcpy(tmp, a[m]); 28 strcpy(a[m], a[n]); 29 strcpy(a[n], tmp); 30 } 31 } 32 33 for ( c = 0; c < 5; c++ ){ 34 printf("%s", a[c]); 35 } 36 37 return 0; 38 }
※左端の数字は行番号であり,ソースコードには含まれない点に注意!
コンパイル & 実行例$ gcc example13_3.c [Enter] $ ./a.out [Enter] 1 > this [Enter] 2 > is [Enter] 3 > a [Enter] 4 > test [Enter] 5 > data [Enter] a data is test this 解説文字列の読み込みに関しては,fgets を使えばよいので説明は不要であろう.ただ,ここで注意しなければならないのは, 文字列が 1 個ではなく複数個入力され, それらをいったん配列に入れておく必要があるという点である. この場合,a は文字列の配列ということになる. 既に学んだように,文字列は文字(char)配列なので, 「文字列の配列」というのは 「char 配列を要素とした配列」 ということになる. よって,宣言は
文字列どうしの(辞書式順での)比較は,
上述のように strcmp 関数を使えばよい.
ただし,文字列の交換については, 例題 2 まで行ってきたような代入が使えない. 直感的には tmp をポインタ変数として, tmp = a[n]; a[n] = a[m]; a[m] = tmp;という具合いにこれまでやってきたのと同じ方法で a[m] と a[n] とを入れ替えればよいように思えるが, 残念ながら配列内のポインタは書き換えができない (第 11 回の解説スライド, 最後の 3 ページを参照) ため,それぞれ内容をまるごとコピーするしかない (27〜29行目): 27 strcpy(tmp, a[m]); 28 strcpy(a[m], a[n]); 29 strcpy(a[n], tmp); |