C言語関係掲示板

過去ログ

No900 2つの文字の組み合わせによる得点表について>

[戻る] [ホームページ]
No.594

2つの文字の組み合わせによる得点表について
投稿者---初心者(2003/10/31 00:34:34)


はじめまして。
今、取り組んでいるプログラミングの中でわからない点があるのでアドバイスをお願いします。

ある関数の中に、20種類の異なる文字が入るxとyが存在していて、それら二つに入る文字の組み合わせにより、得点が決まるというものです。何か文字を入力すると、得点が出力されるものではなく、表を覚えさせることが目的です、

それぞれの組み合わせの数は、20×20の400通り考えられ、さらにそれぞれの得点には、特に規則性はありません。一つだけ挙げるとすれば、(x,y)=(A,R)=(R,A)のように入れ替えても同じ得点になるということだけです。

その表の一部を以下に示します。

  A R
A 5,-2
R -2, 7

多次元配列で表そうと考えましたが、文字と数字が混在するので、どのように表せばよいのかわかりません。文字の種類が20もあるということを考慮して、例を挙げていただければと思います。

No.595

Re:2つの文字の組み合わせによる得点表について
投稿者---ともじ(2003/10/31 00:49:57)


こんばんは。

>多次元配列で表そうと考えましたが、文字と数字が混在するので、
>どのように表せばよいのかわかりません。文字の種類が20もあるという
>ことを考慮して、例を挙げていただければと思います。

文字は大文字のアルファベット限定ですか。ASCIIコードなら、
次のようにすると0〜25の数値に直せるので、2次元配列の添字として
使用可能ですね。
indexx = x - 'A';
indexy = y - 'A';



No.597

Re:2つの文字の組み合わせによる得点表について
投稿者---初心者(2003/10/31 16:57:59)


早速のご返事ありがとうございます。

>文字は大文字のアルファベット限定ですか。ASCIIコードなら、
>次のようにすると0〜25の数値に直せるので、2次元配列の添字として
>使用可能ですね。
indexx = x - 'A';
indexy = y - 'A';

文字はすべて、アルファベットの大文字だけです。
ASCIIコードで変換した場合、任意に文字をそれぞれ0〜25まで変換できるのですか。
せっかく方法をご指摘いただいたのに、上記の変換の意味がわかりません。
文字と数字がどのように対応するのでしょうか。
”そんなこともわからないのか”とお怒りになられるかもしれませんが、
教えていただければと思います。

No.599

Re:2つの文字の組み合わせによる得点表について
投稿者---すがりん(2003/10/31 22:04:41)


>文字と数字がどのように対応するのでしょうか。

↓このように対応します
http://www9.plala.or.jp/sgwr-t/c_sub/ascii.html

コンピュータは、人間のように文字をそのまま「えー」とか「びー」とかって認識しているわけではなく
上の表のように番号を振って、その値で覚えているんです。
だから普段は文字といえども数値扱いで、たまに%cだのputcharだのが来たときに慌てて(?)
コード表から対応する文字を探してくる(?)わけです。
すごくいいかげんな説明ですけど。

こういうのを走らせてみると何となくわかるかもしれない。

#include <stdio.h>

int main(void)
{
    printf("65番の文字..%c\n", 65);
    printf("67番の文字..%c\n", 67);

    printf("'A'の番号..%d\n", 'A');
    printf("'C'の番号..%d\n", 'C');

    printf("'C'-'A' == %d\n", 'C'-'A');

    return 0;
}


No.600

Re:2つの文字の組み合わせによる得点表について
投稿者---初心者(2003/11/01 00:05:52)


なるほど、実際にやってみてその意味がわかりました。
しかしこの値と文字の間には規則性がないし、それを配列の添え字にうまく合わせるにはどうすれば?
それぞれの文字が0,1,2…となるように、文字で引いてみるとか?
うーん、頭がこんがらがってきました。

No.601

Re:2つの文字の組み合わせによる得点表について
投稿者---ともじ(2003/11/01 00:49:47)


>しかしこの値と文字の間には規則性がないし、それを配列の添え字にうまく合わせるにはどうすれば?
>それぞれの文字が0,1,2…となるように、文字で引いてみるとか?

20×20の2次元配列ではなく、26×26の2次元配列で考えればいいのでは、
ということでNo.595は書きました。
#include <stdio.h>

int main(void)
{
    char x, y;
    int tbl[26][26] = {
/*       A  B  C  D  E  F  G  H  I  J  K  L  M  N  O  P  Q  R  S  T  U  V  W  X  Y  Z */
/* A */{ 5,22,63,-4,76,27,71,98,29,-1,12,22,87,-8,23,16,43,-2,11,53,-2,22,88,-9,33,86},
/* B */{22,98,98,54,76,86,-9}, /* 以下略 */
/* C */{63,76,65,98,67,32,45}, /* 以下略 */
/* 以下略 */ };

    printf("A-Z:");    scanf("%c", &x);
    printf("A-Z:");    scanf(" %c", &y);
    printf("(%c, %c) = %d\n", x, y, tbl[x-'A'][y-'A']);
    
    return 0;
}        

実行結果例
A-Z:A
A-Z:R
(A, R) = -2

なお、scanf(" %c", &y); については、
http://www9.plala.or.jp/sgwr-t/c/sec05.html#s5-4
の「(2)改行文字が残る」を参照してください。


No.602

Re:2つの文字の組み合わせによる得点表について
投稿者---初心者(2003/11/01 01:12:51)


ともじさんのおかげで、何とか筋道がつきました。どうもありがとうございました。

No.603

