こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

解決済みの質問

オラクルDB選択レコードの配列代入

オラクル9.0にて、DB(xxxxxx)から選択したレコード項目(record)
を、配列(group)に代入したいのですが、うまくいきません。
よろしくお願いします。

メイン(main)
main
char group[ ];
nSts = GetGroupIcids(nCountGroup);
if (RT_NORMAL != nSts)
{
return (RT_ERROR);
}

レコード選択処理(GetGroupIcids)
EXEC SQL INCLUDE sqlca;

#include <stdio.h>
#include <sys/types.h>
#include "com/comdef.h"


int GetGroupIcids(int nCount)
{
int nRtn = RT_NORMAL;
int nIndex;
EXEC SQL BEGIN DECLARE SECTION;
char www_corp[14];
EXEC SQL END DECLARE SECTION;


EXEC SQL DECLARE CUR1 CURSOR FOR
SELECT
record
FROM
XXXXXXXX;
EXEC SQL OPEN CUR1;

/*取得したカードIDを配列に代入*/
for (nIndex = 0; nIndex < nCount; nIndex++)
{
EXEC SQL FETCH CUR1 INTO :www_corp;
group[nIndex]=www_corp;
}

EXEC SQL CLOSE CUR1;

return (nRtn);
}

投稿日時 - 2006-11-17 19:52:48

QNo.2545799

すぐに回答ほしいです

質問者が選んだベストアンサー

補足拝見しました。
ポイントがいくつかあります。
●ポイント1 groupの型宣言について

> group[]は文字列型になります。文字数は14桁です。
まず、C言語に「文字列型」というのはありません。charの配列を文字列として扱っています。したがって、
char group[];
は「1つの文字列を宣言」しているだけで、これ自体では「文字列の配列」にはなりません。

GetGroupIcids()の中で、group[]に「FETCHで取得した複数の文字列を代入」したいのであれば、groupは「文字列の配列」と宣言しなくてはなりません。

文字列の配列を宣言するには、文字列自体が「charの配列」のため、「charの配列の配列」と宣言する必要があります。
char group[];
が1つの文字列の宣言を意味するので、文字列の配列の宣言は、
char group[][];
という形になります。文字列が14バイトであれば、
char group[][14];
と宣言するのがよいでしょう。(多次元配列で2次元目が内側に来るのでご注意)

●ポイント2 文字列のコピー
C言語では文字列型というのがないので、a = b; というような「文字列変数への代入」というような式は使えません。
文字列を操作するには、文字列操作関数を用いるのが一般的です。
char to[10];
char from[10];
と宣言された2つの文字列間でコピーを行うときは、
strcpy(to, from);
という書き方をします。

したがって、GetGroupIcids()における
group[nIndex]= www_corp;
はエラーは出ませんが正常に動作しません。(ぜんぜん違う意味の式になっています)

この部分は、
strcpy(group[nIndex],www_corp);
と書くべきでしょう。

もし「レコード内容をdbに登録する」の中でも同じような記述があるのであれば、見直してみてください。

投稿日時 - 2006-11-20 12:48:23

お礼

おそくなってもうしわけありません。
本当に感謝しています。
ありがとうございました。
別件で、聞きたいことがあります。
よかったら、アドバイスください。

投稿日時 - 2006-12-12 21:47:15

このQ&Aは役に立ちましたか?

2人が「このQ&Aが役に立った」と投票しています

回答(4)

ANo.3

ちょっと追加です。
GetGroupIcids()の中で、
char icid_corp[14];
と宣言されているので、カードIDは13文字以下の文字列、あるいは13桁以下の数値ですよね。
仮に文字列として扱われている場合、
char group[ ];

char group[ ][14];
とすべきで、

group[nIndex]=www_corp;
は、
memset(group[nIndex],0,sizeof(group[nIndex]))
strncpy(group[nIndex],www_corp,13);
とすればいいかと。(本当は13とか14とかのマジックナンバーは埋め込まずに定数を使うべきですが)

投稿日時 - 2006-11-17 22:34:25

ANo.2

No.1です。

> ・配列の宣言は、空白のままで通っています。
あ、そうなんですか。それならいいです。

> 4.配列の値は、CheckCardsuminf関数にて使用する。
とありますが、どう使用されているのかがわかりません。
カードIDというのは文字列なのでしょうか、数値なのでしょうか。それによってどう修正するべきかが変わってきます。
とりあえず、CheckCardsuminfo()の中でgroup[]が数値(整数)として扱われているのか、文字列として扱われているのか教えてください。

それから、
int GetGroupIcids(int nCount)
と定義されているのに、
CheckCardsuminf()関数の中では、
nCountGroup = GetGroupIcids();
と引数なしで呼ばれています。引数に渡した数だけループしてFETCHして配列に格納しているようなのですが、これはなぜでしょうか。

すみませんが、以上の点を補足願えますか?

