ソフトウェアの仕様書作成について

このQ&Aのポイント
  • ソフトウェアの仕様書作成について(C言語)
  • 電車の時刻表を画面に表示するプログラムについて、詳細仕様を検討して作成しなさい。ユーザが現在時刻と到着したい希望時刻を入力すると、乗れそうな列車の候補を提示する。
  • 関数の形式は「int train_time(int present_h, int present_m, int arrival_h, int arrival_m, const int time_table[][])」であり、時刻表の電車の時間、分を読み込み、現在の時間と到着したい希望時間と比較して、乗れそうな列車の発車時刻と到着時刻を表示する。
回答を見る
  • ベストアンサー

ソフトウェアの仕様書作成について(C言語)

「電車の時刻表を画面に表示するプログラムについて、詳細仕様を検討して作成しなさい。要求は、ユーザが、現在時刻と到着したい希望時刻を入力すると、今から乗れそうな列車の候補をいくつか提示して欲しいということだけである。 この要求に沿って仕様を詳細に検討しなさい。」 という仕様書作成の問題なのですが、よくわかりません。 とりあえず自分なりにがんばってみたのですが(後述)、どうも不自然さがあふれてて困っています。 どこを直して行けばよいでしょうか? <************ここから*****************> 関数の形式:int train_time(int present_h, int present_m, int arrival_h, int arrival_m, const int time_table[][]) 関数の目的: 時刻表の電車の時間、分をそれぞれtime_table[i][0], time_table[i][1]に読み込み、(iは電車を区別する番号で整数である。) 現在の時間と分をそれぞれpresent_h, present_mから受け取り、また、到着したい希望時間と分をそれぞれarrival_h, arrival_mから受け取る。 時刻表の時刻と比較し、現在時刻以降に発車し、到着時刻以前に到着するすべての電車の発車時刻と到着時刻を表示する。 入力の形式:present_h, arrival_h, time_table[i][0]は、0以上24以下の時間を表す整数  present_m, arrival_m, time_table[i][1]は0以上60以下の分を表す整数 出力の形式:  -1、0以上の整数 説明:  時刻は24時間表記とする。  秒単位は考慮しない。 例外時の処理:  時刻で無いものを受け取った場合、例えば24以上の時間、60以上の分、文字列を受け取った場合などは-1を返す。  NULLを受け取った場合-1を返す

  • revia
  • お礼率100% (4/4)

質問者が選んだベストアンサー

  • ベストアンサー
  • dummyplug
  • ベストアンサー率58% (134/230)
回答No.2

