C言語関係掲示板

過去ログ

No.1019 偶数魔方陣の4N魔法陣のプログラム

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

偶数魔方陣
投稿者---kana(2004/02/27 02:55:01)


偶数魔方陣の4N魔法陣のプログラムが分かりません!!
どなたか教えてください!
お願いします

No.1375

Re:偶数魔方陣
投稿者---GGOOD(2004/02/27 11:23:13)


>偶数魔方陣の4N魔法陣のプログラムが分かりません!!
>どなたか教えてください!

こんにちは。4の倍数の魔方陣の作成方法は

4の倍数陣は4マス×4マスの大きさで区切り、対角線を記入。
左上を 1 とし、右に向かって順に記入。
ただし対角線の無いマスに数字は記入しない。
今度は右下を 1 として左に向かって順に記入。
ただし今度は対角線のあるマスには記入しない。
それぞれできあがった、図を重ねあわせた物が4n次魔方陣である。

というような方法で作成できます。
これにしたがってソースを組んでみてはいかがですか?

No.1376

Re:偶数魔方陣
投稿者---kana(2004/02/27 14:26:38)


始めたばかりで、理屈は分かってるのですが
いろはのいも分からない状態なんです・・。
始めはこれでいいんでしょうか?

private sub command1 click()
Const N=8

No.1377

Re:偶数魔方陣
投稿者---GGOOD(2004/02/27 15:20:10)


こんにちは。

>private sub command1 click()
> Const N=8

えーと、これってVBのプログラムの書き方じゃなかったですか・・・?
だとすれば僕にはぜんぜんわかりません。申し訳ないです。

No.1378

Re:偶数魔方陣
投稿者---GGOOD(2004/02/27 15:50:47)


ちなみに、C言語で書くと多分こんな感じになると思います。

Win95、BCC5.5でコンパイルも実行もできました。
多分結果も合ってると思います。

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

void fournhojin(int size);

int main(void){
    int size;
    
    printf("4の倍数を入力して下さい。>>\n");
    scanf("%d",&size);
    if((size % 4) != 0){
        printf("4の倍数ではありません。終了します。\n");
        return(0);  
    }
    
    fournhojin(size);
    return(0);
}

void fournhojin(int size){
    int **field,count,tate,yoko,i;
    
    field = (int **)malloc(sizeof(int *) * size);
    for(i=0;i<size;i++){
        field[i] = (int *)malloc(sizeof(int) * size);
    }
    
    count = 1;
    
    for(tate=0;tate<size;tate++){
        for(yoko=0;yoko<size;yoko++){
            if(tate % 4 == 0 || tate % 4 == 3){
                if(yoko % 4 == 0 || yoko % 4 == 3){
                    field[tate][yoko] = count;
                }
            }else if(tate % 4 == 1 || tate % 4 == 2){
                if(yoko % 4 == 1 || yoko % 4 == 2){
                    field[tate][yoko] = count;
                }
            }
            count++;
        }
    }
    
    count = 1;
    
    for(tate=size-1;tate>=0;tate--){
        for(yoko=size-1;yoko>=0;yoko--){
            if(tate % 4 == 0 || tate % 4 == 3){
                if(yoko % 4 == 1 || yoko % 4 == 2){
                    field[tate][yoko] = count;
                }
            }else if(tate % 4 == 1 || tate % 4 == 2){
                if(yoko % 4 == 0 || yoko % 4 == 3){
                    field[tate][yoko] = count;
                }
            }
            count++;
        }
    }
    
    for(tate=0;tate<size;tate++){
        for(yoko=0;yoko<size;yoko++){
            if(yoko == size - 1){
                printf("%d\n",field[tate][yoko]);
            }else{
                printf("%d\t",field[tate][yoko]);
            }
        }
    }

    for(i=0;i<size;i++){
        free(field[i]);
    }
    
    free(field);
}


No.1382

Re:偶数魔方陣
投稿者---kana(2004/02/28 01:40:51)


