c++初歩的な質問ですが教えて頂けると助かります

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

c++初歩的な質問ですが教えて頂けると助かります

#1

投稿記事 by うしくん » 9年前

c++を勉強(練習)しています。
とりあえずずっと謎なことがあるので教えていただければ助かります。

1.main関数の中には別の関数を作れないのでしょうか?

2.main関数から別の関数を呼び出す場合は、main関数は一番最後に書いて置かないと動きませんか?

3.main関数以外に関数がある場合(例えば関数A)で、両方で使われる変数がある場合はglobal変数として?冒頭、つまり全ての関数の外で、定義しとかないとどうしても動きませんか?

4.使っている問題集で、main関数の中最後に標準出力puts、coutがあるかと思えば、別の呼び出される関数(最後によびだされる関数)の中に標準出力が書かれていたりします。どちらでも同じですか?

4つとも、何度か試してみたものの、未解決の疑問です。そもそも出来ないことを試しているということも考えられ、質問しようと思った次第です。
よろしくおねがいします。

アバター
パコネコ
記事: 139
登録日時: 10年前
住所: 大阪

Re: c++初歩的な質問ですが教えて頂けると助かります

#2

投稿記事 by パコネコ » 9年前

1は私ではわかりません・・・
試しにやってみたら↓は動きました

コード:

#include<stdio.h>
int main(void){
	int pako_kannsuu(void);
	pako_kannsuu();
	return 0;
}
int pako_kannsuu(void){
	printf("pakoneko\n");
	return 0;
}
2、mainより上に宣言を書けば問題ないです。

コード:

#include<stdio.h>
//宣言
int pako_kannsuu(void);
//メイン
int main(void){
	pako_kannsuu();
	return 0;
}
//行いたい処理
int pako_kannsuu(void){
	printf("pakoneko\n");
	return 0;
}
3、?よくわかりません、質問が・・・
関数の中で宣言してそれを別の関数の中でも使える(書きかえれる)か?という意味ならポインタを使えば使えます。
(他にもあった気がするけど・・・)
それとも同じ”名前”の変数を使っても大丈夫か?ということなら問題ないです。
その変数たちは全く関係ない変数です。
4、それが最後の処理?なら同じだと思いますが・・・
状況がわからないとわかりません。

===
何か勘違い書いてたらすいません・・・
ニャン!!\(゜ロ\)(/ロ゜)/

うしくん

Re: c++初歩的な質問ですが教えて頂けると助かります

#3

投稿記事 by うしくん » 9年前

素早い返信ありがとうございますパコネコ さん。
パコネコ さんが書きました:1は私ではわかりません・・・
試しにやってみたら↓は動きました
そういうのではなく、
int a = 0;
int main(){
 int pako(){
   ○○○
 }
 a = pako();
}
みたいなのです。無理でしょうか。まあ、関数を並べる書き方に慣れれば、そっちで書けばいい話かもしれませんが。
パコネコ さんが書きました:2、mainより上に宣言を書けば問題ないです。
ありがとうございます。
パコネコ さんが書きました:3、?よくわかりません、質問が・・・
関数の中で宣言してそれを別の関数の中でも使える(書きかえれる)か?という意味ならポインタを使えば使えます。
(他にもあった気がするけど・・・)
それとも同じ”名前”の変数を使っても大丈夫か?ということなら問題ないです。
その変数たちは全く関係ない変数です。
そうですね、質問の意味は、今参考にしているプログラム集があるのですが、関数がmain関数1つしかない場合は、ほとんどすべての変数がmain内で宣言されていて、const int MAX_NUM =100 だけがmainより上でぽつんと宣言されています.ですが、関数が2つ以上になると(宣言やmain関数の説明が本では省略されていて)よくわからず、そのまま単に関数だけ別にmainの外に作って呼び出したりしても、その外に作った関数でエラー:変数が定義されていません、って出てしまいました。最初にmain関数で標準入力した変数データをmain以外の関数で使う場合です。
なので、関数が2個以上ある場合は、2個以上の関数で使われる変数は全てプログラムの冒頭でglobal変数として宣言しておかないと行けないのかなと思っているのですが、これは正しいですか?

