#include <stdio.h>
main()
{
void original(int[], int *[], int *[], int *[]) ;
int i, origin[10];
int m2[10],m3[10],m5[10];
for(i = 0; i < 10; i++){
scanf("%d", &origin[i]);
}
original(origin, &m2[], &m3[], &m5[]);
printf("2の倍数:");
for(i = 0; i < 10; i++){
printf("%2d ,", m2[i]);
}
printf("\n");
printf("3の倍数:");
for(i = 0; i < 10; i++){
printf("%2d ,", m3[i]);
}
printf("\n");
printf("5の倍数:");
for(i = 0; i < 10; i++){
printf("%2d ,", m5[i]);
}
printf("\n");
return 0;
}
void original(int origin[], int *multiple_2[], int *multiple_3[], int *multiple_5[])
{
int i, m2 = 0, m3 = 0, m5 = 0;
for(i = 0; i < 10; i++){
if(origin[i] % 2 == 0){
*multiple_2[m2] = origin[i];
m2++;
}
if(origin[i] % 3 == 0){
*multiple_3[m3] = origin[i];
m3++;
}
if(origin[i] % 5 == 0){
*multiple_5[m5] = origin[i];
m5++;
}
}
}
上のプログラムをコンパイルし実行するとセグメントエラーがでてしまいます。どこがわるいんでしょうか・・・。上のプログラムは、外部入力から10個の数字をoriginに格納しそれをそれぞれ2の倍数、3の倍数、5の倍数をあらわすポインタにそれぞれを格納していき、最後にそれを表示するプログラムなんですが・・・。いまいち配列を持ったポインタを使い、なおかつ引数として使うやり方がうまくわからないからこんなエラーが出るような気もします・・・。どなたか初心者でもわかるようなアドバイスお願いします!
No.5
- 回答日時:
No.2の者です。
じっくりプログラムを読まずに回答してしてしまい、ポイントがズレてしまっていたみたいですね。すみません。
ところで、じっくりとあなたが書かれたプログラムを見ますと理解に苦しむところが1点あります。
(1)関数originalの引数。
第1引数のみ整数の配列(int[])で、後が整数の配列のポインタ(int *[])
となっている点。
どうして第1引数のみが、整数の配列なのでしょうか?全て整数の配列とした方が判りやすいしよいのでは?
あなたが書かれたプログラム中の矛盾点(BUG)は下記の点では?
(1)関数originalの第2仮引数以降の使用方法
第2仮引数以降は整数の配列のポインタとして宣言されているので、下記のようにするべきでは、
*multiple_2[m2] → multiple_2[m2]
あなたが書かれたプログラムでは、
*multiple_2[m2] →*(multiple_2[m2])となり、 配列multiple_2からm2番目の配列(配列multiple_2のm2番目の要素ではありません)の第1要素を示すことになり、これは多分不定になっているので不正なところに書き込みをすることとなりセグメントエラーがでてしまているのではないかと思われます。
回答ありがとうございます。
確かに、全て配列としたほうがわかりやすかったですね・・・。別のプログラミングを参考にしながらやっているとこのようになってしまいました。
二番目のご指摘につきましては、確かにポインタの扱い方がおかしいですね。言われて読み返してみると間違いに気付きました。どうもご指摘ありがとうございました。
No.4ベストアンサー
- 回答日時:
No.3の者です。
ポインタはアドレスなので、
int origin[10], *op=origin;
のところで、intが4バイトの場合、
例えば
origin[10]がメモリのアドレスFFA0~FFC8までにとられ、
opはポインタ変数で、origin(*origin[0])のアドレスFFA0が入ります。
(配列名originは、その配列の最初のポインタ)
>m2p = m2; m3p = m3, m5p = m5;
>↑の行は何故必要なんでしょうか。実際この行がなしでコンパイル
>したんですけど上手くいきません。どうしてでしょうか・・・。
ループの中の、
*m2p++ = *m3p++ = *m5p++ = 0;
の行で、0を入力していくために、それぞれのポインタをインクリメントしています。
(ループ終了時には、例えばm2pは、存在しないm2[10]のアドレスを示しています)
関数に渡す際には、m2[0]から埋めていってもらうために、
また、倍数を表示させる際は、またm2[0]から順に見ていく必要があるので、
一度m2pにm2を代入し、m2pをm2[0]のアドレスに戻さなくてはいけません。
なるほど!!大変よく分かりました!!ということは、
*m2p++ = *m3p++ = *m5p++ = 0; の行を
*(m2p++) = *(m3p++) = *(m5p++) = 0;としてforループを一回分減らせば、先頭のアドレスに変更が無いので
m2p = m2; m3p = m3, m5p = m5; は、記述しなくてもいいってことにもなりますよね?
二度も回答してくださってほんとうにありがとうございました!!
No.3
- 回答日時:
紛らわしくしてしまうかもしれないので申し訳ないのですが、
せっかくポインタの勉強をするのでしたら、配列の[]を使わないで組む練習をしてみるのもいいかと思います。
少し書き換えてみましたので(短時間なので汚いですが)、
もしよろしければ読み解いていただくと勉強になるかと思います。
int main() {
void original(int *, int *, int *, int *) ;
int i, origin[10], *op=origin;
int m2[10], m3[10], m5[10], *m2p=m2, *m3p=m3, *m5p=m5;
for(i=0; i<10;i++) {
scanf(" %d", op++);
*m2p++ = *m3p++ = *m5p++ = 0;
}
m2p = m2; m3p = m3, m5p = m5;
original(origin, m2, m3, m5);
printf("2の倍数:");
while (*m2p) { printf("%2d ,", *m2p++); }
printf("\n");
printf("3の倍数:");
while (*m3p) { printf("%2d ,", *m3p++); }
printf("\n");
printf("5の倍数:");
while (*m5p) { printf("%2d ,", *m5p++); }
printf("\n");
return 0;
}
void original(int *origin, int *multiple_2, int *multiple_3, int *multiple_5)
{
int i, m2 = 0, m3 = 0, m5 = 0;
for (i = 0; i < 10; i++, origin++) {
if (*origin % 2 == 0){
*multiple_2++ = *origin;
}
if(*origin % 3 == 0){
*multiple_3++ = *origin;
}
if(*origin % 5 == 0){
*multiple_5 = *origin;
}
}
}
返信ありがとうございます。
配列を使わずにやるとすごいコンパクトになりますね。大変勉強になりました。
すこしわからないとこがあるんですが
m2p = m2; m3p = m3, m5p = m5;
↑の行は何故必要なんでしょうか。実際この行がなしでコンパイルしたんですけど上手くいきません。どうしてでしょうか・・・。
No.2
- 回答日時:
配列名は確かポインタ定数のはずですので下記のところが
間違っているのでは?
誤
original(origin, &m2[], &m3[], &m5[]);
正
original(origin, m2[], m3[], m5[]);
後、うろ覚え(幾分忘却の彼方)なので、確認願いますが、
*と[]の優先順位はどうでしたか?
*multiple[] は、(*multiple)[] or *(multiple[])
のどちらでしたっけ?
(前者は配列のポインタ、後者は配列のポインタのポインタだったようナ!)
返信ありがとうございます。
正のほうに変えてみたところやはりエラーが出てしまいます。
優先順位は・・・おそらく[]のほうがさきだったような・・・
No.1
- 回答日時:
ポインタ以外は理解できているようですね。
「ポインタ」という言葉に惑わされず、単なる「アドレス(メモリ上の位置を示す数字)」ということを頭に常に置くと理解しやすいと思います。ある関数にアドレスを渡せば、その関数内ではそのアドレスに対して読み書きすることができます。そうするとそのアドレスに書き込まれた値はプログラム上のどの部分から読み出すことができる...という感じです。
TRACEはprintfに直してください。またscanfも消したのでご自分で入れてください。
#include <stdio.h>
void original(const int* origin,int* multiple_2,int* multiple_3,int* multiple_5)
{
int i, m2 = 0, m3 = 0, m5 = 0;
for(i = 0; i < 10; i++){
if(origin[i] % 2 == 0)
{
multiple_2[m2] = origin[i];
m2++;
}
if(origin[i] % 3 == 0){
multiple_3[m3] = origin[i];
m3++;
}
if(origin[i] % 5 == 0){
multiple_5[m5] = origin[i];
m5++;
}
}
}
main()
{
int i, origin[10];
int m2[10],m3[10],m5[10];
for(i = 0; i < 10; i++)
{
origin[i] = i;
m2[i] = 0;
m3[i] = 0;
m5[i] = 0;
}
original((int*)origin,(int*)m2,(int*)m3,(int*)m5);
printf("2の倍数:");
for(i = 0; i < 10; i++){
TRACE("%2d ,", m2[i]);
}
TRACE("\n");
printf("3の倍数:");
for(i = 0; i < 10; i++){
TRACE("%2d ,", m3[i]);
}
TRACE("\n");
printf("5の倍数:");
for(i = 0; i < 10; i++){
TRACE("%2d ,", m5[i]);
}
TRACE("\n");
return 0;
}
返信ありがとうございます。
とてもよくわかりました。
ただ一つこの行がいまいち理解できないのですが・・・
original((int*)origin,(int*)m2,(int*)m3,(int*)m5);
特に (int*)の部分がわからないのですが・・・。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# 10個の実数に対する降順ソート結果を出力するプログラムを作りたいのですが、以下のプログラムをどう直せ 1 2022/07/09 22:16
- C言語・C++・C# C言語プログラム変更 2 2022/12/21 15:03
- C言語・C++・C# プログラミング c言語 4 2023/03/07 01:05
- C言語・C++・C# C言語の課題が出たのですが自力でやっても分かりませんでした。 要素数がnであるint型の配列v2の並 3 2022/11/19 17:41
- C言語・C++・C# C言語 プログラミング 4 2022/05/22 11:53
- C言語・C++・C# c言語の問題です 3 2023/01/10 16:15
- C言語・C++・C# c言語 プログラムのエラー 1 2023/02/11 20:31
- C言語・C++・C# C言語のエラーについて 2 2022/07/11 13:56
- C言語・C++・C# C 言語の Gauss Jordan 法について 2 2022/12/28 11:16
- C言語・C++・C# c言語配列の結合についてです。 なぜうまくいかないのでしょうか。 #include <stdio.h 4 2022/05/30 22:42
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
C言語
-
#define _CRT_SECURE_NO_WARNIN...
-
C言語 エラーの原因がわからな...
-
比較回数と交換回数表示について
-
複数桁10進数の*桁目だけを抽出...
-
nCmの関数
-
構造体の勉強中です 合計点の高...
-
C言語 配列と関数の練習問題
-
[C言語] 関数を利用する計算
-
実数の整数部,小数部の取得
-
C言語での引数の省略方法
-
数字列を3桁ごとにカンマで区切...
-
アスタリスクでダイヤ型を作る
-
覆面算のプログラムが分かりません
-
C言語の基礎 . 2乗値の差につ...
-
c言語
-
プログラミング
-
【C++】関数ポインタの使い方
-
毎回違う乱数を生成するにはど...
-
if と配列の組み合わせ
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
C言語での引数の省略方法
-
#define _CRT_SECURE_NO_WARNIN...
-
「指定されたキャストは有効で...
-
C言語 配列と関数の練習問題
-
複数桁10進数の*桁目だけを抽出...
-
(int *)の意味
-
if と配列の組み合わせ
-
ラップ関数とはどんなものですか?
-
卒業研究でよく分からないとこ...
-
【C++】関数ポインタの使い方
-
c言語
-
足して100になるような乱数のア...
-
C言語初心者です、、、お助けく...
-
数字列を3桁ごとにカンマで区切...
-
C言語 エラーの原因がわからな...
-
実数の整数部,小数部の取得
-
課題でつまってます・・・
-
商と剰余を同時に求める(C言語)
-
C言語の配列をC++のvectorに高...
-
std::set<int> で、ある値が何...
おすすめ情報