質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Q&A

解決済

4回答

3561閲覧

C言語 データの読み込み、判定、計算

marikot

総合スコア13

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

0グッド

0クリップ

投稿2015/11/17 04:24

編集2015/11/17 07:48

アルファベットで表されたボート名(A~Z)と貸出(O)、返却(I)、時間が各行に示されています。それぞれの貸し出し時間の総時間を出力します。

<入力>
A O 09:00
B O 09:10
A I 09:20
A O 09:30
B I 09:40
A I 09:50
<出力>
1:10

まずすべてをbufに読み込んでからboatnameとboatio,timeに振り分けています。
timeにデータが読み込めていないのか、OIの判定がおかしいのか
うまく計算できません。
どこが悪いのかご指摘お願いします。

#include<stdio.h>
#include<stdlib.h>

char buf[32][9],boatname[52],boatio[52];
int time[52][5];
int i=0,j,k,l,n,subtotal,total=0,final[4];

int calc(int k,int l){ //各ボートがそれぞれ何分借りられていたかを計算する
subtotal=(time[l][5]*10+time[l][6])*60+time[l][8]*10+time[l][9]-((time[k][5]*10+time[k][6])*60+time[k][8]*10+time[k][9]);
return subtotal;
}

int main(void){

do{ fgets(buf[i],9,stdin); //まず一行読み込み boatname[i]=buf[i][0]; boatio[i]=buf[i][2]; for(j=4;j<=8;j++){ time[i][j]=atoi(buf[j]); } i++; }while(fgets(buf[i],9,stdin)!=NULL); //次の行が読み込めなかったら終了 for(k=0;k<i;k++){ for(l=k;l<=i;l++){ if(boatname[k]==boatname[l]&&boatname[k]=='O'&&boatname[l]=='I'){ total+=calc(k,l); } } } final[0]=(total/60)/10; final[1]=(total/60)-final[0]*10; final[2]=(total%60)/10; final[3]=total%60-final[2]*10; if(final[0]==0&&final[1]==0){ printf("0:%d%d\n",final[2],final[3]); }else{ printf("%d%d:%d%d\n",final[0],final[1],final[2],final[3]); } return 0;

}

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答4

0

ベストアンサー

複数のデータが1行にまとめて入っている中から、それぞれのデータを別々に取り出すには、sscanf関数を使うと簡単にできます。
※お使いの環境が判りませんが、VC++の場合はsscanfが使えないのでsscanf_sを使います。

C

1char name; 2char io; 3int hour, minute; 4int count = sscanf(buf, "%c %c %d:%d", &name, &io, &hour, &minute); 5//int count = sscanf_s(buf, "%c %c %d:%d", &name, 1, &io, 1, &hour, &minute); // VC++の場合 6if(count != 4) 7{ 8 // 入力エラーの処理 9}

例えば、bufにA O 09:30を読み込んだ場合、

name = 'A' io = 'O' hour = 9 minute = 30

となります。

追記

すでに読み込んだバッファから取り出す場合はsscanf系を使います。
scanf系はファイルから読み込むのですが、何かと問題があるのでsscanfの方をご使用ください。

投稿2015/11/17 08:41

編集2015/11/17 11:15
catsforepaw

総合スコア5938

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

marikot

2015/11/17 11:03

scanfを使って、読み込むと、よけいな配列や計算がいらず、うまく計算できました。 みなさんのヒントも参考にさせていただいたのですが、一番わかりやすく教えてくださったので、ベストアンサーにさせていただきました。 ありがとうございます。
catsforepaw

2015/11/17 11:07

おっと、気づくの遅すぎましたが、scanfではなくsscanfです。ベストアンサー付けていただきましたが、大丈夫だったでしょうか。回答の方を修正しておきます。
guest

0

こんにちは。

まずいところを1つ1つ指摘することは可能ですが、あなたのためにならないと思いますので、別の観点からアドバイスしてみます。

デバッグするための色々な方法がありますが、良く使うものの1つにprintf()を使って自分が期待している値にちゃんとなっていることを確認する方法があります。
不具合がある場所については期待通りになっていません。それを見つけて、その原因と対策を検討し、正しくなるよう修正するわけです。

例えば下記のように入れて、その結果を見てみて下さい。何か見えてくると思います。

C

1buf[i][0]=0; 2 do{ 3printf("(1)buf[%d]=<%s>\n", i, buf[i]); 4 fgets(buf[i],9,stdin); //まず一行読み込み 5printf("(2)buf[%d]=<%s>\n", i, buf[i]); 6 boatname[i]=buf[i][0]; 7 boatio[i]=buf[i][2]; 8 for(j=4;j<=8;j++){ 9 time[i][j]=atoi(buf[j]); 10printf("(3)time[%d][%d]=%d\n", i, j, time[i][j]); 11 } 12 i++; 13 }while(fgets(buf[i],9,stdin)!=NULL); //次の行が読み込めなかったら終了

コンパイルしてみてないので、もし、エラーになったらごめんなさい。printf()なので頑張って修正下さいね。
他にも色々チェックするべき箇所はあると思います。ご自分でデバッグしてみて下さい。

プログラムの作り方は習うより慣れろって方針の大学も少なくないです。
たいへんですが、めげないで頑張ってください。

投稿2015/11/17 06:44

Chironian

総合スコア23272

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

marikot

2015/11/17 08:07

timeにうまくデータが入ってもいないことが判明しました。もう少し悩んでみます
guest

0

問題の仕様が分かりませんが、このままではダメだと思います
1.atoiの使用方法が間違っている
atoiは数字文字列をバイナリ数値に変換しますが、buf[j]で示される文字列は9:00 のようにコロンが
入った文字列になるので、エラーとなります
変換後の数値をtime[i][j]に格納していることから、1文字ずつバイナリ数値に変換したいのだと
思いますが、1文字の文字数字をバイナリ値に変換するのであれば、ASCIIコードで計算するのが良いと
思います
2.時の桁数に対する考慮できていない
calc()の計算をみると、時部分は二ケタになっていることが前提のように見えます
しかし、例題の入力値は09:00ではなく9:00となっているので、時間の指定部分が一ケタの場合の
考慮が足りていないように思います

投稿2015/11/17 05:21

KatsumiTanaka

総合スコア924

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

int time[52][5]; と宣言しているにもかかわらず、

C

1for(j=4;j<=8;j++){ 2 time[i][j]=atoi(buf[j]); 3}

など、明らかに範囲外を使おうとしています。
配列のインデックスは必ず0始まりです。

投稿2015/11/17 04:34

ozwk

総合スコア13521

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

marikot

2015/11/17 04:57 編集

m=0として for(j=4;j<=8;j++){ time[i][m]=atoi(&buf[i][j]); m++; } になおしてみました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問