仕様の記述はよくがんばっていると思います。 質問に書かれている仕様の範囲で気になるところと言えば、例えば ・「0以上24以下」というのは0も24も含むので例外時の処理に書いてある「24以上の時間」と矛盾する。23以下、24未満とするべき。また、型として(unsigned intでなく)intを選んでいるので負の値についても取り扱いを記述すべき。 ・文字列やNULLを受け取れる引数はないように見えるが、例外時の処理についてそれらの記述があるのが不思議。そういうケースがないのなら混乱の元になるので記述すべきでない。 ・time_table[<列車番号>][<0:時、1:分>]なのだと思うが、これだけだとこのテーブルに載っている時刻は「発車時刻」なのか「到着時刻」なのかわからない。わからないので「現在時刻以降に発車し、到着時刻以前に到着する」の判断の仕方もわからない。 ・該当する列車の時刻表示の表示形式がわからない。実装者の一存で構わないのか。 ・出力の値として-1を返すケース(の一部)は例外時処理として書かれているが、0以上の値はどういうときに返せばいいのか、0以外のことがあるのか、などが出力の規則がわからない。 というあたりが致命的に不足していると思いました。その他細かいところだと ・present_h, present_mなどと変数を分ける代わりに、struct { int h; int m; } time_s;のような構造体を定義しておき、struct time_s present;とする方が見通しがよくなる。 とかあります。 (余談)…ところで、個人的にはこの設問があまりよくないと思いました。前後の文脈でわかるのかもしれないので断定はできませんが、どこからどこまでの仕様をどのレベルで書けばよいのかがわかりません。私なら出題者にくってかかるかも。 詳細、という言葉だけからするとこうした関数レベルやその中身のアルゴリズムなどを記述すべきなようにも思えますし、それならばこんな漠然とした要求だけではなくて概要仕様のようなものが提示されてしかるべきだと思います。とすると、この漠然とした要求からプログラム概要の仕様をなるべく細かく考えろという設問にもとれます。 後者の意味の設問だとするならば、C言語がどうとかではなくて言語によらずプログラム全体の仕様を入出力のインタフェースを中心に記述するのがよいと思いました。 ユーザのUIはGUIなのかCUIなのかコマンドライン引数なのか、時刻は文字列で入力するのか数値か、時刻表データはファイルかデータベースか、書式はどうなっているか、出力形式はどういうフォーマットか、「いくつか」表示するとはいくつにするのか固定数か選択できるようにするのか、該当する列車が見つからないときにはどうするのか、入力の誤り(到着時刻の方が出発時刻より早い場合など)はどうするのか、などです。 それらから、データ構造をどうするか、プログラム全体の構造(処理の流れ)はどうするか、などと考えていって、機能分割やインタフェース定義から関数仕様へと落とし込み、最終的には引数やアルゴリズムなどの記述へと至ります。(やり方の一例ですが。) あんな設問ちょっとでこれを全部かけ、と言われたらちょっと嫌ですよね。 仕事ならやりますけど、課題としてはどうかなぁという感じです。 ちなみに、仕事なら時刻表データのメンテナンスはどうするとか、こんなUIになるが大丈夫かというのをクライアントと確認したり、スケジュールはどうだとか、仕様に関連した色々な話に広がったりします。さすがにそんな設問ではあり得ませんけど参考まで。

revia
質問者

お礼

厳しくかつ丁寧に指摘・説明していただいてありがとうございました。大変感謝しております。 仕様書って作るのは思ってたよりも難しいですね。社会人として出て行くまでにできるだけ力をつけてけるようにがんばります。

その他の回答 (1)

回答No.1

フリーのプログラマーです。 自分が仕様書を受け取ったプログラマーになったつもりで第三者的に(客観的に)チェックするようにしています。 自分がこの仕様書を受け取ったつもりで気づいた点を書いてみます。 ・関数の処理内容も記述したほうがよい。つまり「今から乗れそうな列車の候補」をどのようなロジックで解決するか、についてです。 ・最終的な出力内容「今から乗れそうな列車の候補」がどのように出力されるか不明。printfでだらだら出るのか、別のファイルorデータベースに格納されるか分かりません。 ・エラーコードはエラー種別に応じて変えたほうがよい ・入出力の例などを書くとよい。(文章力をカバーできる!) ・1時60分という入力はOKなのかな?とか日替わり(翌日にまたがった答え)を考慮するの? 言いたい放題言わせてもらいましたが、これだけ書ければ戦力にはなるかなと正直思いました。

revia
質問者

お礼

解答ありがとうございます。 仕様書というのはプログラマーの方が迷わないようにしなければならない、ということですが、ずいぶん迷わせてしまったようで、まだまだ改変すべきところがあるみたいですね。 これを参考に自分でも考えてがんばってみたいと思います。

