仮引数の使い方

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
stream

仮引数の使い方

#1

投稿記事 by stream » 13年前

こんにちは、streamです。今、私は仮引数について勉強しているのですが、ググっても思うようなサイトが見つかりません。仮引数がどんなのかは少しはわかるのですが、使い方がいまいち微妙です。シューティングゲームでは、仮引数は使うと思うのですが1つや2つだけじゃないですよね。例えば、自機の座標や敵の座標、弾の速さなど複数あります。その時に、仮引数を書いた関数のを呼び出すときはもちろんその数だけ仮引数は書くのですか?
少しつまずいてしまいました。仮引数を理解できるようになったら前のトピックで紹介した本がもっと有効的に使えると思いますので返信お願いします!

アバター
みけCAT
記事: 6734
登録日時: 15年前
住所: 千葉県
連絡を取る:

Re: 仮引数の使い方

#2

投稿記事 by みけCAT » 13年前

stream さんが書きました:その時に、仮引数を書いた関数のを呼び出すときはもちろんその数だけ仮引数は書くのですか?
関数を呼び出すときは、仮引数ではなく実引数を書きます。
http://www.cc.kyoto-su.ac.jp/~yamada/ap ... ument.html

追記
「前のトピック」とは、具体的にどのトピックでしょうか?
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: 仮引数の使い方

#3

投稿記事 by softya(ソフト屋) » 13年前

ここは、仮引数と実引数をまとめて引数の使い方の質問と言った所でしょうか?

関数でデータを処理するためには引数で受け渡して戻り値で返すのが原則です。
引数のメリットは違う構造体のデータでも実引数にメンバ変数を書くことで仮引数では同等に扱えることですね。
それと引数に書くことで、どの様なデータを受け取って処理する関数か明確になります。

ただ、沢山の引数の関数があった場合そのプログラムは大変読みづらくなりますので、ほどほどのさじ加減が要求されます。
もし引数が多すぎた場合は構造体や構造体ポインタで受け渡すのが一般的でしょう。
構造体や構造体ポインタで受け渡した場合は、どの要素が変更されるのか明確に分かりづらくなるので関数名や関数の機能分けでわかりやすく工夫する必要が出てきます。
追記
「前のトピック」とは、具体的にどのトピックでしょうか?
このトピックでしょうか?
「参考書で・・・ • C言語交流フォーラム ~ mixC++ ~」
http://dixq.net/forum/viewtopic.php?f=3&t=10205
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: 仮引数の使い方

#4

投稿記事 by softya(ソフト屋) » 13年前

前回の話と今回の話しでstreamさんが考える引数と言うものがどんなものなのか少し不安になって来ました。
簡単なプログラムで良いのでstreamさんが考える引数を使ったプログラムを書いてみてもらえませんか?
引数は2~3個で戻り値もあるのが望ましいです。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

stream

Re: 仮引数の使い方

#5

投稿記事 by stream » 13年前

返信ありがとうございます。前のトピックというのはviewtopic.php?f=3&t=10205であっています。あと、書くのを忘れていたのですが
引数の中でも知りたいのはC++の参照という方の仮引数です。できれば、CとC++を比べての仮引数の説明があるとありがたいです。
簡単な引数のプログラムを書いてくださいとあるんですがこんな感じで大丈夫ですか??

コード:


#include <stdio.h>

int z;
int goukei(int x,int y);

int main(void){
	int a,b;
	scanf("%d",&a);
	scanf("%d",&b);
	goukei(a,b);
	printf("合計は%dです\n",z);

}

int goukei(int x,int y){
	z = x + y;

	return z;
}
	

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: 仮引数の使い方

#6

投稿記事 by softya(ソフト屋) » 13年前

stream さんが書きました: 簡単な引数のプログラムを書いてくださいとあるんですがこんな感じで大丈夫ですか??

コード:

#include <stdio.h>

int z;
int goukei(int x,int y);

int main(void){
	int a,b;
	scanf("%d",&a);
	scanf("%d",&b);
	goukei(a,b);
	printf("合計は%dです\n",z);

}

int goukei(int x,int y){
	z = x + y;

	return z;
}
	
