C言語関係掲示板

過去ログ

No.991 関数への二次元配列の渡し方

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

関数への二次元配列の渡し方
投稿者---目指せ!Cマスター(2004/02/25 16:56:30)


こんにちは

下記のようなコーディングをしたのですが、関数間の受け渡しが
うまく行っていないようで、関数sampleで受け取った値が化けて
出ます。

このような場合関数の宣言等、どのようにすれば良いのでしょうか?
#include<stdio.h>

void sample (char **);

void main (void)
{
int iCnt1;
char str[][128]= {"AAA",
"BBB",
"CCC",
"DDD",
""};

iCnt1 = 0;
while (str[iCnt1][0] != '\0'){
(void)printf("str[%d] = %s\n", iCnt1, str[iCnt1]);
iCnt1++;
}

sample (str);

return;
}

void sample (char **pstr)
{
int iCnt2;


iCnt2 = 0;
while (pstr[iCnt2] != NULL){
(void)printf("pstr[%d] = %s\n", iCnt2, pstr[iCnt2]);
iCnt2++;
}
return;
}

No.12955

Re:関数への二次元配列の渡し方
投稿者---Cマニア(超初心者)(2004/02/25 17:43:04)


こうするとできました。

#include<stdio.h>

void sample (char [][128]);

void main (void){

    int iCnt1;
    char str[][128]= {"AAA",
                        "BBB",
                        "CCC",
                        "DDD",
                            ""};

    iCnt1 = 0;

    while (str[iCnt1][0] != '\0'){
        (void)printf("str[%d] = %s\n", iCnt1, str[iCnt1]);
        iCnt1++;
    }

    sample(str);

    return;
}

void sample (char pstr[][128]){
    int iCnt2;

    iCnt2 = 0;

    while (pstr[iCnt2][0] != '\0'){
        (void)printf("pstr[%d] = %s\n", iCnt2, pstr[iCnt2]);
        iCnt2++;
    }

    return;
}



一応私も初心者ですので、これでいいのかあまり自信がありませんが・・・。
それからちょっと質問したいことがあります。
        (void)printf("pstr[%d] = %s\n", iCnt2, pstr[iCnt2]);

とprintfを(void)とするのはなぜでしょうか?
それからvoid型なので値を返さないと言うのはわかりますが、
  return; 
を入れる理由もよろしければ教えてください。


No.12957

Re:関数への二次元配列の渡し方
投稿者---目指せ!Cマスター(2004/02/25 18:26:27)


Cマニア(超初心者)さんありがとうございます。
記述していただいた物で、正常に動作します。

しかし
void sample (char [][128]);

としか、できないのですかね?
char      string[128]

を渡す場合
void sample (char [128]);


void sample (char *);

は等価ですよね?

同じ考えで
void sample (char **);

にしたんですけど・・・。


>一応私も初心者ですので、これでいいのかあまり自信がありませんが・・・。
>それからちょっと質問したいことがあります。
>
        (void)printf("pstr[%d] = %s\n", iCnt2, pstr[iCnt2]);
とprintfを(void)とするのはなぜでしょうか?
>それからvoid型なので値を返さないと言うのはわかりますが、
>  return; 
>を入れる理由もよろしければ教えてください。

printfは戻り値を返しますよね?それを無視するからvoidを付けます。
詳しくは説明できませんが、void型でreturnを返すのもそうなんですが、
今、自分の学校の実行環境がUNIXなんですよ。作るのはWINDOWSですが。
それでコンパイラ(Sun Microsystems C)ではエラーも警告もでないの
ですが、LINTってコマンドでソースをチェックすると色々でるんですよね。
「〜は値を返す必要があります。」とか、
「値が初期化されていない可能性のあるポインタを使用しています。」とか、
「警告: 32 ビット符号なし整数の 32 ビット符号付き整数への代入。」など。
これのエラーとか警告を可能な限り減らして、プログラム上の起こりえる問題を
減らすってのが目的でやってます。

あと、宣言の事、分かる方いらしたらお願いします。


No.12958

Re:関数への二次元配列の渡し方
投稿者---Cマニア(超初心者)(2004/02/25 18:39:58)


なるほど、そういうことでしたか。勉強になりました、ありがとうございます。
>
string[128]

>を渡す場合
void sample (char [128]);

>と
void sample (char *);

>は等価ですよね?
>同じ考えで
>
void sample (char **);
>にしたんですけど・・・。

このことについてですが、うまく説明できませんが等価ではないと思います。
ポインタへのポインタ変数がどういうものなのかを考えればわかると思いますが・・・。
間違っていることを言っていたら、どなたか教えてください。

No.12960

Re:関数への二次元配列の渡し方
投稿者---BlackWind(2004/02/25 19:05:17)


void sample (char **);
にしたんですけど・・・。

#include<stdio.h>

void sample (char ** );

void main (void){

    char str[][128]= {"AAA", "BBB", "CCC", "DDD", "" };

    ・・・中略・・・

    sample((char**)str);

    return;
}

void sample (char **pstr){
     
    ・・・中略・・・

    return;
}



No.12961

Re:関数への二次元配列の渡し方
投稿者---Cマニア(超初心者)(2004/02/25 19:11:45)


BlackWindさん、どうもうまくいかないのでソース全体を載せてもらえますか?

No.12965

Re:関数への二次元配列の渡し方
投稿者---たか(2004/02/25 21:47:25)


横入り失礼します。(char **)に無理矢理キャストしても、元の配列は
ポインタ配列ではないのでうまく動きません。その場合は元の配列を
char*型へのポインタ配列として定義しましょう。

#include<stdio.h>

void sample(char **);

int main (void)
{
  int iCnt1;
  char *str[128]= {"AAA","BBB","CCC","DDD",""};

  iCnt1 = 0;
  while (str[iCnt1][0] != '\0'){
    printf("str[%d] = %s\n", iCnt1, str[iCnt1]);
    iCnt1++;
  }

  sample(str);

  return 0;
}

void sample(char **pstr)
{
  int iCnt2;

  iCnt2 = 0;
  while (pstr[iCnt2][0] != NULL){
    printf("pstr[%d] = %s\n", iCnt2, pstr[iCnt2]);
    iCnt2++;
  }
}


No.12967

Re:関数への二次元配列の渡し方
投稿者---NykR(2004/02/25 23:10:18)


void sample (char [][128]);
としか、できないのですかね?
char      string[128]
を渡す場合
void sample (char [128]);
void sample (char *);
は等価ですよね? 同じ考えで
void sample (char **);
にしたんですけど・・・。

関数の仮引数の宣言では、配列型の宣言は、その要素型へのポインタ型の宣言に読み換えられます。従って、
void sample (char [128]);
void sample (char *);
は等価です。

また、
void sample (char pstr[][128]);
の仮引数の宣言は、"char[128]型の配列型" の宣言なので、
"char[128]型へのポインタ型" に読み換えられます。が、

ここで宣言されているのはあくまで "char[128]型の配列型" であって
char[128]型ではないので、 char[128]の部分は、そのままchar[128]型として扱われます。

従って、char[][128]型と char **型とは、関数の仮引数宣言においても等価ではありません。

No.12969

Re:関数への二次元配列の渡し方
投稿者---nop(2004/02/26 09:11:49)


>void main (void)

規格に沿うなら main() の戻りは int 型にするべきでしょう。

×void main(/*略*/)
○int main(/*略*/)