関数がわからん

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

関数がわからん

#1

投稿記事 by クボタとシノブ » 14年前

申し訳ありません質問です。
C言語及びC++がよくわからなすぎる原因の1つが、
関数でした。
むしろ初心者丸出しな質問ですけど、ここで引っかかっています。

よく、大きくなったプログラムを効率よく作るために、
処理を関数に分ける必要があるのですが、
関数というやつは、自分の処理が終わったら、
さっさと大事な変数などの情報を忘れてしまいやがるのです。

どのゲームを見ても、ハイスコアから敵の座標まで、
忘れないで覚えたまま処理しているのですけども。

上手に関数を使いこなせないでいるので、
ほかの関数で使いたい変数を使うことができないし、
使っている変数を、関数に上手に預けることもできないし、

グローバル変数が悪というのならば、
グローバル変数以外の方法で、
いろんな関数を使いながら、必要な変数を忘れないで、
変数の内容を記憶させつづけて処理させる方法が、いまいちよくわかりません。
グローバル変数が悪という理由も、こじつけにしか思えないのですけども、
悪と言い切るからには、回避する方法も知っているはずです。

というよりも、関数の有効範囲?を上手に理解できて、関数とつきあう方法を伝授してください。
うまく伝えたいことが伝えられていないかも知れません。

アバター
はんなり
記事: 48
登録日時: 14年前

Re: 関数がわからん

#2

投稿記事 by はんなり » 14年前

率直に、
関数の中の変数の値を忘れさせたくなければ

static

というのを宣言の前につけましょう


使用例:

コード:

int hensu;
からの↓

コード:

static int hensu;

アバター
はんなり
記事: 48
登録日時: 14年前

Re: 関数がわからん

#3

投稿記事 by はんなり » 14年前

ちなみに、グローバル変数は悪とは言いませんが、
関数の中などで宣言した変数名と被ると色々面倒だったりするからではないでしょうか?
あとは書き換え安いのでバグに気付きにくいとか。


こちらをどうぞ:
http://sj6.org/グローバル変数の弊害について/

>>すいません。はんなりさん、このリンクなんですか? by softya(ソフト屋)
グローバル変数のデメリットに関するまとめてあったサイトのURLを貼りました。
ウイルスの類ではありませんが、問題あるなら消します。
Yuo さんが書きました: http://bit.ly/mtHmZh+によると,http://sj6.org/グロãƒ%20...%203ãƒ%20«変数の弊害ã%20«ついて/へのリンクですが,リンクが不正確ですね (404 NOT FOUND)。
YuOさんありがとうございました。
これからはbit.lyを控えますm(_ _)m
最後に編集したユーザー はんなり on 2011年5月05日(木) 11:08 [ 編集 2 回目 ]

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

Re: 関数がわからん

#4

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

最低限のグローバル変数は必要だと思いますが、適当にグローバル変数を使う人は大きな規模のプログラムを組むとだいたい致命的なバグを潜ませます。
自分で変数の使う範囲を決めれない人、適当に思い付きで組む人が膨らむプログラム上に適当に変数処理を散りばめることで自分でも変数の変化が追いかけらられなく成ることが大半の原因です。
「グローバル変数を使うな」は、そういう人に対する戒めです。そういう縛りを作ることで変数のスコープ範囲に気を配るようになるからですね。

あとグローバル変数はモジュール(同じグループの関数群)と別のモジュールの結びつきを強める恐れがあります。これはモジュールの再利用性を妨げて開発効率を下げます。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

YuO
記事: 947
登録日時: 14年前
住所: 東京都世田谷区

Re: 関数がわからん

#5

投稿記事 by YuO » 14年前

はんなり さんが書きました:>>すいません。はんなりさん、このリンクなんですか? by softya(ソフト屋)
グローバル変数のデメリットに関するまとめてあったサイトのURLを貼りました。
ウイルスの類ではありませんが、問題あるなら消します。
http://bit.ly/mtHmZh+によると,http://sj6.org/グロãƒ%20...%203ãƒ%20«変数の弊害ã%20«ついて/へのリンクですが,リンクが不正確ですね (404 NOT FOUND)。
残された文字列から想定するに,http://sj6.org/グローバル変数の弊害について/ が正しいURLでだと思います。