これはコンパイルは通りますが、よくない書き方です。
zをローカル変数にしなかったのは何故でしょうか?
あとzを戻り値として使っていません。
なので、私の問題の答えとしては間違っています。
[補足]考察と修正をお願いします。
stream さんが書きました:返信ありがとうございます。前のトピックというのはviewtopic.php?f=3&t=10205であっています。あと、書くのを忘れていたのですが
引数の中でも知りたいのはC++の参照という方の仮引数です。できれば、CとC++を比べての仮引数の説明があるとありがたいです。
これを説明するには仮引数の特性を理解していないと行けません。
streamさんのコードを元にわざと間違ったサンプルを書きましたので問題点を指摘してみて下さい。

コード:

#include <stdio.h>
 
void goukei(int in_x,int in_y,int out_z);
 
int main(void){
    int a,b,z;
    scanf("%d",&a);
    scanf("%d",&b);
    goukei(a,b,z);
    printf("合計は%dです\n",z);
 
}

void goukei(int in_x,int in_y,int out_z) {
    out_z = in_x + in_y;
}
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

stream

Re: 仮引数の使い方

#7

投稿記事 by stream » 13年前

コード:

#include <stdio.h>
 
void goukei(int in_x,int in_y);
 
int main(void){
    int a,b;
    scanf("%d",&a);
    scanf("%d",&b);
    goukei(a,b);
   
 
}
 
void goukei(int in_x,int in_y) {
	int out_z;
    out_z = in_x + in_y;
	printf("合計は%dです\n",out_z);
}

このプログラムはどうですか?
自分がみたら自分がさっきか書いたプログラムとあまり変わらない気がします。
仮引数では
void goukei(int in_x,int in_y) {
int out_z;
out_z = in_x + in_y;
printf("合計は%dです\n",out_z);
}
の部分で書いた仮引数で
goukei(a,b);
の部分で本来は
goukei(20,30);
と実引数で書きたかったのですがscanf関数でこちらから入力した値を渡したいのでgoukei(a,b)と書きました。
あと、goukei関数のなかでprintf関数を使用するようにしました。
今の私ではすぐに答えが見つかりませんでした。
返信お願いします。

box
記事: 2002
登録日時: 15年前

Re: 仮引数の使い方

#8

投稿記事 by box » 13年前

そのコードを改造して、main関数の中で合計値を出力するようにしてみてください。
goukei関数は、引数で受け取った2個の値の合計を呼び出し元(今回はmain関数)に返すだけ、ということです。
そうすると、goukei関数の戻り値の型がvoidではまずくなります。さて、どうすればいいでしょうか。
バグのないプログラムはない。
プログラムは思ったとおりには動かない。書いたとおりに動く。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: 仮引数の使い方

#9

投稿記事 by softya(ソフト屋) » 13年前

前半のstream さんの書いたプログラムの方を問題(1)、後半の私が書いたプログラムを問題(2)と呼ぶことにしますが、いま出てきたのは新しいプログラムで問題点を無視して自分の知識の中で書いてしまっています。これでは何時までも仮引数や戻り値がわからないのでもう一度整理してみましょう。

問題(1)は、問題テーマとして
・引数を2~3個使う。
・戻り値で結果を返す。
で書かれた回答に対しては
(a)zをローカル変数にしなかったのは何故でしょうか?
(b)あとzを戻り値として使っていません。修正をお願いします。
と指摘しました。
まだ、ここの回答を頂いていません。

問題(2)の質問はシンプルに
(c)・問題点を指摘してみて下さい。
です。これの回答をお願いします。

[補足] 答えが分からないなら分からないという答えもありです。ただ、どこが分からないのか出来るだけ具体的に書いてみて下さい。

問題(1)の(b)に関しては、ただ戻り値を使うプログラムを書いてもらったほうが良いかも知れません。
と言うことで問題(3)ですが、
scanfして数値をひとつ返す関数
int input(void);
を使ってプログラムを組んでみて下さい。
このプログラムでグローバル変数は使ってはいけません。
input関数は少なくとも2回呼び出して下さい。

