質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

ポインタ

ポインタはアドレスを用いてメモリに格納された値を"参照する"変数です。

Q&A

解決済

3回答

2194閲覧

ポインタのポインタについて

K.M.PEANUTS

総合スコア40

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

ポインタ

ポインタはアドレスを用いてメモリに格納された値を"参照する"変数です。

0グッド

0クリップ

投稿2021/04/16 11:24

イメージ説明
イメージ説明

上記写真のような問題に取り組んでいるのですが、ネットでどれだけ調べてもここでのポインタのポインタについての理解ができなかったので質問させていただきます。下のコードが僕の書いたものなのですが、output_strings_reverse関数の引数にどうしてポインタのポインタを使うのかわかりません。素人の自分からすると単にポインタstr_pを受け渡して*array_pを受け取ればいい気がするのですが、それでコードを書いてもうまくいかなかったのでだめなのでしょう。
質問は、ここでポインタのポインタを使わなければならない理由と、output_strings_reverse関数をどのようにすれば良いのかも教えてくれたら幸いです。

c

1#include <stdio.h> 2#include <stdlib.h> 3#include <string.h> 4 5#define NUM_STRING 20 //文字列の最大個数 6#define MAX_LEN 100 //文字配列のサイズ(入力文字列の最大長さ+1) 7 8//文字列の画面出力用関数(逆順) 9void output_strings_reverse(char **array_p, int m) 10{ 11 int i; 12 printf("%d\n", m); 13 for(i=m-1; m>=0; m--) { 14 printf("%s\n", *array_p[i]); 15 } 16} 17 18 19int main( void ) 20{ 21 int i; 22 int n; //文字列の個数 23 char data[MAX_LEN]={}; //入力用文字列 24 char *str_p[NUM_STRING]; //文字列へのポインタを格納するポインタ配列 25 26 //i〜iiiの処理 27 for(i=0; i<20; i++) { 28 //iの処理 29 printf("Input strings -> "); 30 scanf("%s", data); 31 printf("%s\n", data); 32 if(strcmp(data, "end") == 0) break; 33 //iiの処理 34 *str_p[i] = (char *)malloc(strlen(data) + 1); 35 strcpy(*str_p[i], data); 36 37 } 38 39 40 //文字列の画面出力 41 output_strings_reverse(&str_p, i); 42 43 //動的確保した領域の開放 44 free(*str_p); 45 46 47 return 0; 48}

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

パッと見て、、

*str_p[i] = (char *)malloc(strlen(data) + 1);
strcpy(*str_p[i], data);

ここ、

C

1 str_p[i] = (char *)malloc(strlen(data) + 1); 2 strcpy(str_p[i], data);

じゃないでしょうか。
最近のコンパイラだと、型の不一致でエラー(警告かも)がでませんか?

おっと、

free(*str_p);

こちらも
for(i=0; i<20; i++) free(str_p[i]);
かな。

投稿2021/04/16 11:42

pepperleaf

総合スコア6385

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

pepperleaf

2021/04/16 11:51

ちょっと細かい説明を書く余裕がなくて申し訳ない、、です。 ただ、最近のコンパイラだと、この辺、結構、チェックが入って警告やら、エラーがでると思います。まず、それを丁寧にみる事を勧めます。
K.M.PEANUTS

2021/04/16 12:55

メモリの動的確保についてはミスってました! 開放についてはfor文使うの知らなかったので教えていただきありがとうございます!
guest

0

ベストアンサー

次のコードは理解できますか?

C

1#include <stdio.h> 2 3void output_int_reverse(int *p, int n) 4{ 5 for (int i = n - 1; i >= 0; i--) 6 printf("%d\n", p[i]); 7} 8 9int main(void) 10{ 11 int a[3] = { 11, 22, 33 }; 12 output_int_reverse(a, 3); 13}

int を char * に変えてみましょう。

C