Blue

Re: c++初歩的な質問ですが教えて頂けると助かります

#4

投稿記事 by Blue » 9年前

1.
ローカル関数の定義はできないかと。
ローカルクラスの静的メソッドを使えば似たようなことはできなくもないけど。

コード:

int main()
{
    struct Hoge {
        static int pako() { return 1; };
    };
    int i = Hoge::pako();

    return 0;
}
3.
単純に関数の引数を使えばいいのではないでしょうか?
ポインタでも参照渡しでも値を設定することは可能ですので。

コード:

int pako(int& n);

int main()
{
    int n;
    int i = pako(n);

    return 0;
}

int pako(int& n)
{
    n = 100;
    return 1;
}

アバター
パコネコ
記事: 139
登録日時: 10年前
住所: 大阪

Re: c++初歩的な質問ですが教えて頂けると助かります

#5

投稿記事 by パコネコ » 9年前

コード:

#include<stdio.h>
int main(void){
	int pako_kannsuu(void){
		printf("pakoneko\n");
		return 0;
	};
    pako_kannsuu();
    return 0;
}
でやってみたところ「;」をつけろとしつこく怒られました。
なのでこのままでは難しいかと・・・


こんな感じでどうでしょうか?

コード:

#include<stdio.h>
int pako_A(int);
int pako_B(int *);
int main(void){
	int a=50;
	pako_A(a);
	printf("a=%d\n",a);
	pako_B(&a);
	printf("a=%d\n",a);
	return 0;
}
int pako_A(int a_modoki){
	a_modoki+=10;
	printf("a_modoki=%d\n",a_modoki);
	return 0;
}
int pako_B(int *a_modoki){
	*a_modoki+=10;
	printf("a_modoki=%d\n",*a_modoki);
	return 0;
}
pako_Aの中での変化は元のaには関係ありませんが、
pako_Bの中では変数aのアドレスに書き込んでるため同じ変数として扱えます。

コード:

/*実行結果*/
a_modoki=60
a=50
a_modoki=60
a=60
ということでいいでしょうか?
ニャン!!\(゜ロ\)(/ロ゜)/

うしくん

Re: c++初歩的な質問ですが教えて頂けると助かります

#6

投稿記事 by うしくん » 9年前

パコネコ さん、Blue さん、返信ありがとうです。
ポインタを使うなどでmain関数内で宣言した変数でも他の関数で使用可能ということですね。
とりあえず、ポインタはよくわかってないので、頭にとめておき、慣れてきたら試してみます。
ありがとうございます。

ところで、

コード:

#include <iostream>
#include <algorithm>

const int MAX_NUM = 1000;
int n,m;
int k[MAX_NUM];
bool f = false;

bool binary_search(int x){
	int l =0, r =n;
	while((r-l)>=1){
		int i = (l+r)/2;
		if(k[i] == x) return true;
		else if(k[i] < x) l=i+1;
		else r=i;
	}
	return false;
}

void solve(){
	using namespace std;
	//sort for binary search
	sort(k, k + n);
		
	for (int a=0; a<n; a++) {
		for (int b =0; b<n; b++) {
			for (int c =0; c<n; c++) {
				//binary search instead of 4th loop
				if(binary_search(m-k[a]-k[b]-k[c])){
					f = true;
				}
			}
		}
	}
	
	if(f) puts("yes");
	else puts("no");
}

int main () {
	using namespace std;
    
	//	int n,m;
	//	int k[MAX_NUM];
	
	cin >> n >> m;
	for(int i = 0; i <n; i++){
		cin >> k[i];
	}
	
	solve();
	
	return 0;
}

これなら動くのですが、このmain関数をbinary_search関数の上に持ってくると、デバッグでエラーが出ます。main関数内のsolve();の行で。宣言されてないと。
ですから、main関数を一番上に持って来れないのです。
上に置けるとのことですが、どうしたらいいのでしょうか?
よろしくおねがいします。

アバター
bitter_fox
記事: 607
登録日時: 9年前
住所: 大阪府