[追記]
聞き忘れてましたが、今参考にしているC言語やC++の書籍、サイトを全部書きだしてみてもらえますか?
それらに問題があるのかも知れません。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

stream

Re: 仮引数の使い方

#10

投稿記事 by stream » 13年前

返信ありがとうございます。
問題(1)(a)zをローカル変数にしなかったのは何故でしょうか?
それはローカル変数にするとワー二ングが出てしまうからです。

     (b)あとzを戻り値として使っていません。修正をお願いします。
        よくわかりません。自分は返り値の使い方が分かってないのかもしれません。

問題(2)(c)問題点を指摘してみて下さい。
まず、仮引数を使っているからmain関数のなかで実引数を使うことですかね。
       それから、voidでは値が返せないのでint型に変えることですかね。

問題(3)scanfして数値をひとつ返す関数int input(void);を使ってプログラムを組んでみて下さい。
     今度は素直に組んでみました。

コード:

 
#include<stdio.h>

int input();

int main(void){
	int x = input();
	int y = input();
	printf("合計は%d\n",x+y);


}

int input(){
	int a;
	scanf("%d",&a);
	return a;
}
       
[追記]
http://gihyo.jp/book/2010/978-4-7741-4232-6
http://www.rutles.net/books/217.html
本を読んで理解はできてもいざプログラムを作ろうとなると思うようにできません。
回答の返信をしていなくてすみません。
返信お願いします。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: 仮引数の使い方

#11

投稿記事 by softya(ソフト屋) » 13年前

問題(3)はOKです。これがOKで問題(1)が解けない理由が良くわかりません。
見たところお持ちのC言語の入門書「かんたん C言語」はポインタの説明もあるみたいですね。
この本をちゃんと理解すればC++は別としてC言語の基本は、ほぼ大丈夫になると思います。
と言うことで基本の理解のために問題(1)と問題(2)を続けます。
stream さんが書きました: 問題(1)(a)zをローカル変数にしなかったのは何故でしょうか?
それはローカル変数にするとワー二ングが出てしまうからです。
(問題1-A)どんなワーニングでしょうか?
プログラムで対処療法する事態に落った場合はだいたいトンデモないミスをしていることが多いです。
stream さんが書きました:     (b)あとzを戻り値として使っていません。修正をお願いします。
        よくわかりません。自分は返り値の使い方が分かってないのかもしれません。
(問題1-B) 問題(3)が組めるなら問題(1)も出来るはずです。
input関数と同じ返し方でzを返せませんか?
stream さんが書きました:問題(2)(c)問題点を指摘してみて下さい。
まず、仮引数を使っているからmain関数のなかで実引数を使うことですかね。
       それから、voidでは値が返せないのでint型に変えることですかね。
(問題2-C1)仮引数を使っているとどんな問題があるのでしょうか?
(問題2-C2)実引数を使うと何が改善しますか?

>voidでは値が返せないのでint型に変えることですかね
(問題2-C3)戻り値がないと、なぜ返せないのでしょうか?
(問題2-C4)C言語の値渡しと参照渡しと言うのが本に載っていたと思います。
問題2をC言語の参照渡しで、ちゃんと動くように書き換えてみて下さい。戻り値は使いません。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

stream

Re: 仮引数の使い方

#12

投稿記事 by stream » 13年前

返信ありがとうございます。
(問題1-A)どんなワーニングでしょうか?
       「warning C4700: 初期化されていないローカル変数 'z' が使用されます」と表示されます。ちなみに下のプログラムは一番最初のプログラムをローカル変数にしたものです。

コード:

 
#include <stdio.h>
 
int goukei(int x,int y);
 
int main(void){
    int a,b,z;
    scanf("%d",&a);
    scanf("%d",&b);
    goukei(a,b);
    printf("合計は%dです\n",z);
 
}
 
int goukei(int x,int y){
	int z;
    z = x + y;
 
    return z;
}
(問題1-B) 問題(3)が組めるなら問題(1)も出来るはずです。
       input関数と同じ返し方でzを返せませんか?
これはどうですか?input関数を2回以上使っていませんが・・・・

コード:

#include<stdio.h>
 
int input();
 
int main(void){

	int z = input();
    printf("合計は%d\n",z);
 
}
 