関連するQ&A

  • 待ち行列シュミレーションのプログラム

    今現在待ち行列シュミレーションを勉強しているのですが、M/M/2モデルのプログラムをそれぞれ窓口数1(M/M/1)、窓口数3(M/M/3)のプログラムにしたいのですが上手くできません。 窓口数2のプログラムを記載します(窓口数の増減に関係ないと思われる後半のプログラムは記載してません)ので、どなたかわかる方がいましたらご教授のほうお願いします。 M/M/2 待ち行列のモデル -- ポアソン到着 => 到着時間間隔は指数分布 -- 指数サービス => サービス時間は指数分布 */ #include <stdio.h> #include <stdlib.h> #include <math.h> #include <time.h> #define N_SERVICE 2 /* 窓口数 */ #define N_USER 10000 /* 総到着人数 */ #define ARRIVAL_INTERVAL 30.0 /* 平均到着間隔*/ #define SERVICE_TIME 70.0 /* 平均サービス時間 */ double uni_random(void); /* 区間[0,1]の一様乱数 */ double exp_random(double); /* 平均値を引数にとる指数乱数*/ int main(void){ int i; /* 客番号 */ int j; /*窓口番号*/ double arrival[N_USER]={0.0} /*N人の到着時刻 */ int counter[N_USER]={0}; /*N人の利用窓口*/ int current_user[N_SERVICE]={0};/*最近の窓口利用者 */ double srv_start[N_USER]={0.0}/* N人のサービス開始時刻 */ double wait[N_USER]={0.0}; /*N人の待ち時間 */ double srv_time[N_USER]={0.0}/* N人のサービス時間 */ double srv_finish[N_USER]={0.0}; /* N人のサービス終了時刻*/ double avr_wait; /* 平均待ち時間*/ double avr_srvtime; /* 平均サービス時間  */ double avr_srvrate[N_SERVICE]={0.0}; /* 窓口の稼働率 */ /* 乱数の「種」を初期化 */ srand((unsigned)time(NULL)); /* 最初の客が到着した時刻から開始. 窓口0に入ってすぐサービス開始 */ arrival[0]=0.0; counter[0]=0; current_user[0]=0; srv_start[0]=0.0; wait[0]=0.0; srv_time[0]=exp_random(SERVICE_TIME); srv_finish[0]=srv_start[0] + srv_time[0]; /* 2人目の客が到着. 窓口0が空いていれば窓口0に、塞がっていれば窓口1に入ってすぐサービス開始 */ arrival[1]=arrival[0]+exp_random(ARRIVAL_INTERVAL); if(srv_finish[0]>arrival[1]){ counter[1]=1; current_user[1]=1; } else{ counter[1]=0; current_user[0]=1; } srv_start[1]=arrival[1]; wait[1]=0.0; srv_time[1]=exp_random(SERVICE_TIME); srv_finish[1]=srv_start[1]+srv_time[1]; for(i=2; i<N_USER; i++){ /* 客の到着時刻 = 前の客の到着時刻 + 到着間隔 */ arrival[i]=arrival[i-1]+exp_random(ARRIVAL_INTERVAL); /* 利用窓口 = 2つに窓口で早く空くほう */ if(srv_finish[current_user[1]]<srv_finish[current_user[0]]){ counter[i]=1; } else{ counter[i]=0; }

  • C言語の質問です。

    C言語の質問です。 C言語で、PCの時間を、キーボードで入力した好きな秒数ごとに表示するプログラムを作りたいのですが、どうしても1秒ごとになってしまいます。ここまで作ったのですが、あとどのようにすればよろしいでしょうか? #include <stdio.h> #include <time.h> #include <string.h> int a2i(char x); main() { time_t jikoku; char t[30]; int h,m,s,so=0; int x,a; printf("秒数xを入力"); scanf("%d",&x); while(1){ for(a=0;a<x;a++){ time(&jikoku); strcpy(t,ctime(&jikoku)); h=a2i(t[11])*10+a2i(t[12]); m=a2i(t[14])*10+a2i(t[15]); s=a2i(t[17])*10+a2i(t[18]); if(s!=so+a){ printf("%d:%d:%d\n",h,m,s); so=s; } } } } int a2i(char x) { return(x-'0'); }

  • C言語でこのプログラムを完成させるには

    C言語でこのプログラムを完成させるには C言語初心者です。 1~6の乱数を100回発生させて、それぞれの出現回数をカウントし、ヒストグラムとして表示するプログラムを作成したいのですが上手くいきません。 #include <stdio.h> #include <time.h> #include <stdlib.h> int rnd(int m, int n) { return (int)(n-m+1)*(rand()/(RAND_MAX+0.1))+m; } int main(void) { int i, j, r; int hist[7]; for (i=1; i<7; i++) hist[i]=0; srand((unsigned)time(NULL)); for (i=0; i<100; i++) { r=6; while (6-- > 0) putchar('*'); putchar('\n'); } for (i=1; i<7; i++) { printf("%2d:", i); for (j=0; j<hist[i]; j++) printf("*"); printf("\n"); } return 0; } 何がいけないのでしょうか? よろしくお願いします。

  • c言語についての質問です

    c言語についての質問です。あるdatファイルに振幅と時間のデータが保存されています。 このdatファイルを読み込み振幅の最大値を求めてから振幅の2割の値を求めます。 そこから再度読み込み振幅の2割を超える時間まで読み込み越えた際の時間を出力したいのですが上手くいきません。途中がけのプログラムをのせるのでお願いします。 datファイルには 時間 振幅 時間 振幅 … のようになっています。 #include <stdio.h> #include <math.h> int main(void) { const char * fname = "C1rbc1(50,0)sq,almi00001.dat"; char line[BUFSIZ]; double amp, time,arrival, max=0,max20; FILE *fp = fopen(fname, "r"); while (fgets(line, BUFSIZ, fp)) { sscanf(line, "%lf%lf", &time, &amp); if (amp > max) { max = amp; max20=max*0.2; } } fclose(fp); printf("max: %.7lf\n", max); printf("0,2*max:%.7lf\n",max20); int main(void) { FILE *fp =fopen(fname,"r"); while (fgets(line, BUFSIZ, fp)){ sscanf(line,"%lf%lf",&time,&amp); if(amp>max20){ arrival=time; break; } } fclose(fp); printf("arrival:%.7lf\n",arrival); return 0; } }

  • C言語の問題で困っています。

    C言語の問題で困っています。 誰か教えてください。 下の問題ですが、intがiだけでプログラムするにはどうしたら良いでしょうか? (a)から(d)に入るプログラムをすいませんが教えてください。 お願いします。 【問題】 1以上10以下の整数を昇順に区切って表示するプログラムです。 実行例 1 2 3 4 5 #include <stdio.h> int main (void) { int i; (A) while ((b)){ (c); (d); } printf("¥n"); return(0); }

  • c言語についての質問です

    あるdatファイルに時間と振幅のデータが入っているんですが振幅のデータのみを2乗してから2乗したものに1/2乗し正のものだけから振幅の最大値を求め、振幅の最大値の2割に達した時間を出力したいのですが、どのようにすればよいか分かりません。 サンプルプログラムを載せますのでおねがいします。 ちなみにdatファイルには 時間 振幅 時間 振幅 … となっています。 #include <stdio.h> int main(void) { const char * fname = "C2.dat"; char line[BUFSIZ]; double amp, time,arrival, max=0,max20; FILE *fp = fopen(fname, "r"); while (fgets(line, BUFSIZ, fp)) { sscanf(line, "%lf%lf", &time, &amp); if (amp > max) { max = amp; } } fclose(fp); printf("max: %.7lf\n", max); fp =fopen(fname,"r"); while (fgets(line, BUFSIZ, fp)){ sscanf(line, "%lf%lf" , &time, &amp); if(amp > max*0.2){ arrival = time; break; } } fclose(fp); printf("arrival:%.16lf\n",arrival); return 0; }

  • C言語についてです。

    mのn乗を計算する関数power()を作成せよ. ただし,関数power()はm,nを引数とし, 戻り値としてmのn乗の値を返すものとする. m,nは,正整数とする.提出するプログラムには, 関数power()だけでなく,m,nを入力し, mのn乗を出力するメイン関数main()を含むものとする. main()は,power()の前に記述すること. また,power()のプロトタイプ宣言も記述する これについて、作ってみたのですが実行できません。 どこが間違ってるか教えてください。 #include<stdio.h> int power(int m, int n); int main() { int m,n; int a,sum; printf("整数を入力してください:"); scanf("%d",&m); printf("何乗しますか?"); sum = power(n,m); printf("%dの%d乗は%dです。\n",n,m,sum); } int power(int m, int n) { int a, kotae; kotae = 1; for(a=1; a<=n; a++) kotae = kotae * m; return kotae; }

  • C言語の問題

    以下はC言語の問題です。お教えください。 1000以下の素数を求めるプログラム prog.c を作成せよ。各素数を整数4桁で出力し、15個の素数を出力した時点で改行処理 を行うこと。作成したプログラムを提出せよ。 です。 僕の考えでは、 #include <stdio.h> #include <math.h> main(){ int i; int j; int ix; int k; printf("正の整数を入力して下さい: "); scanf("%d",&i); ix=(int)(sqrt((double)i)); k=0; for(j=2;j<=ix;j++) { if(i%j==0) { k=1; } } if(k==0) { printf("%d は素数です\n",i); } else { printf("%d は素数ではありません\n",i); } となると思うのですが。どうやら違うようです。全然わからないので、正しい答えを教えてください。

  • C言語の課題が分からなくて困っています。

    http://www.picamatic.com/view/5868047_かかか/ URLの画像のような数当てゲームのプログラムを作成しているのですが、(1)~(5)の部分が分からなくて困っています。 面倒だとは思いますが、教えていただけないでしょうか。 #include<stdio.h> #include<stdlib.h> #include<time.h> int mani(void){ int i,x,y; srand((unsigned int)time(NULL)); (1) //1~1000の数をランダムに作成   y=0; //入力回数yを0にセットする for(;;){ //break文があるまで以下の処理を繰り返す printf("1以上1000以下の整数を入力してください。\n"); (2) //答えの入力 y=y+1; //入力回数yを1を増やす (3) //あたりの場合 printf("%d回目で当たりました。\n",y); (4) } else{ //外れの場合    (5) printf("違います。もっと大きな数です。\n"); else printf("違います。もっと小さな数です。\n"); } } return 0; }

  • C言語のプログラムでおかしな動作をするのですが教えて頂けないでしょうか?

    VisualStudio2008使用しています。 問題は、サイコロを200回振ってその出た目の数の個数分*を表示するプログラムです。 サイコロの目はランダムで出しています。 次のプログラムは正常に動作するものです。 /* #include <stdio.h> #include<stdlib.h> #include<time.h> #define N 200 int DICE(int min,int max); int main() { int n,i,j; int y[7]={0}; srand((unsigned int)time(NULL)); for(i=0;i<N;i++){ n=DICE(1,6); y[n]++; } for(i=1;i<7;i++){ printf(" %2d: ",i); for(j=0;j<y[i];j++){ printf("*"); } printf("\n"); } return 0; } int DICE(int min,int max) { return min+(int)(rand()*(max-min+1.0)/(1.0+RAND_MAX)); } */ 次のプログラムが問題で、授業で先生が配列にはstaticをおまじないとしてつけないと暴走すると言われたので、つけて見ると明らかに間違ってると思われるプログラムで動作するのですが原因を教えて頂けないでしょうか? 以下問題のプログラム! 配列の前にstaticをつけたら、添え字をいくつにしても正常に動作します。普通は添え自分しか領域って確保されないですよね??? /* #include <stdio.h> #include<stdlib.h> #include<time.h> #define N 200 int DICE(int min,int max); int main() { int n,i,j; //以下が問題の配列宣言 static int y[2]={0}; srand((unsigned int)time(NULL)); for(i=0;i<N;i++){ n=DICE(1,6); y[n]++; } for(i=1;i<7;i++){ printf(" %2d: ",i); for(j=0;j<y[i];j++){ printf("*"); } printf("\n"); } return 0; } int DICE(int min,int max) { return min+(int)(rand()*(max-min+1.0)/(1.0+RAND_MAX)); } 質問の意味が正確に伝わらなかった場合は補足しますので、ご回答よろしくお願いします。

専門家に質問してみよう