Re: c++初歩的な質問ですが教えて頂けると助かります

#7

投稿記事 by bitter_fox » 9年前

以下でできるはずです。
プロトタイプ宣言をすることで、「こういう名前の関数がありますよー」ということを先に言っておいてあとから中身を定義することができます。

コード:

#include <iostream>
#include <algorithm>

const int MAX_NUM = 1000;
int n,m;
int k[MAX_NUM];
bool f = false;

// プロトタイプ宣言
bool binary_search(int x);
void solve();

int main () {
	using namespace std;
    
	//	int n,m;
	//	int k[MAX_NUM];
	
	cin >> n >> m;
	for(int i = 0; i <n; i++){
		cin >> k[i];
	}
	
	solve();
	
	return 0;
}

bool binary_search(int x){
	int l =0, r =n;
	while((r-l)>=1){
		int i = (l+r)/2;
		if(k[i] == x) return true;
		else if(k[i] < x) l=i+1;
		else r=i;
	}
	return false;
}

void solve(){
	using namespace std;
	//sort for binary search
	sort(k, k + n);
		
	for (int a=0; a<n; a++) {
		for (int b =0; b<n; b++) {
			for (int c =0; c<n; c++) {
				//binary search instead of 4th loop
				if(binary_search(m-k[a]-k[b]-k[c])){
					f = true;
				}
			}
		}
	}
	
	if(f) puts("yes");
	else puts("no");
}


アバター
パコネコ
記事: 139
登録日時: 10年前
住所: 大阪

Re: c++初歩的な質問ですが教えて頂けると助かります

#8

投稿記事 by パコネコ » 9年前

bool binary_search(int);
をメインの上に置いておけばメインより下に
bool binary_search(int x){
・・・
}
としてもエラーでないはずです・・・
こんな感じ?

コード:

#include <iostream>
#include <algorithm>
//関数の宣言
void solve(void);
bool binary_search(int);

const int MAX_NUM = 1000;
int n,m;
int k[MAX_NUM];
bool f = false;
 

 
int main () {
    using namespace std;
    
    //  int n,m;
    //  int k[MAX_NUM];
    
    cin >> n >> m;
    for(int i = 0; i <n; i++){
        cin >> k[i];
    }
    
    solve();
    
    return 0;
}
bool binary_search(int x){
    int l =0, r =n;
    while((r-l)>=1){
        int i = (l+r)/2;
        if(k[i] == x) return true;
        else if(k[i] < x) l=i+1;
        else r=i;
    }
    return false;
}
 
void solve(){
    using namespace std;
    //sort for binary search
    sort(k, k + n);
        
    for (int a=0; a<n; a++) {
        for (int b =0; b<n; b++) {
            for (int c =0; c<n; c++) {
                //binary search instead of 4th loop
                if(binary_search(m-k[a]-k[b]-k[c])){
                    f = true;
                }
            }
        }
    }
    
    if(f) puts("yes");
    else puts("no");
}
私の使ってるものでは、インクルードできなかったので起動してませんが・・・
おそらくできるはず・・・
===
すいませんかぶってました・・・
ニャン!!\(゜ロ\)(/ロ゜)/

うしくん

Re: c++初歩的な質問ですが教えて頂けると助かります

#9

投稿記事 by うしくん » 9年前

どうもありがとうございます。
関数の型の宣言を重複してするようで少し違和感がありますが、そういう仕様なのですね。
これですっきり解決しました。

ところで、ついでにあと一つだけ聞きたいことがあります。
プログラミングというよりアルゴリズムの質問になってしまいますが。
binary search(2分探索)では長さnのソート済み配列kに数xが含まれているかを確かめる場合、log2 n(2は下付き)回の繰り返しで済み、結果、計算量はO(log n)となるそうですが、このlog2n(2は下付き)はどういう計算で出てきたのでしょう?
下付きの2は、毎回2分する2から来ているように想像できますが、それくらいしか思いつきません。
ご存知でしたら教えてください。

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

Re: c++初歩的な質問ですが教えて頂けると助かります