投稿日時 - 2006-11-17 22:16:03

補足

2.CheckCardsuminf関数
1.> 4.配列の値は、CheckCardsuminf関数にて使用する。について
 ・group[]は文字列型になります。文字数は14桁です。
 
2.int GetGroupIcids(int nCount)と定義されているのに、
CheckCardsuminf()関数の中では、について
・nSts = GetGroupIcids(nCountGroup)が正解です。
  その前に、GetCountGroup関数にて件数を格納します。
 ・GetGroupIcids関数にて件数分の配列にカードIDを代入する。
 ・GetCountRecord関数にて、配列にあるカードIDが、あるDB
に何レコードあるか確認し、2レコードならDBに登録する。
  
CheckCardsuminf関数
char group[ ]; /* グループID格納 * /
int CheckCardsuminfo()
{
/*カードIDグループ件数取得*/
nCountGroup = GetCountGroup();
if (0 == nCountGroup)
{
return (RT_NOICID);
}
/*カードID一覧取得(グループ)/*
nSts = GetGroupIcids(nCountGroup);
if (RT_NORMAL != nSts)
{
return (RT_ERROR);
}
for (nIndex = 0; nIndex < nCountGroup; nIndex++)
{
/*レコード内容抽出*/
nCountRecord = GetCountRecord(group[nIndex]);
if (1 == nCountRecord)
{
continue;
}
else if (2 == nCountRecord)
{
レコード内容をdbに登録する
}
    }
}






}
}

投稿日時 - 2006-11-20 11:03:48

ANo.1

よくわからないところがあるので補足をお願いします。

まず、
char group[ ];
ですが、

・配列の宣言では、宣言時に初期化する場合以外は、明示的に要素数を指定する必要があったと思うのですが、これでコンパイル通ってますか?(最近Cから遠ざかっているから、知らないうちに仕様変わったのかな…)

・ソースを見る限り、これはmain()の中でローカルに宣言されているようですが、GetGroupIcids()の中で値を代入しているように見えます。スコープ外なので、main()以外の関数からこの配列変数は見えないと思うのですが。アップするためにソースの一部をカットして切り貼りしているうちに、本当はmainの外で宣言されているのを中に書いてしまったのでしょうか?

それはとりあえず置いておいて、GetGroupIcids()の中ですが、
group[nIndex]=www_corp;
というのは、FETCHしてwww_corpに入れた「数値」をgroup[]に代入したいのでしょうか?

とすると、www_corp[]は文字列の配列なので、
group[nIndex]=atoi(www_corp);
というように数値に変換する必要があります。しかし上記ではgroup[]はchar型の配列として宣言されています。なぜでしょうか?

もし文字列としてコピーしたいのであれば、
strcpy(group[nIndex],www_corp);
などとする必要がありますが、それならばgroupはcharの配列でなくchar[]の配列でないといけないですよね。

アップするためにソースの大部分を省略していると思うのですが、大事なところをもう少し正確に書いていただいた方が解決が早いと思います。(mainの宣言も本当は int main() { という形式のはずなのにmainの一言で終わってますよね)

投稿日時 - 2006-11-17 21:08:39

補足

・配列の宣言は、空白のままで通っています。
 char group[ ];で、宣言してます。
・流れは、以下の通りです。
 1.メイン関数
int main(int argc, char** argv)
  {
   nSts = CheckCardsuminfo();
if (RT_NORMAL != nSts)
{
CloseDb(DF_FLAG_OFF);
nRtn = nSts;
  }
}
2.CheckCardsuminf関数
char group[ ]; /* グループID格納 * /
int CheckCardsuminfo()
{
nCountGroup = GetGroupIcids();
if (0 == nCountGroup)
{
return (RT_NOICID);
}
}
3.GetGroupIcids関数
  int GetGroupIcids(int nCount)
{
int nRtn = RT_NORMAL;
int nIndex;
EXEC SQL BEGIN DECLARE SECTION;
char icid_corp[14];
EXEC SQL END DECLARE SECTION;


EXEC SQL DECLARE CUR1 CURSOR FOR
SELECT
CARDID
FROM
XXXXXXXXDB;
EXEC SQL OPEN CUR1;

/*取得したカードIDを配列に代入*/
for (nIndex = 0; nIndex < nCount; nIndex++)
{
EXEC SQL FETCH CUR1 INTO :icid_corp;
group[nIndex]=icid_corp;
}
・データの流れは、以下のようになります。
 1.GetGroupIcids関数にて、DBより、CARDIDを抽出する。
 2.FETCHにて、変数icid_corpに代入する
 3.変数icid_corpを、配列groupに代入する。
 4.配列の値は、CheckCardsuminf関数にて使用する。

・以下の文章ですが、初期設定をどう変えれば、いいのでしょうか?  →groupはcharの配列でなくchar[]の配列

投稿日時 - 2006-11-17 21:15:27

あなたにオススメの質問