例題 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);
|