1#include <stdio.h> 2 3void output_str_reverse(char **p, int n) 4{ 5 for (int i = n - 1; i >= 0; i--) 6 printf("%s\n", p[i]); 7} 8 9int main(void) 10{ 11 char *a[3] = { "abc", "def", "ghi" }; 12 output_str_reverse(a, 3); 13}

関数が、int の配列を引数で受け取る時、引数は int へのポインタです。
関数が、char * の配列を引数で受け取る時、引数は char * へのポインタです。
これが、ポインタのポインタを使わなければならない理由です。

投稿2021/04/16 15:53

編集2021/04/16 15:57
kazuma-s

総合スコア8224

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

K.M.PEANUTS

2021/04/18 01:52

わかりやすいコードで説明いただきありがとうございます!このコードのおかげでやっと点と点が線で結ばれた気がします!
guest

0

c

1prog.c: In function 'output_strings_reverse': 2prog.c:14:14: warning: format '%s' expects argument of type 'char *', but argument 2 has type 'int' [-Wformat=] 3 14 | printf("%s\n", *array_p[i]); 4 | ~^ ~~~~~~~~~~~ 5 | | | 6 | | int 7 | char * 8 | %d 9prog.c: In function 'main': 10prog.c:34:13: warning: assignment to 'char' from 'char *' makes integer from pointer without a cast [-Wint-conversion] 11 34 | *str_p[i] = (char *)malloc(strlen(data) + 1); 12 | ^ 13prog.c:35:10: warning: passing argument 1 of 'strcpy' makes pointer from integer without a cast [-Wint-conversion] 14 35 | strcpy(*str_p[i], data); 15 | ^~~~~~~~~ 16 | | 17 | char 18In file included from prog.c:3: 19/usr/include/string.h:125:39: note: expected 'char * restrict' but argument is of type 'char' 20 125 | extern char *strcpy (char *__restrict __dest, const char *__restrict __src) 21 | ~~~~~~~~~~~~~~~~~^~~~~~ 22prog.c:41:26: warning: passing argument 1 of 'output_strings_reverse' from incompatible pointer type [-Wincompatible-pointer-types] 23 41 | output_strings_reverse(&str_p, i); 24 | ^~~~~~ 25 | | 26 | char * (*)[20] 27prog.c:9:36: note: expected 'char **' but argument is of type 'char * (*)[20]' 28 9 | void output_strings_reverse(char **array_p, int m) 29 | ~~~~~~~^~~~~~~ 30prog.c:22:7: warning: unused variable 'n' [-Wunused-variable] 31 22 | int n; //文字列の個数 32 | ^

https://wandbox.org/permlink/KvPsd3OlqsBig1Lc

<source>(14): warning C4477: 'printf' : format string '%s' requires an argument of type 'char *', but variadic argument 1 has type 'int' <source>(23): error C2059: syntax error: '}' <source>(34): warning C4047: '=': 'char' differs in levels of indirection from 'char *' <source>(35): warning C4047: 'function': 'char *' differs in levels of indirection from 'char' <source>(35): warning C4024: 'strcpy': different types for formal and actual parameter 1 <source>(41): warning C4047: 'function': 'char **' differs in levels of indirection from 'char *(*)[20]' <source>(41): warning C4024: 'output_strings_reverse': different types for formal and actual parameter 1

https://godbolt.org/z/5hqa7nofa

はい。コンパイラの警告は読みましょう。

c

1char data[MAX_LEN]={};

これはC++の記法ですね、Cのaggregate初期化は最初の要素に対する初期値指定を省略できません。

ref: 本の虫: aggregateと初期化リストの不思議


本題については簡単です。文字列が格納された領域を指し示すポインタの型はchar*です。このポインタを格納する領域へのポインタは必然的にchar**ですね。このポインタと個数がoutput_strings_reverseではほしいわけです。

投稿2021/04/16 14:59

yumetodo

総合スコア5852

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問