int input(){
    int x,y,z;

    scanf("%d",&x);
	scanf("%d",&y);
	z = x+y;

    return z;
}
(問題2-C1)仮引数を使っているとどんな問題があるのでしょうか?
(問題2-C2)実引数を使うと何が改善しますか?
この2問は分かりませんでした。
(問題2-C3)戻り値がないと、なぜ返せないのでしょうか?
       あー、思えば関数の中で処理をしてしまえば返せますよね。
(問題2-C4)C言語の値渡しと参照渡しと言うのが本に載っていたと思います。
       問題2をC言語の参照渡しで、ちゃんと動くように書き換えてみて下さい。戻り値は使いません。
       下のようになりました。

コード:

#include<stdio.h>


void goukei(int *px,int *py){

    *px = *px + *py;
} 


int main(void){
	int a,b;
	scanf("%d",&a);
	scanf("%d",&b);
	goukei(&a,&b);
	printf("合計は%d\n",a);

}


	
ポインタを使ったときの場合のプロトタイプ宣言の書き方が分かりません。
返信お願いします

box
記事: 2002
登録日時: 15年前

Re: 仮引数の使い方

#13

投稿記事 by box » 13年前

stream さんが書きました: ポインタを使ったときの場合のプロトタイプ宣言の書き方が分かりません。
ポインターのことを意識しすぎではないでしょうか。
関数の実体 { ~ }
の代わりに、最後にセミコロンを付ければよい、という点において、
ポインター変数が引数であるかどうかは「全く」関係ありません。
バグのないプログラムはない。
プログラムは思ったとおりには動かない。書いたとおりに動く。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: 仮引数の使い方

#14

投稿記事 by softya(ソフト屋) » 13年前

warning C4700: 初期化されていないローカル変数 'z' が使用されます」と表示されます。ちなみに下のプログラムは一番最初のプログラムをローカル変数にしたものです。
なぜ、このエラーが出るか分かりますか?
すごく重要なポイントなのですが。
[ヒント] 変数のスコープと寿命