#10

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

>1.main関数の中には別の関数を作れないのでしょうか?
関数内関数は基本的に作れません。
他言語ではサポートされているものも多数あります。

>2.main関数から別の関数を呼び出す場合は、main関数は一番最後に書いて置かないと動きませんか?
関数をプロトタイプ宣言すれば順番は関係有りません。

>3.main関数以外に関数がある場合(例えば関数A)で、両方で使われる変数がある場合はglobal変数として?冒頭、つまり全ての関数の外で、定義しとかないとどうしても動きませんか?
そうなります。
あるいは、引数渡しを使います。

>4.使っている問題集で、main関数の中最後に標準出力puts、coutがあるかと思えば、別の呼び出される関数(最後によびだされる関数)の中に標準出力が書かれていたりします。どちらでも同じですか?

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

うしくん

Re: c++初歩的な質問ですが教えて頂けると助かります

#11

投稿記事 by うしくん » 9年前

softya(ソフト屋) さんが書きました: 他言語ではサポートされているものも多数あります。

関数をプロトタイプ宣言すれば順番は関係有りません。

そうなります。
あるいは、引数渡しを使います。

よく分からないので例を挙げてください。
softya(ソフト屋)さん、返信ありがとうございます。
分かりました。
4については、私のNo6のポストに添付のコードを参照ください。
そこでは、solve関数に
if(f) puts("yes");
else puts("no");
と書かれているのですが、これをmain関数の最後(solve();行の直後)に持ってきても、同じことかどうかということです。私が手本にしている本に載ってるこのプログラムではsolve内にありますが、これは何かこだわりがあってそうしているのか、それとも定番の表記法だからか、たまたまか、という質問です。

よろしくおねがいします。

アバター
bitter_fox
記事: 607
登録日時: 9年前
住所: 大阪府

Re: c++初歩的な質問ですが教えて頂けると助かります

#12

投稿記事 by bitter_fox » 9年前

うしくん さんが書きました: binary search(2分探索)では長さnのソート済み配列kに数xが含まれているかを確かめる場合、log2 n(2は下付き)回の繰り返しで済み、結果、計算量はO(log n)となるそうですが、このlog2n(2は下付き)はどういう計算で出てきたのでしょう?
下付きの2は、毎回2分する2から来ているように想像できますが、それくらいしか思いつきません。
ご存知でしたら教えてください。
バイナリサーチの特徴は、二分を繰り返していくところです。
二分を繰り返すということは、文字どうり2で割っていくということです。
で、操作回数は長さn'が1になった時の2で割った回数です。

m回の操作で、nの長さまで調べられるといった風に言い換えると
1回の操作で、2
2回の操作で、4
3回の操作で、8
4回の操作で、16
といった風になります。

このとき、nに注目すると、
2, 4, 8, 16, ...となり、2のm乗となります。

よって、mはlog2(n)で求められます。

アバター
bitter_fox
記事: 607
登録日時: 9年前
住所: 大阪府

Re: c++初歩的な質問ですが教えて頂けると助かります

#13

投稿記事 by bitter_fox » 9年前

うしくん さんが書きました: そこでは、solve関数に
if(f) puts("yes");
else puts("no");
と書かれているのですが、これをmain関数の最後(solve();行の直後)に持ってきても、同じことかどうかということです。私が手本にしている本に載ってるこのプログラムではsolve内にありますが、これは何かこだわりがあってそうしているのか、それとも定番の表記法だからか、たまたまか、という質問です。
fはグローバル変数なので、fの値はsolve関数を出ても保持されているので、slove();の次に持ってきても問題はないです。

関数の処理をどこで分けるかは非常に難しい問題ですね。
今回は、solve関数で出力までの処理を完結させたかったので関数内で出力をしたのでしょう。

ただ、これだと、他の文字列を表示させたかったり、真偽で場合分けしたかったりした場合は、solve関数をいじらなければならいのであまりよろしくありません。
またグローバル変数を使ってるというのも、どこからでも値を変えられたりしてよろしくありません。
trueかfalseをただ単に返すだけにして、あとは呼び出し元任せにした方がよいと思います。

