最速怪談選手権

C言語における2次元文字配列のポインタ渡しについてです。
メイン関数中で宣言した2次元文字配列aをローカル関数にポインタで渡し、配列の中身を書き換えたいのですが、うまくいきません。

void sub(char *a){
char b[5][5] = {"abcd","efgh","ijkl"};

for(i=0;i<3;i++){
for(j=0;j<30;j++){
a[i][j] = b[i][j];
}
}

}

int main(void){
char a[3][30];
sub(a);

for(i=0;i<3;i++){
printf("%s"a[i] );
}
}
↑のようにやったのですが駄目でした。
そもそもポインタで二次元配列aの先頭のアドレスのポインタを渡したらaの1行目はちゃんと場所を把握して読み取られそうですが2行目以降はちゃんと読み取ってもらえるのでしょうか。

C言語はまだ初心者なので、簡単な方法で、丁寧に教えていただけると嬉しいです。

A 回答 (4件)

単純な配列ならともかくニ次元以上の配列ならば、関数の引数には呼び出し元と同じ型にすべき


誤: void sub(char *a){ ← char 型のポインタ
正: void sub(char a[3][30]){ ← char[3][30] の配列型のポインタ

少々汎用的に書くなら
void sub(int m, int n, char a[m][n]){ ← 呼び出し側を sub(3,30,a) とすること

文字列のコピーは、string 系の関数を使えば間違いがない
誤: a[i][j] = b[i][j];
正: strcpy(a[i], b[i]);

string 系を使いたくないならば、文字列は '\x00' 末端で終わる配慮が必要
for (j=0; j<30; j++){
a[i][j] = b[i][j];
if (b[i][j] == '\x00') { break; }
}
    • good
    • 0

私もポインタについて偉そうなことをいえる立場ではないのですが


以下でいかがでしょうか。

-----
void sub( char (*a)[30] , int row){ /* 第1引数の型を変更, 第2引数追加 */
char b[5][30] = {"abcd","efgh","ijkl", "", ""}; /* 要素数[5]→[30], 文字列を追加 */
int i,j; /* 追加 */

for(i=0;i<row;i++){ /* 3 → row, main側のa[3][]を越えてコピーしない為*/
for(j=0;j<30;j++){ /* ここで30文字コピーしているので、b[][30]に変更した */
a[i][j] = b[i][j];
}
}
}

int main(void){
char a[3][30];
int i; /* 追加 */

sub(a, 3); /* 第2引数(a[3][]の3)を追加 */
for(i=0;i<3;i++){
printf("%s\n", &a[i] ); /* \nと,と&を追加 */
}

return 0;
}
-----

ポインタについては以下の書籍がお勧めです。
https://www.amazon.co.jp/%E6%96%B0%E3%83%BB%E6%A …
    • good
    • 0

C言語での文字列操作って、C言語最大の難関である「ポインタと配列」抜きには語れません。



やりたいことを早くやりたい、という気持ちもわかりますが、まずは「初心者」をやめることを目指した方がいいかと。

あるいは、 C言語自体を一旦やめるか。
他の多くの言語では、文字列操作にこんなにも悩むことはありません。



 char a[3][30];
これを二次元配列、と呼んでいますが、 C言語での扱いは 「『charが30個並んだ配列』が3つ並んだ配列」です。
配列のルールに従えば
 sub(a);
と関数の呼び出しに名前の a だけで使った場合には、 ポインタと見做されます。
つまり
「『charが30個並んだ配列』が3つ並んだ配列」

「『charが30個並んだ配列』へのポインタ」
となります。

ところが、受ける関数sub は
void sub(char *a){
と「charのポインタ」で受けようとしています。
char と 『charが30個並んだ配列』 とでは、当然型は一致しません。
型は揃えるのが基本です。


また
a[i][j] = b[i][j];
ここでのaはmainの char a[3][30]; ではなく、 void sub(char *a){ の char *a のaです。
aが char * なのですから、 a[i] は char です。 char には []を付けることはできません。よってエラーになります。
これも、正しい型を使っていないのが原因です。



それを直したとして
char b[5][5] = {"abcd","efgh","ijkl"};

for(i=0;i<3;i++){
for(j=0;j<30;j++){
a[i][j] = b[i][j];
}
}

これが「コンパイルではエラーにならないけど、実行したら重大な問題を起す可能性のあるプログラム」になっていることに気付きませんか?
気付けないのなら、ポインタと配列のことを勉強しなおしましょう。
    • good
    • 0

どう見たって


printf("%s"a[i] );
はおかしいよな.
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!