Re:2つの文字の組み合わせによる得点表について
投稿者---ともじ(2003/11/01 16:58:59)


すみません。入力値のチェックが抜けていました。
単なる例でもまずいので、修正しておきます。

#include <stdio.h>
#include <ctype.h>

int main(void)
{
    char x, y;
    int tbl[26][26] = {
/*       A  B  C  D  E  F  G  H  I  J  K  L  M  N  O  P  Q  R  S  T  U  V  W  X  Y  Z */
/* A */{ 5,22,63,-4,76,27,71,98,29,-1,12,22,87,-8,23,16,43,-2,11,53,-2,22,88,-9,33,86},
/* B */{22,98,98,54,76,86,-9}, /* 以下略 */
/* C */{63,76,65,98,67,32,45}, /* 以下略 */
/* 以下略 */ };

    printf("A-Z:");    scanf("%c", &x);
    printf("A-Z:");    scanf(" %c", &y);
    if (isupper(x) && isupper(y))
        printf("(%c, %c) = %d\n", x, y, tbl[x-'A'][y-'A']);
    
    return 0;
}        




No.596

Re:2つの文字の組み合わせによる得点表について
投稿者---とおり(2003/10/31 13:42:48)


こんな方法でどうでしょうか?

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

#define SIZE 16

const size_t char_to_index[] = {
#define __ 0
/*   0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F          0123456789ABCDEF */
    __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,    /* 0:制御文字         */
    __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,    /* 1:制御文字         */
    __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,    /* 2: !"#$%&'()*+,-./ */
     0,  1,  2,  3,  4,  5,  6,  7,  8,  9, __, __, __, __, __, __,    /* 3:0123456789:;<=>? */
    __, 10, 11, 12, 13, 14, 15, __, __, __, __, __, __, __, __, __,    /* 4:@ABCDEFGHIJKLMNO */
    __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,    /* 5:PQRSTUVWXYZ[\]^_ */
    __, 10, 11, 12, 13, 14, 15, __, __, __, __, __, __, __, __, __,    /* 6:`abcdefghijklmno */
    __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __,    /* 7:pqrstuvwxyz{|}~  */
#undef __
};

int score[SIZE][SIZE];

#define SCORE(x, y) score[ char_to_index[x] ][ char_to_index[y] ]

int main(void)
{
    const char tohex[] = {'0','1','2','3','4','5','6','7',
                          '8','9','A','B','C','D','E','F' };
    char buf[32];
    int x, y;

    /* 得点表作成 */
    for (y = 0; y < SIZE; y++) {
        for (x = 0; x < SIZE; x++) {
            SCORE(tohex[x], tohex[y]) = x*100 + y;
        }
    }

    /* 得点表参照 */
    while (1) {
        printf("score[][]:");
        gets(buf);
        if (strlen(buf) != 2)
            break;
        printf("score[%c][%c]=%d\n", buf[0], buf[1], SCORE(buf[0], buf[1]));
    }

    return 0;
}


No.598

Re:2つの文字の組み合わせによる得点表について
投稿者---初心者(2003/10/31 17:11:00)


例を示していただきありがとうございます。しかし、このソースプログラムが、何を表しているのかわかりません。添え字が、char型のままなのですが。
すみませんが、説明していただけないでしょうか。


No.605

Re:2つの文字の組み合わせによる得点表について
投稿者---とおり(2003/11/02 03:22:09)


No.594の書き込みを読んだ自分なりの解釈で組んでみました。
間違ってたらごめんなさい。
たとえばその書き込みにある
   A  R
A  5,-2
R -2, 7
という表の作成と参照は以下のような感じです。
前回の例では16進数の16個の文字を選んで適当な表を作っています。
あと、char_to_indexを使ってエラーチェックできるようにちょっと修正しました。

#include <stdio.h>

#define SIZE 2
#define CHAR_ERROR -1

const int char_to_index[] = {
#define __ CHAR_ERROR
/*   0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F       0123456789ABCDEF */
    __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, /* 0:制御文字         */
    __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, /* 1:制御文字         */
    __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, /* 2: !"#$%&'()*+,-./ */
    __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, /* 3:0123456789:;<=>? */
    __,  0, __, __, __, __, __, __, __, __, __, __, __, __, __, __, /* 4:@ABCDEFGHIJKLMNO */
    __, __,  1, __, __, __, __, __, __, __, __, __, __, __, __, __, /* 5:PQRSTUVWXYZ[\]^_ */
    __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, /* 6:`abcdefghijklmno */
    __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, __, /* 7:pqrstuvwxyz{|}~  */
#undef __
};

int score[SIZE][SIZE];

#define SCORE(x, y) score[ char_to_index[x] ][ char_to_index[y] ]

int main(void)
{
    const int table[SIZE][SIZE] = {
        /* A   R */
        {  5, -2},  /* A */
        { -2,  7},  /* R */
    };
    int x, y;

    /* 得点表作成 */
/*  SCORE('A', 'A') =  5;
    SCORE('A', 'R') = -2;
    SCORE('R', 'A') = -2;
    SCORE('R', 'R') =  7;*/
    for (y = 0; y < SIZE; y++)
        for (x = 0; x < SIZE; x++)
            score[x][y] = table[y][x];

    /* 得点表参照 */
    printf("(A,A) = % d\n", SCORE('A', 'A'));
    printf("(A,R) = % d\n", SCORE('A', 'R'));
    printf("(R,A) = % d\n", SCORE('R', 'A'));
    printf("(R,R) = % d\n", SCORE('R', 'R'));

    return 0;
}

[出力]
(A,A) =  5
(A,R) = -2
(R,A) = -2
(R,R) =  7