うしくん

Re: c++初歩的な質問ですが教えて頂けると助かります

#14

投稿記事 by うしくん » 9年前

bitter_foxさん
バイナリサーチの説明ありがとうございます。対数と指数をネットでしらべてなんとか感覚はつかめました。
no11にもお答えいただき感謝です。

maru
記事: 150
登録日時: 9年前

Re: c++初歩的な質問ですが教えて頂けると助かります

#15

投稿記事 by maru » 9年前

うしくん さんが書きました:どうもありがとうございます。
関数の型の宣言を重複してするようで少し違和感がありますが、そういう仕様なのですね。
これですっきり解決しました。
既に納得しておられるようですが、
bool binary_search(int);
これは関数のプロトタイプ宣言(Declarations)です。

bool binary_search(int x){
・・・
}
これは関数の定義(Definitions)で、宣言ではありません。従って重複しているわけではありません。

関数が使用時に既に定義されていれば(main関数が後ろにある場合)宣言なしにそのまま使用できますが、
定義されていない場合(main関数が前にある場合)には関数プロトタイプ宣言が必要です。

C言語ではプロトタイプ宣言なしで使用することもできますが、引数、型のチェックが行われないので、
その後の処理が保障されません。

dic
記事: 585
登録日時: 10年前
住所: 宮崎県

Re: c++初歩的な質問ですが教えて頂けると助かります

#16

投稿記事 by dic » 9年前

4.使っている問題集で、main関数の中最後に標準出力puts、coutがあるかと思えば、別の呼び出される関数(最後によびだされる関数)の中に標準出力が書かれていたりします。どちらでも同じですか?
引用失敗してたらすいません

main()関数の最後で puts,cout を呼び出すのと
main()関数の最後で 別の関数を呼び出し、そこでputs,cout を呼び出すのは同じことか?
ということでしょうか?

標準出力に出力するという点においては同じです
puts,cout を呼び出すタイミング(位置)は異なります(これはわりますよね?)

別の意味でしたらすいません

ISLe
記事: 2648
登録日時: 10年前
連絡を取る:

Re: c++初歩的な質問ですが教えて頂けると助かります

#17

投稿記事 by ISLe » 9年前

C++であれば関数内関数(のようなもの)は次のように作れます。

コード:

#include <iostream>
int main()
{
	struct {
		int operator()(int a, int b) {
			return a + b;
		}
	} functor;
	auto lambda = [](int a, int b) {
		return a + b;
	};
	std::cout << functor(12, 34) << std::endl;
	std::cout << lambda(56, 78) << std::endl;
	return 0;
}
functor(ファンクタ)は()演算子のオーバーライドを利用しています。このようなクラス(のインスタンス)は関数オブジェクトと呼ばれます。

lambda(ラムダ)式は簡単に関数オブジェクトの定義できるようにC++0xで採用されることになっています。
Visual C++は2010、gcc(g++)は4.5以降(要-std=c++0xオプション)でコンパイルできます。

うしくん

Re: c++初歩的な質問ですが教えて頂けると助かります

#18

投稿記事 by うしくん » 9年前

解決ってのを押しとくのを忘れてました。
ISLeさん、dicさん、 maruさん、補足説明ありがとうございました。とても勉強になりました。

mats

Re: c++初歩的な質問ですが教えて頂けると助かります

#19

投稿記事 by mats » 9年前

解決済みのようですが失礼します

うしくんさんの使用している本とは,「プログラミングコンテスト チャレンジブック」でしょうか?
(違っていたら以降は無視してください.トピ汚しすいません…)

もしそうであればその本の13ページに書いてある
「本質から外れるため、この本では入力はすべてmain関数で読み込まれてグローバル変数に置かれたのち、
関数solveが呼ばれることによって問題を解く形式を用いることにします。」
の文章がいくつかの質問に対する答えになると思います.

つまり,solve関数内で出力をしているのも,グローバル変数を用いているのも,その本におけるルールに乗っ取った結果だと思われます

閉鎖

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