短縮URLは,本当のリンク先がわからないので,twitterのように文字数制限がある場合程度に留めた方が良いです。

アバター
Dixq (管理人)
管理人
記事: 1662
登録日時: 14年前
住所: 北海道札幌市
連絡を取る:

Re: 関数がわからん

#6

投稿記事 by Dixq (管理人) » 14年前

関数に処理をさせて、その結果を得たいなら、ポインタを使うと良いと思います。
またゲームプログラムの設計については
http://dixq.net/g/
「ゲームプログラム設計」のコーナーで紹介しているのでご覧ください。

クボタとシノブ

Re: 関数がわからん

#7

投稿記事 by クボタとシノブ » 14年前

みなさんありがとうございます。

グローバル変数を使うと、ポインタを使わなくても、
お目当ての変数の処理が楽に出来る代わりに、
予想もしていなかった別の関数などからの不意打ちを食らって、
バグの元になる・・・という意味で悪なのでしょうか。

逆に、それらのものに影響されないように関数に数値を預けるようにするには、
ポインタを使うしかない。
返り血では、1個しか変数を保証できないようだし。

グローバル変数を使う要領でstatic宣言すれば、
そのソース以外からの干渉を受けないから、
グローバル変数が悪である理由は封じ込められるようですね。
でも、cppファイルを複数使う状況だと、状況は元に戻ってしまいますね。

なかなか、打ち込んでいるうちに覚えてくる・・・が出来ないものなので、
今回、どうしても質問させて頂きました。
関数を自作できるはいいとして、
現状の使い勝手の悪さを、どのように克服するのかが、どうしても知りたかったのでした。

アバター
h2so5
副管理人
記事: 2212
登録日時: 14年前
住所: 東京
連絡を取る:

Re: 関数がわからん

#8

投稿記事 by h2so5 » 14年前

クボタとシノブ さんが書きました: 返り血では、1個しか変数を保証できないようだし。
一応、複数の値を返したければポインタを使う以外にも構造体や、
C++ならクラスやstd::pair、boost::tupleなどを使う方法があります。

アバター
はんなり
記事: 48
登録日時: 14年前

Re: 関数がわからん

#9

投稿記事 by はんなり » 14年前

クボタとシノブ さんが書きました: グローバル変数を使う要領でstatic宣言すれば、
そのソース以外からの干渉を受けないから、
グローバル変数が悪である理由は封じ込められるようですね。
うーん。ちょっと間違ってます。
staticは関数などで、何度も定義をする場合に使うと再度定義することなく処理を進められるものです。

コード:

void kansu(){
 int a=0; //これだと変数aは常に0に戻されます
 a+=1;    //aの値を増やします
 printf("%d¥n",a);//aの値を出力して改行。
}
上のkansuという関数を繰り返すと、出てくる結果は
1
1
1

となります。

ここでintの前にstaticを付けることで
1
2
3

としっかり増えていきます。



関数の外の値をいじりたいときは、
関数の引数に*(アスタリスク)を付け、
関数の呼びだす時に変数に&(アンパーサンド)を付けて渡しましょう。



解決したのであれば、投稿の際に投稿の右側の

解決!

のチェックボタンを押して投稿しましょう。

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

Re: 関数がわからん

#10

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

大体は構造体の受け渡しで解決すると思います。
関数に複数の機能持たせると大体引数が増えて面倒なことになるので、関数分けに問題があるケースが多いです。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

クボタとシノブ

Re: 関数がわからん

#11

投稿記事 by クボタとシノブ » 14年前

解決したような、してないような?
解決おしたくても押せない状態。
完全に理解したつもりになって、いざ自分で組み立てようとすると、
どこか間違ったものがいつも出来上がるのでした。

はじめにメイン関数内で試作して成功したあとで、
関数として分離・・・でも、変数を中心に、いつも何かがおかしい関数が出来上がるのでした。

構造体とポインタ、
C++だったらクラスかstd::pair、boost::tuple・・・。

いまのところはヒントとして受け取りながら、
もう少し悩み苦しみます。

