動的多元配列で、
Voidポインタに、多種の型がぶら下がった多元配列を作り、
読み書きをしたいのですがどのようにしたらよろしいでしょうか。
具体的には、
x[0][1]は、intで「2」が入っている
x[0][4]は、intで「9」が入っている
x[1][2]は、charでしかも文字列の配列で「goo」が入っている
x[1][5]は、charでしかも文字列の配列で「教えて」が入っている
x[0]は、int型の配列。X[1]は、文字列型の配列。
というようなものです。
一応ソースは作ってみたのですが、int型では問題なくいくのですが、
文字列は、コンパイルはできますが、実行すると予期せぬことが起きます。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main (void) {
void **topPointa;
int * iDataInput;
int * iDataOutput ;
char * chDataInput;
char * chDataInput2;
char * chDataOutput1 ;
// ポインタアドレス用のメモリ確保
topPointa = (void *) calloc (10 , sizeof(void *));
if(topPointa == NULL) {
printf("メモリが確保できません\n");
exit(-1);
}
//int配列のメモリ確保
iDataInput = (int * ) calloc (10 , sizeof(int));
if(iDataInput == NULL) {
printf("メモリが確保できません\n");
exit(-1);
}
iDataInput[0] = 3 ;
iDataInput[1] = 4 ;
topPointa[0] = (void * ) &iDataInput;
//int配列の取り出し
iDataOutput = *(int *) topPointa[0];
printf( "int: %d\n", iDataOutput[0] );
printf( "int: %d\n", iDataOutput[1] );
//char配列 のメモリ確保
chDataInput = (char * ) calloc (10 , sizeof(char *));
if(chDataInput == NULL) {
printf("メモリが確保できません\n");
exit(-1);
}
chDataInput2 = (char * ) calloc (10 , sizeof(char));
if(chDataInput2 == NULL) {
printf("メモリが確保できません\n");
exit(-1);
}
strcpy(chDataInput2 , "hoe");
chDataInput[0] = &chDataInput2;
topPointa[1] = (void * ) &chDataInput;
//char配列の取り出し
chDataOutput1 = *(char *) topPointa[1];
printf( "char: %S\n", chDataOutput1[0] );
free(iDataInput);
free(chDataInput);
free(chDataInput2);
return 0;
}
言語は、C言語ANCI Cでお願いします。
以上。よろしくお願いします。
No.2ベストアンサー
- 回答日時:
★アドバイス
・最初に
誤→topPointa = (void *) calloc (10 , sizeof(void *));
正→topPointa = (void **) calloc (10 , sizeof(void *));
誤→tchDataInput = (char * ) calloc (10 , sizeof(char *));
正→tchDataInput = (char **) calloc (10 , sizeof(char *));
※chDataInputはchar**にすべきです。
※文字列型の配列をchar*の配列として表現するため。
>Voidポインタに、多種の型がぶら下がった多元配列を作り、
↑
共用体を利用して実現できませんか。
例えば:
typedef struct tagPOINTER {
union {
void *ptr;
int *i;
char **c;
} x;
} POINTER;
void **top;
POINTER *set;
// void*配列の確保
top = calloc( 10, sizeof(void*) );
// 代入用にキャスト
set = (POINTER *)top;
// int配列の確保
set[0].x.ptr = calloc( 10, sizeof(int) );
// char*配列の確保
set[1].x.ptr = calloc( 10, sizeof(char*) );
// 代入処理
set[0].x.i[1] = 2;
set[0].x.i[4] = 9;
set[1].x.c[2] = strdup( "goo" );
set[1].x.c[5] = strdup( "教えて" );
↑
>具体的には、
>x[0][1]は、intで「2」が入っている
>x[0][4]は、intで「9」が入っている
>x[1][2]は、charでしかも文字列の配列で「goo」が入っている
>x[1][5]は、charでしかも文字列の配列で「教えて」が入っている
>x[0]は、int型の配列。X[1]は、文字列型の配列。
>というようなものです。
より。
// void**で受け取る
static void func( void **top )
{
POINTER *get = (POINTER *)top;
printf( "get[0].x.i[1] = %d\n", get[0].x.i[1] );
printf( "get[0].x.i[4] = %d\n", get[0].x.i[4] );
printf( "get[1].x.c[2] = %s\n", get[1].x.c[2] );
printf( "get[1].x.c[5] = %s\n", get[1].x.c[5] );
printf( "\n" );
}
※strdup関数はANSI-Cではないので同様な関数を自作しましょう。
この回答への補足
一応、他の方が見られても解るように、
最終的な(共用体はなしで)ソースを載せておきます。
#include <stdio.h> // printf
#include <stdlib.h> // callc,exit,free
#include <string.h> // strcpy
int main (void) {
int i,j;
// ポインタへのポインタ
void **topPointa;
// int時の受け渡しポインタ
int * iDataInput;
int * iDataOutput ;
// char時の受け渡しポインタ
char ** chDataInput;
char ** chDataOutput;
/************** ポインタアドレスの確保 *********/
topPointa = (void **) calloc (10 , sizeof(void *));
if(topPointa == NULL) {
printf("メモリが確保できません[topPointa]\n");
exit(-1);
}
/************** int型の確保 ********************/
// int配列のメモリ確保
iDataInput = (int * ) calloc (10 , sizeof(int));
if(iDataInput == NULL) {
printf("メモリが確保できません[iDataInput]\n");
// メモリ開放
free(topPointa);
exit(-1);
}
// データの入力
iDataInput[0] = 3 ;
iDataInput[1] = 4 ;
topPointa[0] = (void * ) &iDataInput;
//int配列の取り出し
iDataOutput = *(int **) topPointa[0];
printf( "int: %d\n", iDataOutput[0] );
printf( "int: %d\n", iDataOutput[1] );
/************** char型の確保 ********************/
// char配列 のメモリ確保
chDataInput = (char ** ) calloc (10 , sizeof(char *));
if(chDataInput == NULL) {
printf("メモリが確保できません[chDataInput]\n");
// メモリ開放
free(topPointa);
free(iDataInput);
exit(-1);
}
for(i=0;i<10;i++)
{
chDataInput[i] =(char*)calloc(10 , sizeof(char));
if(chDataInput[i] == NULL) {
printf("メモリが確保できません[chDataInput(%d)] \n",i);
// メモリ開放
free(topPointa);
free(iDataInput);
for ( j = i ; 0 <= j ; j--)
free(chDataInput[j]);
break;
}else {
printf("chDataInput[%d]確保\n" ,i );
}
}
// データの入力
strcpy(chDataInput[1] , "hoe");
topPointa[1] = (void * ) chDataInput;
// char配列の取り出し
chDataOutput = (char **) topPointa[1];
printf( "char: %s\n", chDataOutput[1] );
// 開放
free(topPointa);
free(iDataInput);
for ( i = 0 ; i < 10 ; i++)
free(chDataInput[i]);
return 0;
}
ご返答ありがとうございます。
自己解決していました。
ご指摘のとおりメモリの確保時のポインタが間違ってました。
・共用体
なるほど、確かにこういう使い方が、良いですね。
検討してみます。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# c言語配列の結合についてです。 なぜうまくいかないのでしょうか。 #include <stdio.h 4 2022/05/30 22:42
- C言語・C++・C# 宣言する関数の形が決まっている状態で、 str1とstr2の文字列をこの順に引っ付けてstrに保存し 2 2022/05/30 18:21
- C言語・C++・C# プログラミングの授業の課題です 1 2023/01/17 22:15
- C言語・C++・C# c言語でユーザ関数を利用して入力された文字列を反転させるプログラムを作りたいです。 3 2023/01/29 19:47
- C言語・C++・C# c言語 プログラムのエラー 1 2023/02/11 20:31
- C言語・C++・C# C言語のエラーについて 2 2022/07/11 13:56
- C言語・C++・C# C言語で再起関数とポインタを用いて文字列反転をする方法がわかりません。 4 2023/04/29 20:32
- C言語・C++・C# c言語の問題の説明、各所ごとに 5 2023/07/26 11:03
- C言語・C++・C# c言語の問題です 3 2023/01/10 16:15
- C言語・C++・C# バイナリファイルをコピーするのにかかる時間を測りたいのですが実行するとFatel error:gli 2 2022/11/03 01:10
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
関数から配列を返すには?
-
C#で構造体の配列を持った構造...
-
構造体のextern方法
-
配列の要素数に変数を入れたい...
-
C言語を使って、ファイルの読み...
-
[C++/CLI]マネージコードで配列...
-
define で 配列
-
配列のアドレス部
-
AfxBeginThread の引数について
-
C言語についてです 5人のテスト...
-
MFCのCArrayを使った二次元配列
-
プログラム 数列の和
-
万年カレンダーについて。
-
bmpやImageの配列を関数の引数...
-
char型配列をint型に代入するには
-
配列のNULL初期化について
-
c言語の自分で数字を入力してサ...
-
C言語において、 配列要素をひ...
-
c言語
-
C#で配列が空かを判定するには?
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
関数から配列を返すには?
-
配列の要素数に変数を入れたい...
-
c言語
-
構造体のextern方法
-
define で 配列
-
C#で構造体の配列を持った構造...
-
C言語において、 配列要素をひ...
-
コンボボックスでデフォルト値...
-
2番目の最大値を求める
-
C言語の2次元配列 容量が大き...
-
C#で配列が空かを判定するには?
-
MFCのCArrayを使った二次元配列
-
C言語の課題が出たのですが自力...
-
C言語 ファイルの指定された行...
-
Cのエラー
-
ポインタを使って構造体の配列...
-
配列のアドレス部
-
char型配列をint型に代入するには
-
MFC - ダイアログボックスのPic...
-
C言語から質問です。
おすすめ情報