プロが教えるわが家の防犯対策術!

初心者のためコードや説明が拙いと思いますが、ご了承ください。
今この問題に取り組んでいます。
https://onlinejudge.u-aizu.ac.jp/problems/ITP1_6_B

私はC言語で以下のようにコードを書きましたが、コンパイルは通ったものの実行すると上手くいきません。修正すべきところを教えて下さい。
うまくいっていないと思う箇所
・カードの枚数nを入力してもその枚数分読み込めない。
・最後に入力したカードが読み込まれない。


自分が書いたコード;

#include <stdio.h>
#include <string.h>

struct playingcard {
int number;
char suit;
};


int main(void) {
int n;
struct playingcard card[52];
int s[13], h[13], d[13], c[13];
int sn=1, hn=1, dn=1, cn=1;
int count = 0;

scanf("%d", &n);

for (int i = 0; i < (n+1); i++) {
scanf("%c %d", &card[i].suit, &card[i].number);
}

for (int j = 0; j < n; j++) {
if (card[j].suit == 'S') {
s[sn] = card[j].number;
sn++;
}
else if (card[j].suit == 'H') {
h[hn] = card[j].number;
hn++;
}
else if (card[j].suit == 'C') {
c[cn] = card[j].number;
cn++;
}
else if (card[j].suit == 'D') {
d[dn] = card[j].number;
dn++;
}
}

for (int x = 1; x < 14; x++) {
for (int a = 1; a < (sn + 1); a++) {
if (x == s[a]) {
count++;
}
}
if (count == 0) {
printf("S %d\n", x);
}
count = 0;
}

for (int x = 1; x < 14; x++) {
for (int a = 1; a < (hn + 1); a++) {
if (x == h[a]) {
count++;
}
}
if (count == 0) {
printf("H %d\n", x);
}
count = 0;
}

for (int x = 1; x < 14; x++) {
for (int a = 1; a < (cn + 1); a++) {
if (x == c[a]) {
count++;
}
}
if (count == 0) {
printf("C %d\n", x);
}
count = 0;
}

for (int x = 1; x < 14; x++) {
for (int a = 1; a < (dn + 1); a++) {
if (x == d[a]) {
count++;
}
}
if (count == 0) {
printf("D %d\n", x);
}
count = 0;
}
}

A 回答 (4件)

何が上手くいっていないのかを人に聞くというのも一つの手ではありますが、何が上手くいっていないのかを自分で探る方法を身につけましょう。

そうしないと、上手くいかないことがあったら人に教えてもらう、ということを一生続けなくてはなりません。

たとえば、1行目を読んだ後にその行数分だけscanf()を使ってplayingcard構造体に値を入れていると思いますが、これがどのように格納されているかを確認する、といったことを繰り返しながら進めた方がいいです。

たとえば、こんな感じ。forループの中のscanf()の下にprintf()を入れているだけですが、1行画面から入力するごとにその入力した内容を(意図する動きであれば)オウム返ししているだけです。他に出力したい内容があれば、printf()で出力したい内容を書けばいいです。

 for (i = 0; i < (n+1); i++) {
  scanf("%c %d", &card[i].suit, &card[i].number);
  printf("XXXX %c : %d\n", card[i].suit, card[i].number);
 }

ここの処理が上手くいっていることを確認したら次の処理の確認へ進む、といったやり方をすると、少なくともどこが悪いかを自分で知ることができます。

また、こういったことを試すのにいちいちキーボードから入力するのも大変だと思いますので、入力はファイルに書いておいて、これを標準入力に食わせるといった方法を取ると時短ができるかもしれません。

$ ./my-command < cards.txt
    • good
    • 1
    • good
    • 0

配列の添え字は気を付けましょう。


C 言語の系統では添え字は 0 から始まるので、
n個の要素を持つ配列を順に処理するなら大抵はこう書きます。
for (i=0; i<n; i++) 処理(配列[i]);

参考)
https://ja.wikipedia.org/wiki/%E3%82%AA%E3%83%AA …

scanf の %c は少々特殊なので、空白に対する配慮が必要です。
誤: scanf("%c %d", ...
正: scanf(" %c %d", ...

参考)
https://linuxjm.osdn.jp/html/LDP_man-pages/man3/ …

変換指定の %c の説明にて以下の記述有り
> 通常行われる先頭のホワイトスペースの読み飛ばしは行われない。
> 先頭のホワイトスペースを読み飛ばすためには、
> フォーマット文の中で明示的にスペースを使用すれば良い。

フォーマット文の ホワイトスペース の説明にて以下の記述有り
> 入力中の任意の個数のホワイトスペースに一致する。
> 「何もなし」にも一致する

余談ではありますが

配列 s, h, d, c は不要かと思います。
この程度のデータ量なら配列 card を直接見ても問題ないでしょう。
例)
for (char* suit = "SHCD"; *suit; suit++) {
for (int num = 1; num <= 13; num++) {
if (card[i].suit == *suit && card[i].number == num) {
...
    • good
    • 0

「カードの枚数nを入力してもその枚数分読み込めない。

」とか「最後に入力したカードが読み込まれない。」とか書いてあるけど, 「読み込めない」「読み込まれない」がどのような状況を指しているのかがわからない.
・どのような入力をして
・どのような結果になることを期待したところ
・実際にはどのような結果であったのか
を「具体的に」書いてほしい.

あと, 配列の宣言と添え字の範囲の関係は大丈夫? 例えば
int a[10];
と配列を宣言した場合, 実際に値を格納できるのは
a[0]~a[9] の 10ヶ所
ってことは理解してる?
    • good
    • 1

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!