ありがとうございます!!
何も分からなかったのでとても助かりました!
これからもっと勉強していきます!
本当にありがとうございました!

No.1383

re:入力文字のチェックについて
投稿者---GGOOD(2004/02/28 16:03:44)


入力文字のチェックについてなのですが、

printf("4の倍数を入力して下さい。>>\n");
scanf("%d",&size);
if((size % 4) != 0){
printf("4の倍数ではありません。終了します。\n");
return(0);


上記の部分、4の倍数の入力待ちの部分ですが、
半角数字以外が入力された場合の処理を行いません。
多分isdigit()を使えばいいのでしょうが、

printf("4の倍数を入力して下さい。>>\n");
size = getchar();
if(isdigit(size) != 0 ||(size % 4) != 0){
printf("4の倍数ではありません。終了します。\n");
return(0);


ctype.hをインクルードして
上記のように変更すると4の倍数を入力しても、それ以外でもすべて
4の倍数ではない、と判定してしまいます。
おそらくgetchar()に変更したことが原因だと思うのですが、
どのように変更すれば入力されたものが数字かどうか
チェックできるのでしょうか?

どなたかご教示いただけませんでしょうか。
よろしくお願いします。

No.1384

re:入力文字のチェックについて
投稿者---NykR(2004/02/28 16:10:45)


> if(isdigit(size) != 0 ||(size % 4) != 0)

isdigit関数の使い方が間違っています。
isdigit(c)は、c が数字でなければ0を、数字であれば非0を返します。

> どのように変更すれば入力されたものが数字かどうか
> チェックできるのでしょうか?

元のやり方なら、scanfの戻り値を見ればいいです。

No.1385

re:入力文字のチェックについて
投稿者---GGOOD(2004/02/28 17:05:12)


NykRさん、御返信ありがとうございます。

>isdigit関数の使い方が間違っています。
>isdigit(c)は、c が数字でなければ0を、数字であれば非0を返します

そうですね、リファレンスを見て入力したのに間違えてました。

>> どのように変更すれば入力されたものが数字かどうか
>> チェックできるのでしょうか?
>元のやり方なら、scanfの戻り値を見ればいいです。

scanf("%d",&size);
このように受けたのですが、同じようにすべて「4の倍数ではない」と判定していました。
もう一度関数リファレンスを確認すると
isdigitなどの文字処理を行う関数は文字を引数に持つのですね。
という事は
scanf("%c",&size);
で受けなければならないと思い、そのように変更したのですが、
aや4の倍数以外はちゃんと判定してくれるのですが、

4を入力すると52(表示される最大数が2704→52の2乗の為)
8を入力すると56(同 3136→56の2乗)
12を入力すると4の倍数ではないと判定

このような結果になってしまいました。
%cが「1文字として入力する」となっている為、2桁の数字である12が
おかしいのはなんとなく分かるのですが、
4や8が52,56となってしまう理由が分かりません。

int size = 0;と初期化してみましたが、結果は変わりませんでした。
この場合数字かどうかのチェックはどのようにすべきなのでしょうか?

No.1386

re:入力文字のチェックについて
投稿者---NykR(2004/02/28 18:41:08)


>元のやり方なら、scanfの戻り値を見ればいいです。
scanf("%d",&size);
このように受けたのですが、同じようにすべて「4の倍数ではない」と判定していました。

で、どこでscanf()の戻り値を見ているのでしょう?


もう一度関数リファレンスを確認すると
isdigitなどの文字処理を行う関数は文字を引数に持つのですね。
という事は
scanf("%c",&size);
で受けなければならないと思い、そのように変更したのですが、

それはそれで正しいです。isdigitを使うなら。


4を入力すると52(表示される最大数が2704→52の2乗の為)
8を入力すると56(同 3136→56の2乗)
12を入力すると4の倍数ではないと判定

このような結果になってしまいました。
%cが「1文字として入力する」となっている為、2桁の数字である12が
おかしいのはなんとなく分かるのですが、
4や8が52,56となってしまう理由が分かりません。

sizeの値は、「4や8」ではなく、'4'や'8' です。
この場合は、sizeから '0' を引けば4や8になります。


この場合数字かどうかのチェックはどのようにすべきなのでしょうか?

だからscanf()の返却値(又は戻り値、あるいは返り値)。



No.1400

re:入力文字のチェックについて
投稿者---GGOOD(2004/03/02 13:03:07)


お返事が遅くなってしまいました。
NykRさん返信ありがとうございます。

>だからscanf()の返却値(又は戻り値、あるいは返り値)。

との事ですが、int scanf(char *format,...) ;
の戻り値はint型で、内容は入力されたデータの個数であるようなのですが、
これをどう利用すればよいのでしょうか?

    int size = 0;
    int d = 0;
    printf("4の倍数を入力して下さい。>>\n");
    d = scanf("%d",&size);
    if(isdigit(d) == 0 || (size % 4) != 0){
        printf("4の倍数ではありません。終了します。\n");
        return(0);  
    }

のように変更してみましたが、やはり判定部分がおかしいようなのですが
いかがでしょうか?


No.1404

re:入力文字のチェックについて
投稿者---NykR(2004/03/02 13:59:06)


> 内容は入力されたデータの個数であるようなのですが、

scanfは *第2引数以降が指すオブジェクトに代入された* 入力項目の個数を返します。

変換指定による変換が失敗すると即座に呼び出し元に戻るので、それ以降の項目は代入されません。

書式文字列の指令と違う項目が入力されると、変換に失敗します。


> これをどう利用すればよいのでしょうか?

返されたintの(種類ではなく)値をそのまま見ればいいです。

No.1390

re:入力文字のチェックについて
投稿者---あかま(2004/02/29 03:00:35)


>12を入力すると4の倍数ではないと判定
getcherやscanf("%c",&size);
は1文字しか入力できませんが「12」のような2文字の入力ができていないのでは?

No.1401

re:入力文字のチェックについて
投稿者---GGOOD(2004/03/02 13:05:27)


あかまさん、御返信ありがとうございます。

>getcherやscanf("%c",&size);
>は1文字しか入力できませんが「12」のような2文字の入力ができていないのでは?

おっしゃるとおりです。isdigit()が文字を引数に持つ、という事なので、
変更してみたのですが、やはりだめだったようですね。
引数や戻り値についてもう少し確認してみます。

No.1408

re:入力文字のチェックについて
投稿者---RAPT(2004/03/03 00:36:40)


サンプルコードです。
なるべく分かりやすく書いたつもりですが、参考になるでしょうか?

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

void sub(char str[]){
  size_t len = strlen(str), i;
  for(i = 0; i < len; i++){
    if(!isdigit(str[i])){
      printf("数字以外の文字が含まれています - [%s]\n", str);
      return;
    }
  }
  printf("数字文字のみで構成されています - [%s]\n", str);
}

int main(){
  sub("0123456789");
  sub("0123a56789");
  return 0;
}


No.1423

re:入力文字のチェックについて
投稿者---NykR(2004/03/04 13:38:12)


例えば、" 123" とか "123 " とか "12 3" という入力があった場合、
3つ目の様に、空白類文字が途中にあるものだけをエラーにするのが妥当だと思いますが、is〜系でこれに対応するのは結構面倒です。

というわけで私もサンプルを作ってみました。

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

int setInteger(int *dest, const char *src)
{
    char dummy;
    return sscanf(src, "%i %c", dest, &dummy) == 1;
}

int main(void)
{
    char buf[256];
    int  i;

    fgets(buf, sizeof(buf), stdin);

    if ( !setInteger(&i, buf) ) {
        fprintf(stderr, "not an int literal\n");
        return EXIT_FAILURE;
    }
    printf("i...%d\n", i);
    return EXIT_SUCCESS;
}