ページ 1 / 1
会津オンラインジャッジ:Finding Missing Cards
Posted: 2010年11月27日(土) 22:02
by みけCAT
http://rose.u-aizu.ac.jp/onlinejudge/Pr ... 15&lang=jp
の問題で、以下のソースコードを書いたのですが、Runtime Errorと出ました。
printfでデバッグしたところ、カードの種類を入力した段階でfor文を一回回ってしまうようです。
いい書き方があったら教えてください。
お願いします。
コード:
#include <stdio.h>
int main(void) {
int sonzai[52];
int n;
int i;
char kindc[4]={'S','H','C','D'};
char kind;
int num;
for(i=0;i<52;i++)sonzai[i]=0;
scanf("%d",&n);
for(i=0;i<n;i++) {
scanf("%c %d",&kind,&num);
switch(kind) {
case 'D':num+=13;
case 'C':num+=13;
case 'H':num+=13;
case 'S':num+=13;
}
sonzai[num-1]=1;
}
for(i=0;i<52;i++) {
if(sonzai[i]==0)
printf("%c %d\n",kindc[i/13],i%13+1);
}
return 0;
}
Re: 会津オンラインジャッジ:Finding Missing Cards
Posted: 2010年11月27日(土) 22:50
by 五反田
カードの種類を読み取る際に、バッファに残っている改行を読み込んでしまっているようです。
そこで以下のように%cの前(と一応%dの後にも)スペースを入れて、空白を読み飛ばすようにし、さらにcaseの最後の+=13はいらないので、コメントアウトしたら無事Acceptされましたよ。
コード:
#include <stdio.h>
int main(void) {
int sonzai[52];
int n;
int i;
char kindc[4]={'S','H','C','D'};
char kind;
int num;
for(i=0;i<52;i++)sonzai[i]=0;
scanf("%d",&n);
for(i=0;i<n;i++) {
scanf(" %c %d ",&kind,&num);
switch(kind) {
case 'D':num+=13;
case 'C':num+=13;
case 'H':num+=13;
//case 'S':num+=13;
}
sonzai[num-1]=1;
}
for(i=0;i<52;i++) {
if(sonzai[i]==0)
printf("%c %d\n",kindc[i/13],i%13+1);
}
return 0;
}
Re: 会津オンラインジャッジ:Finding Missing Cards
Posted: 2010年11月27日(土) 22:58
by bitter_fox
すべてのscanf文に対して
コード:
scanf("%d",&n);
while (getchar() != '\n');
while (getchar() != '\n'); をはさんでみてください。scanfは最後の改行もバッファとして残して処理を終了するので、getcharで改行まで読み込んでやる必要があります。
switch文でbreakが無いのは、仕様ですよね??
Re: 会津オンラインジャッジ:Finding Missing Cards
Posted: 2010年11月27日(土) 23:02
by 七篠
横槍で質問に質問を返すので大変申し訳ないのですが、
この問題はNoteに
int cards[4][13]; // bool でもよい
と書いてあり、おそらく2次元配列の勉強をしろということだと思うのですが、わざわざ単なる配列で考えるのでしょうか。
二次元配列ですればわかりやすいというのを使わないのはもったいないです。
考え方は
最初の文字で繰り返す回数をきめて、その後に入力するトランプの種類に合わせたところにフラグを立てて(最初に繰り返す回数分)、([4]*[13]回分 )最後にフラグがたたなかったところ(=存在しないもの)だけ出力すればいいと思います。
[4]*[13]回分 の繰り返し方法は
for(4回文の繰り返し文){
for(13回文の繰り返し文){
判定と出力処理
}
}
という感じだと思います。 二次元配列は覚えるととても便利ですのでがんばってください
Re: 会津オンラインジャッジ:Finding Missing Cards
Posted: 2010年11月28日(日) 04:24
by ゆーずぃ
bitter_fox さんが書きました:すべてのscanf文に対して
コード:
scanf("%d",&n);
while (getchar() != '\n');
while (getchar() != '\n'); をはさんでみてください。scanfは最後の改行もバッファとして残して処理を終了するので、getcharで改行まで読み込んでやる必要があります。
このトピック自体とは関係ありませんが、他の方が後で閲覧する時の為に念の為。
scanfで最後の改行をバッファに残してしまうのは代入抑止(%*c)で防げます。(期待通りの入力が行われた場合のみ。)
ちなみに既にストリームに入っている改行は、%c以外の場合デフォルトで無視されます。
%cの場合でも、今回の問題のように確実に期待された入力がされる(エラー判定処理の必要が無い)のであれば、
char c;
char s[10];
scanf("%c",&c);
scanf("%s%*c",s);
又、逆ならば
scanf("%s",s);
scanf(" %c%*c",&c);
で充分です。
有名な、空白を入れる
scanf(" %c",&c);
は、
既にストリームに改行・空白・タブが入っている場合に読み飛ばすだけなので気を付けて下さい。(自身の改行を打ち消すものではありません。)
知っておいて損は無いと思います。横から失礼しましたm(_ _)m
//本文修正しました
Re: 会津オンラインジャッジ:Finding Missing Cards
Posted: 2010年11月28日(日) 08:04
by みけCAT
bitter_foxさん
この方法で解決しました。ありがとうございます。
switch文でbreakが無いのは、仕様ですよね??
仕様です。
コード:
#include <stdio.h>
int main(void) {
int sonzai[52];
int n;
int i;
char kindc[4]={'S','H','C','D'};
char kind;
int num;
for(i=0;i<52;i++)sonzai[i]=0;
scanf("%d",&n);
while (getchar()!='\n');
for(i=0;i<n;i++) {
scanf("%c %d",&kind,&num);
while (getchar()!='\n');
switch(kind) {
case 'D':num+=13;
case 'C':num+=13;
case 'H':num+=13;
/*case 'S':num+=13;*/
}
sonzai[num-1]=1;
}
for(i=0;i<52;i++) {
if(sonzai[i]==0)
printf("%c %d\n",kindc[i/13],i%13+1);
}
return 0;
}
七篠さん
二次元配列のコードでもAcceptされました。ありがとうございます。
コード:
#include <stdio.h>
int main(void) {
int sonzai[4][13];
int n;
int i;
int c;
char kindc[4]={'S','H','C','D'};
char kind;
int num;
for(c=0;c<4;c++) {
for(i=0;i<13;i++)sonzai[c][i]=0;
}
scanf("%d",&n);
while (getchar()!='\n');
for(i=0;i<n;i++) {
scanf("%c %d",&kind,&num);
while (getchar()!='\n');
switch(kind) {
case 'S':sonzai[0][num-1]=1;break;
case 'H':sonzai[1][num-1]=1;break;
case 'C':sonzai[2][num-1]=1;break;
case 'D':sonzai[3][num-1]=1;break;
}
}
for(c=0;c<4;c++) {
for(i=0;i<13;i++) {
if(sonzai[c][i]==0)
printf("%c %d\n",kindc[c],i+1);
}
}
return 0;
}