アバター
はんなり
記事: 48
登録日時: 14年前

Re: 関数がわからん

#12

投稿記事 by はんなり » 14年前

クボタとシノブ さんが書きました: はじめにメイン関数内で試作して成功したあとで、
関数として分離・・・でも、変数を中心に、いつも何かがおかしい関数が出来上がるのでした。
メイン関数で作ると正常。いざ関数に分離すると異常・・・。
エラーは出てるんですか?

ソースコードを全部UPしてもらったほうが解決が早いかもしれません

クボタとシノブ

Re: 関数がわからん

#13

投稿記事 by クボタとシノブ » 14年前

コード:

#include<stdio.h>
int eroguro(int a){
	a=a+10;
	return a;
}
int main(){
	int a=1;
	eroguro(a);
	printf("a=%d",a); //最初、何を血迷ったか%fにして必死に間違い探ししてた
	return 0;
}
結果 a=1

勉強してブランクあいて、また勉強して、
を繰り返してるというものあるけど、
ノーヒントで自分でどうにかしようとすると、
毎回ありえない数字になります。
まだ関数をコントロールしきれていない状態。

・・・って、あ、なんかうまく逝った。
いろいろいじっていたら、
このソースでいうところの、a=11になりました。

改造したらうまくいった方法例
1 void eroguro(int& a){ にしたらうまくいった。
2 メイン関数内でeroguro関数使うときの命令eroguro(a)の、aを、&aにしたあと、
 void eroguroの関数の、aの部分を、全部*aにしたらうまくいった。

どうやら、参照またはポインタというやつみたいですね。
ということは、return a;は何のためにあるのだか。

もしかしたら、参照またはポインタを使わないと、
上手に関数に変数を預けられないものなのでしょうか。

解決でもいいような気がしてきましたが、
この、なんだかよくわからないもやもやが、まだ晴れません。
とりあえず解決にしますけど、何か意見頂けたら幸いです。

たいちう
記事: 418
登録日時: 14年前

Re: 関数がわからん

#14

投稿記事 by たいちう » 14年前

> どうやら、参照またはポインタというやつみたいですね。
> ということは、return a;は何のためにあるのだか。
>
> もしかしたら、参照またはポインタを使わないと、
> 上手に関数に変数を預けられないものなのでしょうか。

コード:

int add10(int a) {
	a += 10;
	return a;
}

void add10(int& a, int& b) {
	a += 10;
	b += 10;
}
前者はreturnで計算結果を返しています。
後者は2つの値を更新したいのですが、returnで返せるのは1つだけです。
他の回答者も書いているように、関数から複数の値を受け取る方法がいくつかあり、
その内の1つが参照を使った方法です。

またうまくいかないことがあれば、そのソースコードを貼って質問してください。
その際、できるだけ質問を小さく・具体的にできると回答も付きやすいですし、
成長にもつながりやすいです。

クボタとシノブ

Re: 関数がわからん

#15

投稿記事 by クボタとシノブ » 14年前

本当の意味で「解決」ということで。
皆さん本当にありがとうございます。
ここまで解決してもらえば、自力でなんとか理解できそうです。

どうやら、自分にとっては、参照というやり方が、相性がよさそうです。

ISLe
記事: 2650
登録日時: 14年前
連絡を取る:

Re: 関数がわからん

#16

投稿記事 by ISLe » 14年前

コード:

#include <stdio.h>
int add(int a, int b){
    return a+b;
}
int main(void){
    int a=12, b=34;
    printf("a=%d\nb=%d\na+b=%d\n",a, b, add(a, b));
    return 0;
}
こういうコードは参照だととても面倒くさいことになると思います。
あとC言語では参照使えませんし。

あと

コード:

void hoge(int &a, int &b){
    // aとbが同じオブジェクトを差している可能性
}
とか。
気付かずに一時オブジェクトを参照してたとかもよくありますかね。
クボタとシノブ さんが書きました:どうやら、自分にとっては、参照というやり方が、相性がよさそうです。
引数を書きかえるプログラム言語はふつうにあるのでかまわないと思いますけど、異文化コミュニケーションを乗り越えるために相当の努力を強いられることは間違いないでしょう。

閉鎖

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