C言語 職業訓練課題

概要

C言語では無駄な処理のないアルゴリズムの構築方法や、構造体・ポインタなどの扱い方、メモリ破壊を起こさないプログラムの組み方について学びました。
その中から、得るものが多かったと感じた課題を2つ掲載いたします。

課題1 電車の運賃検索

プログラム概要
東海道新幹線の出発駅から到着駅までの距離と運賃を表示するプログラムです。
出発駅と到着駅の駅名を入力し、2駅間の距離および運賃を出力します。
処理は繰り返し行えるものとして、入力した駅名のどちらかが [終了] の場合に終了します。
処理条件
駅名がエラーの場合はエラーメッセージを出力後、駅名の再入力ができる。
出発駅と到着駅が同じ場合は、到着栄をエラーとして、エラーメッセージを出力後に駅名の再入力ができる。
距離の出力は小数点以下1桁目まで。
入力可能な駅名(全17駅):東京・品川・新横浜・小田原・熱海・三島・新富士・静岡・掛川・浜松・豊橋・三河安城・名古屋・岐阜羽島・米原・京都・新大阪
ソースコード
GitHubで確認する
苦労したところ
出発駅または到着駅で[終了]と入力されるまで処理が繰り返されることや、出発駅が正しい場合にのみ、はじめて到着駅が入力できるというという仕組みが中々難しく、考えがいのある課題でした。
対応としましてはwhile文を入れ子にして外側を出発駅、内側を到着駅のループとして、内側のループの終了が外側でも捕捉できるようにして、フラグを用いることで実現することができました。
開発環境
バックエンド
言語: C言語
コンパイラ:C/C++ Optimizing Compiler Version 19.28.29914 for x64
その他のツール
EmEditor, Visual Studio 開発者コマンドプロンプト(x64 Native Tools Command Prompt for VS 2019)
制作時間
2時間 (2021年7月)

課題2 データチェック

プログラム概要
[成績データ]ファイルを入力し、レコード(1行)ごとにデータチェックを行います。
[エラーデータ]があった場合、エラーの内容を出力します。
処理条件1 [成績データ]ファイルについて
レコードのレイアウト
ファイル形式 テキストファイル
レコード長 最大80Byte (改行を除く)
クラス 1Byte
NO 1Byte
氏名 1~10Byte
得点 1~3Byte
  • 項目間は1Byteのカンマ[,]で区切られている
  • レコード間は改行で区切られている
  • 入力データの中に全角文字・タブは含まれないものとする
処理条件2 [エラーデータ] ファイルについて
レコードのレイアウト
レコード番号 1~2Byte
成績データ内容 1~80Byte
エラー内容 1~11Byte
項目の詳細
レコード番号 入力レコードの番号
成績データ内容 エラーのあったレコード内容をそのまま出力する
エラー内容 エラーの内容を記号で出力する。複数のエラーがあった場合は、[,]で区切る。
※記号については後述のデータチェック詳細を参照のこと。
  • 項目間は1Byteのコロン[:]で区切られている
  • レコード間は改行で区切られている
処理条件3 データチェック詳細
エラー記号とエラー内容
SP エラー番号:①
レコード内に半角スペースがないことを確認する。
ここでエラーがあった場合は③~⑥のチェックは行わない。
CM エラー番号:②
項目間の区切り文字である1Byteのカンマ[,]が、レコード内に3つあることを確認する。
ここでエラーがあった場合は③~⑥のチェックは行わない。
CL エラー番号:③
項目[クラス]は1Byteで、アルファベットの大文字A・B・Cのいずれかとする。
それ以外をエラーとする。
NO エラー番号:④
項目[NO]は1Byteで数字の1から5までのいずれかとする。
それ以外をエラーとする。
NA エラー番号:⑤
項目[氏名]は1Byteから10Byteまでで、アルファベットで構成されている。
また、先頭のみ大文字で2文字目以降は小文字とする。
1Byteのみの場合は大文字とする。
それ以外をエラーとする。
PO エラー番号:⑥
項目[得点]は1Byteから3Byteまでで、数字で構成されている。
また、整数に変換した場合0から100の範囲である。
それ以外をエラーとする。
ファイル内容 [成績データ] (seiseki.dat)
A,1,Ito,80
A,2,Yamamoto,85
A,3,Naka mura,79
a,4,Kobayashi,930
A 5 Kato 100
B,1,Yoshida,98
B,2,Yamada,75
E,8,SASAKI,1000
B,4,YamaguchiTaro,81
B,5 Matsumoto,75
C,1,Saito,100
C,2,INOUE,99
C.3.Kimura.80
C,4,hayashi,ZI
C,5,Simizu,96
ZI,10,Ito,8000
OO,A,SaIto,8
ソースコード
GitHubで確認する
工夫したところ
レコードこと、1行の文字列をポインタのインクリメントで、1文字ずつエラーが無いか判定しています。
SP(半角スペース)とCM(カンマの数)を先んじて判定しつつ、同時に区切り文字をNULL文字に置き換えております。そうすることで、変数を用意して各項目を格納することなく、項目ごとに疑似的に分割した状態を作り出し strlen() で長さの判定を行っています。

文字列を文字として1文字ずつ判定していくことの大変さを痛感しましたが、一方でポインタを扱いつつ、どうすればシンプルに処理できるのかを考えるのがとても楽しく感じた課題でした。
開発環境
バックエンド
言語: C言語
コンパイラ:C/C++ Optimizing Compiler Version 19.28.29914 for x64
その他のツール
EmEditor, Visual Studio 開発者コマンドプロンプト(x64 Native Tools Command Prompt for VS 2019)
制作時間
3時間30分 (2021年7月)