練習 [9] 文字列(3/5)

練習 3(提出プログラム名:p0903a.c)

まず,このプログラム(p0903a.c)をダウンロードしなさい.

このプログラムでは名前の姓と名(2 つの文字列)を読み込んで,それぞれの 1 文字目だけを大文字に変換して出力している.

これを編集して,次の動作を行うプログラムに仕上げなさい.ただし,この問題では入力される姓や名はすべて小文字であり,それぞれの文字数は SIZE-1 であると仮定してプログラムを作ってよい.
【目的の動作】
姓と名で短い方(文字数の少ない方)をすべて大文字で出力し,そうでない方は先頭のみを大文字にして出力する.
なお,姓と名の文字数が同じ場合は,姓の方が短いものと見なして処理せよ.

【注意】
マクロ SIZE の定義部分以外に 20 (や 19, 18 といった関係する数字)を直接書いてはいけません.
なお,この問題でも strlen を使ってはいけません.
ただし,以下のヒントに示すように自前で文字数を調べる関数を作って使うのはOKとする.

【ヒント】
文字列の長さ(文字数)の数え方は講義スライドで説明しているように簡単です.
先頭から順にナル文字を探していくことで文字列の長さは分かります.
ただ,そのためのプログラムを姓と名について別々に 2 回書くのは少々無駄なので,これを関数としてして作る(文字列を引数とし,その長さを戻り値とする)と以下のようにスッキリと書くことができます:
例えば,
  int get_length( char str[] )
  {
   str
の文字数を調べる
   return str
の文字数;
  }

という関数をあらかじめ(main よりも前で)作っておけば,目的の処理は main の中で
  if ( get_length(name1) <= get_length(name2) )
  {
   name1 をすべて大文字に置き換える

   name2 は先頭(name2[0])のみ大文字に置き換える
  }
  else

  {
   name2 をすべて大文字に置き換える

   name1 は先頭(name1[0])のみ大文字に置き換える
  }

として書けます.(※「すべて大文字に置き換える」も別の関数として作るとなお良いです)

【ヒント2】すべて大文字へ書き換える関数の作り方.
例えば,引数で与えられた char 配列 str の中身をすべて大文字に書き換えるために
convert_upper という関数を作るとした場合:
  void convert_upper( char str[] )
  {
   int i;
   for ( i = 0; str[i] != '\0'; i++ )
   {
     str[i] を大文字で上書きする
   }
  }
この場合,戻り値は不要(配列の場合は変数の内容を直接書き換えることができるため)ですので,戻り値の型に相当する部分は void で宣言します.

  • 【プログラムの実行例】(その1)赤字は実行時にキーボードから入力する内容
氏名を入力してください(姓と名の間は空白):
aman hirohisa
ようこそ AMAN Hirohisa さん
  • 【プログラムの実行例】(その2)赤字は実行時にキーボードから入力する内容
氏名を入力してください(姓と名の間は空白):
matsuyama taro
ようこそ Matsuyama TARO さん
  • 【プログラムの実行例】(その3)赤字は実行時にキーボードから入力する内容
氏名を入力してください(姓と名の間は空白):
suzuki ichiro
ようこそ SUZUKI Ichiro さん

【過去にあったミス(減点となり,やり直しを命じられる)】
3 種類の実行例を確認せずに提出してしまっている.
 (例1)文字数に関係なく常に姓の方をすべて大文字にしてしまっている.
 (例2)長い方は先頭のみを大文字にすべきところをすべて大文字に変えてしまっている.
ナル文字を別の文字で上書きしてしまい,出力で文字化けしている.
インデントに不備がある(VSCode 上でインデントを自動で揃える作業をやっていない).


ミスが無いことを確認したら次の問題へ → [ 練習4 (p0904a.c) ]