(問題1-B) に関しては(問題1-A)のgoukeiまま、input()の様に値を戻すだけです。
input()にしてしまっては原型と違いすぎるので入力と出力はmainで計算はgoukeiでの形を守って下さい。
softya(ソフト屋) さんが書きました:
stream さんが書きました:まず、仮引数を使っているからmain関数のなかで実引数を使うことですかね。
(問題2-C1)仮引数を使っているとどんな問題があるのでしょうか?
(問題2-C2)実引数を使うと何が改善しますか?
この2問は分かりませんでした。
ご自分で回答された事に対する質問のつもりだったのですが「まず、仮引数を使っているからmain関数のなかで実引数を使うことですかね」について解説してもらってよいでしょうか?
stream さんが書きました:ポインタを使ったときの場合のプロトタイプ宣言の書き方が分かりません。
関数の定義とプロトタイプ宣言は同じに書けば良いです。
で書き方の問題ですが、1つの変数を違う2つの意味に使うのはバグの元になります。pxの指す先の変数に本来zである数値を入れるのは止めて下さい。
void goukei(int *px,int *py){
あとxとyは変更しないので参照渡しする意味がありません。答えを返すzを参照渡ししてください。
私の書いた
void goukei(int in_x,int in_y,int out_z)
を参照渡しに書き換えてもらうだけで良いです。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

stream

Re: 仮引数の使い方

#15

投稿記事 by stream » 13年前

返信ありがとうございます。
なぜ、このエラーが出るか分かりますか?
すごく重要なポイントなのですが。
[ヒント] 変数のスコープと寿命
これはワー二ングにも出ていた通りにローカル変数が初期化されていないのに使っているからです。
だから下のプログラムではmain関数でint z;と書いておいただけでzの中身に何も代入されていないのにprintf関数で使われているからです。と今分かりました。

コード:

  
#include <stdio.h>
 
int goukei(int x,int y);
 
int main(void){
    int a,b,z;
    scanf("%d",&a);
    scanf("%d",&b);
    goukei(a,b);
    printf("合計は%dです\n",z);
 
}
 
int goukei(int x,int y){
    int z;
    z = x + y;
 
    return z;
}
(問題1-B) に関しては(問題1-A)のgoukeiまま、input()の様に値を戻すだけです。
input()にしてしまっては原型と違いすぎるので入力と出力はmainで計算はgoukeiでの形を守って下さい。
下のプログラムではどうでしょうか?

コード:

 
#include <stdio.h>
 
int goukei(int x,int y);
 
int main(void){
    int a,b;
    scanf("%d",&a);
    scanf("%d",&b);
    int c = goukei(a,b);
    printf("合計は%dです\n",c);
 
}
 
int goukei(int x,int y){
    int z;
    z = x + y;
 
    return z;
}
ご自分で回答された事に対する質問のつもりだったのですが「まず、仮引数を使っているからmain関数のなかで実引数を使うことですかね」について解説してもらってよいでしょうか?
このことについてはすみません、実引数というものは数字だけで文字ではいけないと知ったかぶりをしていました。
void goukei(int in_x,int in_y,int out_z)
を参照渡しに書き換えてもらうだけで良いです。
このプログラムでよいのでしょうか?

コード:

#include <stdio.h>
 
void goukei(int *pin_x,int *pin_y,int *pout_z);
 
int main(void){
    int a,b,c;
    scanf("%d",&a);
    scanf("%d",&b);
    goukei(&a,&b,&c);
    printf("合計は%dです\n",c);
 
}
 
void goukei(int *pin_x,int *pin_y,int *pout_z) {
    *pout_z = *pin_x + *pin_y;
}
いろいろごちゃごちゃしてきてすみません。
返信お願いします。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: 仮引数の使い方

#16

投稿記事 by softya(ソフト屋) » 13年前

ローカル変数と戻り値の件はOKです。分かって来ましたね。
で、参照渡しの件ですが不必要なものを参照渡しにしないでください。
softya(ソフト屋) さんが書きました:あとxとyは変更しないので参照渡しする意味がありません。答えを返すzを参照渡ししてください。
と書いておいたはずですが。

さて、これが整理できたらいよいよC++の参照渡しです。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

stream

Re: 仮引数の使い方

#17

投稿記事 by stream » 13年前

参照渡しの件ですが不必要なものを参照渡しにしないでください。
確かにgoukei()で&aと&bは不必要とは感じるのですが
goukei関数で*pin_xには&aを
         *pin_yには&bを
         *pout_zには&cを対応させたいのですがそれがうまくできません。
それから一応確認で答えを返すzを参照にするというのは void goukei(int *pout_z)と表すことですよね?
あとxとyは何が変更しないのでしょうか?値ですか?

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: 仮引数の使い方

#18

投稿記事 by softya(ソフト屋) » 13年前

コード:

#include <stdio.h>
 
void goukei(int *pin_x,int *pin_y,int *pout_z);
 
int main(void){
    int a,b,c;
    scanf("%d",&a);
    scanf("%d",&b);
    goukei(&a,&b,&c);
    printf("合計は%dです\n",c);
 
}
 
void goukei(int *pin_x,int *pin_y,int *pout_z) {
    *pout_z = *pin_x + *pin_y;
}
stream さんが書きました:
参照渡しの件ですが不必要なものを参照渡しにしないでください。
確かにgoukei()で&aと&bは不必要とは感じるのですが
goukei関数で*pin_xには&aを
         *pin_yには&bを
         *pout_zには&cを対応させたいのですがそれがうまくできません。
それから一応確認で答えを返すzを参照にするというのは void goukei(int *pout_z)と表すことですよね?
あとxとyは何が変更しないのでしょうか?値ですか?
C言語でポインタを渡しているのは参照渡しにするためで、それは変数の持つ値を書き換えるために必要な行為です。
例示されているプログラムですが、*pin_xを右辺にかけば変数のaの値を取り出せて、*pin_xを左辺に書けば変数aに代入出来ます。
ポインタを使うことで擬似的に*pin_xはaの仮の名前として機能すると言うことです。
これが参照渡しなのですが、x,yは計算の右辺にしか使わないので書き換えられる必要はありませんので値渡しで十分です。zは値を返すので参照渡しにする必要があります。

>goukei関数で*pin_xには&aを
>         *pin_yには&bを
>         *pout_zには&cを対応させたいのですがそれがうまくできません。

出来ているようですが?

>zを参照にするというのは void goukei(int *pout_z)と表すことですよね?

これだとxとyがありません。

>あとxとyは何が変更しないのでしょうか?値ですか?

値を変更しないと言うことです。
何か良く分からずプログラムを書き換えている感がしてきました。
これが終わったら、、もう一問出してみますね。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

stream

Re: 仮引数の使い方

#19

投稿記事 by stream » 13年前

返信ありがとうございます。このプログラムはどうですか?参照渡しをするためには*がいるわけだから必要ないものはとりました。正直*があるのとないものを比べられるとは思ってなかったので・・・思ったらそうですよねvoid goukei()でかっこの中身は仮引数でそれに*をつけて参照渡しにするかしないかの問題ですよね。自分のバカさ加減にちょっと落ち込みます・・・
返信お願いします。

コード:

#include <stdio.h>
 
void goukei(int pin_x,int pin_y,int *pout_z);
 
int main(void){
    int a,b,c;
    scanf("%d",&a);
    scanf("%d",&b);
    goukei(a,b,&c);
    printf("合計は%dです\n",c);
 
}
 
void goukei(int pin_x,int pin_y,int *pout_z) {
    *pout_z = pin_x + pin_y;
}

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: 仮引数の使い方

#20

投稿記事 by softya(ソフト屋) » 13年前

どれを参照渡しする・しないにする拘るのはバグの元だからです。

[余談]
書き換えられて困るものは書き換え不能にするのは大事なバグを予防する手段で、そのためにわざわざconst修飾子と言うものがあるぐらいです。
たとえばgoukeiでは次のように使えます。

コード:

#include <stdio.h>
 
void goukei(int const pin_x,int const pin_y,int * const pout_z);
 
int main(void){
    int a,b,c;
    scanf("%d",&a);
    scanf("%d",&b);
    goukei(a,b,&c);
    printf("合計は%dです\n",c);
 
}
 
void goukei(int const pin_x,int const pin_y,int * const pout_z) {
    *pout_z = pin_x + pin_y;	//問題なし
    pout_z++;	//エラーになる。
    pin_x++;	//エラーになる。
    pin_y++;	//エラーになる。
}
こうするとpin_xとpin_yの変更、pout_zのポインタ値の変更を文法レベルで禁止できます。
ただし、ポインタ参照先の値は変更できるので *pout_zへの代入は可能です。
この位自分自身がうっかり間違うと言うことを前提に書いたほうがバグが予防できると言うわけですし実際に役立ちます。

[新問題]
さて、もう一つ参照渡しの問題を出しておきます。
参照渡しで、関数を2段階組み合わせてみてください。
main()→func1()→func2()
func2()で書き換えてmainに戻して表示します。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

stream

Re: 仮引数の使い方

#21

投稿記事 by stream » 13年前

[新問題]
さて、もう一つ参照渡しの問題を出しておきます。
参照渡しで、関数を2段階組み合わせてみてください。
main()→func1()→func2()
func2()で書き換えてmainに戻して表示します。
この問題も足し算を求める問題でいいんですか??

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: 仮引数の使い方

#22

投稿記事 by softya(ソフト屋) » 13年前

stream さんが書きました:
[新問題]
さて、もう一つ参照渡しの問題を出しておきます。
参照渡しで、関数を2段階組み合わせてみてください。
main()→func1()→func2()
func2()で書き換えてmainに戻して表示します。
この問題も足し算を求める問題でいいんですか??
計算はなんでも良いので、mainから渡した値でfunc1経由のfunc2で計算させて下さい。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

stream

Re: 仮引数の使い方

#23

投稿記事 by stream » 13年前

すいません、func1経由というところがわかりません。
ヒントが欲しいです!!
例えばfunc1の関数の中身とか!
それから、入出力はmain関数ですか?

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: 仮引数の使い方

#24

投稿記事 by softya(ソフト屋) » 13年前

stream さんが書きました:すいません、func1経由というところがわかりません。
ヒントが欲しいです!!
例えばfunc1の関数の中身とか!
それから、入出力はmain関数ですか?
条件を詳しく書くと
・入出力(scanfやprintf)はmain関数です。
・mainはfunc1を呼び出します。
・func1はfunc2を呼び出します。つまりfunc1は中継を行います。関数内で別の関数を呼び出すということでプログラムではよく行われるパターンです。
・戻り値は使いません。func1とfunc2の戻り値はvoidです。
・計算はfunc1でもfunc2でもどちらでも構いませんが、mainでprintfする参照渡しの変数に代入するのはfunc2に限定します。
・グローバル変数(関数外の変数)は使用禁止です。
これはC言語の基礎的な応用力の練習も兼ねているのでfunc1の関数の中身は書きません。
自分の力で出来るだけのものを書いて下さい。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

stream

Re: 仮引数の使い方

#25

投稿記事 by stream » 13年前

すいません、中学校の課題やらで追われ返信が遅れました。
このプログラムはどうでしょうか?

コード:

#include <stdio.h>

void func1(int e,int r,int *t);
void func2(int x,int y,int *p_z);

int main(void){

	int a,b,c;
	scanf("%d",&a);
	scanf("%d",&b);
	func1(a,b,&c);
	printf("%d\n",c);
	


}

void func2(int x,int y,int *p_z){
	*p_z = x + y;

}


void func1(int e,int r,int *t){

	func2(e,r,t);

}



返信お願いします!

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: 仮引数の使い方

#26

投稿記事 by softya(ソフト屋) » 13年前

OKですね。
では、いよいよC++における参照です。
実は、C言語のポインタによる参照よりもシンプル書くことができます。

コード:

#include <stdio.h>
 
void goukei(int in_x,int in_y,int &out_z);

int main(void){
    int a,b,c;
    scanf("%d",&a);
    scanf("%d",&b);
    goukei(a,b,c);
    printf("合計は%dです\n",c);
 
}
 
void goukei(int in_x,int in_y,int &out_z) {
    out_z = in_x + in_y;
}
goukei(a,b,c);で関数が呼び出され時mainのc変数とgoukeiのout_zは同じメモリを使う変数だとして処理されます。
要はポインタが見えないだけで同じ事をやっているんですが、ポインタとしての機能は無いのでより安全になります。

さて、これを踏まえて練習問題です。
問題(1) main()→func1()→func2()の問題をC++の参照を使って書きましょう。
問題(2) main()→func1()→func2()のひねった応用問題。
入出力はmainで、計算はfunc2()で行いfunc2()では計算結果をC++の参照でfunc1()に戻すこととし、func1()からは戻り値でmainに値を戻すこと。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

stream

Re: 仮引数の使い方

#27

投稿記事 by stream » 13年前

どうでしょうか?
問題(1)

コード:


#include <stdio.h>
 
void func1(int e,int r,int &t);
void func2(int x,int y,int &p_z);
 
int main(void){
 
    int a,b,c;
    scanf("%d",&a);
    scanf("%d",&b);
    func1(a,b,c);
    printf("%d\n",c);
    
 
 
}
 
void func2(int x,int y,int &p_z){
    p_z = x + y;
 
}
 
 
void func1(int e,int r,int &t){
 
    func2(e,r,t);
 
}
 
 
問題(2)

コード:


#include <stdio.h>
 
int func1(int e,int r,int &t);
void func2(int x,int y,int &p_z);
 
int main(void){
 
    int a,b,c;
    scanf("%d",&a);
    scanf("%d",&b);
    int d = func1(a,b,c);
    printf("%d\n",d);
    
 
 
}
 
void func2(int x,int y,int &p_z){
    p_z = x + y;
 
}
 
 
int func1(int e,int r,int &t){
 
    func2(e,r,t);
	return t;
 
}

返信お願いします

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: 仮引数の使い方

#28

投稿記事 by softya(ソフト屋) » 13年前

問題(1)はOKです。ただ、引数名がp_zなのはポインタを表すpなので避けて下さい。
問題(2)に関してはmainからc→t→p_zと参照で渡していますが、func1→func2の間だけの参照にして下さい。mainからの変数をfunc1に参照で渡してはいけません。と言うか渡す意味がありません。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

stream

Re: 仮引数の使い方

#29

投稿記事 by stream » 13年前

問題(2)このプログラムは処理が通らないプログラムなんですがイメージは合っていますか??

コード:

 
#include <stdio.h>
 
int func1(int e,int r,int t);
void func2(int x,int y,int &z);
 
int main(void){
 
    int a,b,c,d;
    scanf("%d",&a);
    scanf("%d",&b);

    d = func1(a,b,c);
    printf("%d\n",d);

 
}
 
void func2(int x,int y,int &z){
    z = x + y;
 
}
 
 
int func1(int e,int r,int t){
 
    func2(e,r,t);
    return t;
 
}


アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: 仮引数の使い方

#30

投稿記事 by softya(ソフト屋) » 13年前

stream さんが書きました:問題(2)このプログラムは処理が通らないプログラムなんですがイメージは合っていますか??

コード:

 
#include <stdio.h>
 
int func1(int e,int r,int t);
void func2(int x,int y,int &z);
 
int main(void){
 
    int a,b,c,d;
    scanf("%d",&a);
    scanf("%d",&b);

    d = func1(a,b,c);
    printf("%d\n",d);

 
}
 
void func2(int x,int y,int &z){
    z = x + y;
 
}
 
 
int func1(int e,int r,int t){
 
    func2(e,r,t);
    return t;
 
}

このプログラムは、仮引数とローカル変数の役割をちゃんと理解していない事を表していると思います。
動作はするでしょうが問題があります。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

stream

Re: 仮引数の使い方

#31

投稿記事 by stream » 13年前

ギブアップです、ちょっと分かりません。
答えを教えていただいても構いませんか?

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: 仮引数の使い方

#32

投稿記事 by softya(ソフト屋) » 13年前

func1の仮引数int tは不要なので外します。
[補正]func1とmainとの間のデータのやり取りには不要ですから。
なので、func2の参照用の変数については別の方法を考えてみて下さい。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

stream

Re: 仮引数の使い方

#33

投稿記事 by stream » 13年前

これでどうですか??

コード:

#include <stdio.h>
 
int func1(int e,int r);
void func2(int x,int y,int &z);
 
int main(void){
 
    int a,b;
	int c;
    scanf("%d",&a);
    scanf("%d",&b);
    
   c = func1(a,b);
    printf("%d\n",c);
 
 
}
 
void func2(int x,int y,int &z){
    z = x + y;
 
}
 
 
int func1(int e,int r){
	int t;
 
    func2(e,r,t);
    return t;
 
}

返信お願いします!!!

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: 仮引数の使い方

#34

投稿記事 by softya(ソフト屋) » 13年前

はい。それでOKです。
以上なのですが前回の質問の仮引数の問題は、これで解決しそうですか?

「参考書で・・・ • C言語交流フォーラム ~ mixC++ ~」
http://dixq.net/forum/viewtopic.php?f=3&t=10205

まだ、疑問があれば聞いてくださいね。

これからも色々分からないこともあると思いますが、今までのやり取りのようにテストプログラムを組んでみて実感を掴んでみて下さい。
コンパイル・実行してみないと分からないことは沢山あります。
複雑すぎるプログラムは、まず分からない部分だけ抜き出した簡単なプログラムで実験するのが有効な理解方法の一つです。
それでも分からないとか自信が無ければ、この掲示板で質問してもらえばと思います。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

stream

Re: 仮引数の使い方

#35

投稿記事 by stream » 13年前

返信ありがとうございます!!

softyaさんの的確のアドバイスで詳しく段階を経て
理解することができました

僕はお題を本以外の人に出され、答えていくのは初めてでしたが
とても楽しく返信を返しどう返ってくるのかすごい楽しみでした

また、お世話になることもあると思いますのでそのときはまた
よろしくお願いいたします!

僕はこの春から高専の方でもっと詳しく学びます。それで
Softyaさんの悩みを解決し恩を返したいと思います!!

閉鎖

“C言語何でも質問掲示板” へ戻る