第12講 ポインタを利用してテトリスからグローバル変数とグローバル配列を追放する!

第5話 2次元配列をいかにして送るか?
1次元配列の場合、第3話で第11講第8話から引用しましたように、
#include<stdio.h>
#include<stdlib.h>
void f(int
x[]); //データを作成する社員
void g(int x[]); //データを表示する社員
int main(){
  int x[5];
  f(
x);
  g(
x);
  return(0);
}
void f(int x[]){
  int i;
  for(i=0;i<5;i++)x[i]=rand()%10;
}
void g(int x[]){
  int i;
  for(i=0;i<5;i++)printf("%d ",x[i]);
  printf("\n");
}
コピペ用添付ファイル
配列を引数にできます。
2元配列も同様にできるはずですので、
第1講第7話で作ったプロジェクトaまたは第3講第1話で作ったプロジェクトbを開いて、
コードを次のように変更してみましょう。
#include<stdio.h>
#include<stdlib.h>
void f(int x[][]); //データを作成する社員
void g(int x[][]); //データを表示する社員
int main(){
  int x[5][4];
  f(x);
  g(x);
  return(0);
}
void f(int x[][]){
  int i,j;
  for(i=0;i<5;i++){
    for(j=0;j<4;j++){
      x[i][j]=rand()%10;
    }
  }
}
void g(int x[][]){
  int i,j;
  for(i=0;i<5;i++){
    for(j=0;j<4;j++){
      printf("%d ",x[i][j]);
    }
    printf("\n");
  }
}
コピペ用添付ファイル
ところが、エディタに入力した時点で、

などと赤い波線が出てきてしまします。
1>------ ビルド開始: プロジェクト: a, 構成: Debug Win32 ------
1> a.cpp
1>d:\vcpp2010\a\a\a.cpp(3): error C2087: 'x' : 添字がありません。
1>d:\vcpp2010\a\a\a.cpp(4): error C2087: 'x' : 添字がありません。
1>d:\vcpp2010\a\a\a.cpp(7): error C2664: 'f' : 1 番目の引数を 'int [5][4]' から 'int [][1]' に変換できません。(新しい機能 ; ヘルプを参照)
1> 指示された型は関連がありません。変換には reinterpret_cast、C スタイル キャストまたは関数スタイルのキャストが必要です。
1>d:\vcpp2010\a\a\a.cpp(8): error C2664: 'g' : 1 番目の引数を 'int [5][4]' から 'int [][1]' に変換できません。(新しい機能 ; ヘルプを参照)
1> 指示された型は関連がありません。変換には reinterpret_cast、C スタイル キャストまたは関数スタイルのキャストが必要です。
1>d:\vcpp2010\a\a\a.cpp(11): error C2087: 'x' : 添字がありません。
1>d:\vcpp2010\a\a\a.cpp(19): error C2087: 'x' : 添字がありません。
========== ビルド: 0 正常終了、1 失敗、0 更新不要、0 スキップ ==========



エディタの波線を消すために
#include<stdio.h>
#include<stdlib.h>
void f(int x[]); //データを作成する社員
void g(int x[]); //データを表示する社員
int main(){
  int x[5][4];
  f(x);
  g(x);
  return(0);
}
void f(int x[]){
  int i,j;
  for(i=0;i<5;i++){
    for(j=0;j<4;j++){
      x[i][j]=rand()%10;
    }
  }
}
void g(int x[]){
  int i,j;
  for(i=0;i<5;i++){
    for(j=0;j<4;j++){
      printf("%d ",x[i][j]);
    }
    printf("\n");
  }
}
と打ち直すと、

のように事態は悪化して赤い波線が増えてしまいます。
そこで、さらに
#include<stdio.h>
#include<stdlib.h>
void f(int x[][]); //データを作成する社員
void g(int x[][]); //データを表示する社員
int main(){
  int x[5][4];
  f(&x[0][0]);
  g(&x[0][0]);
  return(0);
}
void f(int x[][]){
  int i,j;
  for(i=0;i<5;i++){
    for(j=0;j<4;j++){
      x[i][j]=rand()%10;
    }
  }
}
void g(int x[][]){
  int i,j;
  for(i=0;i<5;i++){
    for(j=0;j<4;j++){
      printf("%d ",x[i][j]);
    }
    printf("\n");
  }
}
としても

など波線を消すことはできません。

いろいろ試行錯誤をしても2次元配列をそのものを引数にするのはむずかしいようです。
実際には、方法があるのかもしれませんが、それがわかりませんので、
私は、次のようにして問題を解消しています。
#include<stdio.h>
#include<stdlib.h>
void f(int **x); //データを作成する社員
void g(int **x); //データを表示する社員
int main(){
  int **x=(int **)malloc(sizeof(int)*5); //配置担当
  for(int i=0;i<12;i++)*(x+i)=(int *)malloc(sizeof(int)*4);
  f(x);
  g(x);
  return(0);
}
void f(int **x){
  int i,j;
  for(i=0;i<5;i++){
    for(j=0;j<4;j++){
      x[i][j]=rand()%10;
    }
  }
}
void g(int **x){
  int i,j;
  for(i=0;i<5;i++){
    for(j=0;j<4;j++){
      printf("%d ",x[i][j]);
    }
    printf("\n");
  }
}
コピペ用添付ファイル
つまり、2次元配列を引数にすることをあきらめて、
2次元ポインタを用意して、それを引数にするということです。
本当は、私が2次元ポインタと呼んでいるものはポインタへのポインタと言います。
でもこの表現は、初心者を混乱に陥れるだけですので、
私は、2次元ポインタと名付けています。
2次元の意味は
      x[i][j]=rand()%10;
のように添え字が2つだからです。
これを参考にして、
2つのグローバル配列を
char chizu[12][27]; //配置担当
char chizumodosu[12][27]; //地図配置を元に戻す1:可0:不可
をローカル2次元ポインタに変更しましょう。


第4話へ   第6話へ

第2部目次に戻る  第1部目次に戻る


初心者のための excel 2016 マクロ VBA 入門講義 基礎から応用まで
vc++ c言語 c++ 入門 初心者 基礎から応用まで
ecliqse c++ 入門
魔方陣 数独で学ぶ VBA 入門

数独のシンプルな解き方・簡単な解法の研究
VB講義へ
VB講義基礎へ
初心者のための世界で一番わかりやすいVisual C++入門基礎講座
初心者のための世界で一番わかりやすいVisual Basic入門基礎講座
初心者のための世界で一番わかりやすいVBA入門講義(基礎から応用まで)
初心者のための VC++による C言語 C++ 入門 基礎から応用まで第1部
ecliqse java 入門
java 入門 サイト 基礎から応用まで
本サイトトップへ