![](http://oshiete.xgoo.jp/images/v2/pc/qa/question_title.png?e8efa67)
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件)
- 最新から表示
- 回答順に表示
No.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; }
}
No.3
- 回答日時:
私もポインタについて偉そうなことをいえる立場ではないのですが
以下でいかがでしょうか。
-----
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 …
No.2
- 回答日時:
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];
}
}
これが「コンパイルではエラーにならないけど、実行したら重大な問題を起す可能性のあるプログラム」になっていることに気付きませんか?
気付けないのなら、ポインタと配列のことを勉強しなおしましょう。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# c言語配列の結合についてです。 なぜうまくいかないのでしょうか。 #include <stdio.h 4 2022/05/30 22:42
- C言語・C++・C# ポインタの型変換、どうやるんでしたっけ? 2 2022/03/28 11:00
- C言語・C++・C# C言語初心者 ポインタについて、お助けください、、 2 2023/03/15 23:50
- C言語・C++・C# c言語の問題です 課題1 (二分探索木とセット) 大きさ size の配列 array を考える。す 2 2023/01/10 21:08
- C言語・C++・C# C言語プログラム変更 2 2022/12/21 15:03
- C言語・C++・C# C言語のエラーについて 2 2022/07/11 13:56
- C言語・C++・C# c言語 プログラムのエラー 1 2023/02/11 20:31
- C言語・C++・C# C言語初心者 構造体 課題について 2 2023/03/10 19:48
- Perl perlで2次元配列をサブルーチンに値渡しで渡す 5 2022/12/17 18:49
- C言語・C++・C# C言語の課題が出たのですが自力でやっても分かりませんでした。 要素数がnであるint型の配列v2の並 3 2022/11/19 17:41
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
char*を初期化したいのですが
-
C言語にて構造体のメンバがNULL...
-
strcat関数を自作したいです
-
C言語で文字列をかえす正しい書...
-
new charとnew char[N]の違いは?
-
小数点入りの文字列をfloat型に...
-
C言語のintとcharの違いってな...
-
char型にint型の数値を代入する。
-
const char* s1とただのchar s1...
-
36進数
-
CStringからchar*への型変換に...
-
C言語のchar型配列を計算させる...
-
文字列の途中から途中までを抽出
-
警告
-
C言語の文字列について
-
多次元配列のメモリ解放
-
SetWindowTextについて。
-
szとlpszの違い
-
char 文字列型 の表現範囲が-12...
-
エクセルのMID関数は、C言語では?
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
char*を初期化したいのですが
-
CStringからchar*への型変換に...
-
C言語のintとcharの違いってな...
-
C言語にて構造体のメンバがNULL...
-
小数点入りの文字列をfloat型に...
-
strcat関数を自作したいです
-
C言語のプログラムについてです
-
const char* s1とただのchar s1...
-
DWORDとcharの変換
-
char型にint型の数値を代入する。
-
文字列の途中から途中までを抽出
-
new charとnew char[N]の違いは?
-
文字列内の数字削除
-
csvファイルをfscanfで読み込む...
-
fgetc( )の戻り値はなぜ整数??
-
char 文字列型 の表現範囲が-12...
-
fstream型オブジェクトを関数の...
-
エクセルのMID関数は、C言語では?
-
ポインタを使って回文かどうか...
-
ポインタ配列
おすすめ情報