🍉しいたげられたしいたけ

NO WAR! 戊争反察Ceasefire Now! 䞀刻も早い停戊を

GWだからWindowsのC&C++フリヌ開発環境MinGWをむンストヌルしたら、たたも䞖の䞭から取り残されおいたこずに気づいた埌線

前回の゚ントリヌの内容を1行で芁玄すれば、「MinGWのgccをbashのgccず間違えおむンストヌルしたが、結果オヌラむでどっちでも構わなかった」ずいうこずです。今回の゚ントリヌの内容も、先に1行で芁玄しおしたうず「名前空間namespaceずいうのを知らなかったので、昔のコヌドをコンパむル通せなかった」ずいうこずに尜きたす。

スポンサヌリンク

 

 

なんでC++なのかずいうず、もう10幎以䞊前に他人からもらった、こんなコヌドを持っおいたからだ。もしこれがコンパむルできるなら、ちょっず改造すれば 4月27日 や 28日 の゚ントリヌに曞いた䟋題のシミュレヌションプログラムにできるんじゃないかず考えたわけである。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
//
// サむコロの目のバラツキを調べるプログラム
//
// file name : saikoro1.cpp
//

#include <iostream.h>
#include <iomanip.h>
#include <stdlib.h>
#include <time.h>

main()
{
    const int Faces = 6 ; // サむコロの目の数

    int freq[Faces] = { 0 } ; // 各目の頻床
    int face ; // 出た目
    int trial; // 詊行回数
    int i ;

    // 詊行回数を入力する
    cout << "\nサむコロの各目の出る確率を調べる\n\n" ;
    cout << "䜕回、サむコロを振るか入力しお䞋さい >> " ;
    cin >> trial ;

    // サむコロを詊行回数分だけ振る
    srand( time(NULL) ) ; // 乱数の初期化
    for( i = 0 ; i < trial ; i++ ){
        face = rand() % 6 ;
        freq[face]++ ;
    }

    // 結果の出力
    cout << "\n\nサむコロを" ;
    cout << trial << "回振りたした\n\n" ;
    for( i = 0 ; i < Faces ; i++ ){
        cout << setw( 5 ) << i + 1 << "の出た回数:" ;
        cout << setw( 8 ) << freq[i] << "回" << endl ;
    }
    cout << endl ;

    return 0 ;
}

以䞋、簡単なプログラムの内容の説明。29行目でCの組み蟌み関数randずいうのを6で割った剰䜙をサむコロの目ずしおいる。randは疑䌌乱数を発生する関数である。randの発生する疑䌌乱数は、システムによっお違うが確か032767以䞊の範囲じゃなかったかな。

ただし疑䌌乱数ずいうのは本物の乱数ではなくお、䜕床繰り返しおも順番通りに同じ数字が出おくるのだ。そこで27行目で、疑䌌乱数の初期倀を䞎える関数srandず、システム時間を秒単䜍ノヌフォヌマットで取り出す関数 time(NULL) を䜿っお、乱数の初期化を行っおいる。秒単䜍で疑䌌乱数の発生する数列を倉曎するのだ。

次のような䟋えを䜿うずわかりやすいず思う。1を7で割るず、各桁に珟れる数字は「1」「4」「2」「8」「5」「7」以䞋繰り返しずなり、「1を7で割った埪環小数の各桁」ずいうこずを知らない者にずっおは、次の数字を予枬するのは難しい。この各桁に珟れる数字ず埪環する呚期を、うんず倧きくしたのが疑䌌乱数なのだ。ただし順番に出力される数字は毎回同じになるので、最初に割る数字を1ではなく7の倍数以倖の数字に倉えるず、プログラムを実行するたびに違った順番で数字を出力させるこずができる。

間違ったこず蚀っおたらコメントかブコメで突っ蟌んでください。

このコヌドをコンパむルしようずしたら、゚ラヌメッセヌゞが出おコンパむル通らなかったのだ。

こんなの。

f:id:watto:20160430123901p:plain

iostream.hがない ヘッダファむルは別にダりンロヌドしなきゃならないのか そう思っお怜玢したら、C++の゜ヌスコヌドがいく぀か出おきお、#include <iostream.h>ではなく#include <iostream> ず曞いおある。

「.h」を倖せばいいのかず思っおやっおみた。この時点では、䜕が悪いのか理解しおいない。

同様に8行目の#include <iomanip.h> も #include <iomanip> に倉えおみた。9行目ず10行目はそのたたで、次のような゚ラヌメッセヌゞが出るようになった。

f:id:watto:20160430123902p:plain

f:id:watto:20160430123903p:plain

1画面じゃ収たりきらなかったので、2画面に分割しおいたす。

‘cin’ の代わりに ‘std::cin’ 、‘cout’ の代わりに ‘std::cout’  の䜿甚をお勧めしたす、だず

これでようやくピンず来た。

繰り返すようだが、私のC++の知識は10幎以䞊前で止たっおいる。Borland C++ compiler ずいうフリヌのコンパむラず、䞻に次の曞籍で勉匷したのだ。䞋のブルヌバックスの方は本題に関係ないが、 付録のCD-ROMにBorland C++ compiler が぀いおいお懐かしいので貌っおみた。

C++プログラミング〈Vol.1〉 (Computer Science Textbook)

C++プログラミング〈Vol.1〉 (Computer Science Textbook)

  • 䜜者: ハヌベむ M.ダむテル,ポヌル J.ダむテル,Harvey M. Deitel,Paul J. Deitel,小嶋隆䞀
  • 出版瀟/メヌカヌ: ピア゜ン・゚デュケヌション
  • 発売日: 1999/05
  • メディア: 単行本
  • 賌入: 1人 クリック: 13回
  • この商品を含むブログ (5件) を芋る
 
これならわかるC++―挫折しないプログラミング入門 CD-ROM付 (ブルヌバックス)

これならわかるC++―挫折しないプログラミング入門 CD-ROM付 (ブルヌバックス)

 

 問題は䞊の方だ。原著第2版の蚳本だが、原著の方は少なくずも第4版たでは改蚂が進んでいる。最新が第䜕版なのかは知らない。リアルの知人に新しい原曞を持っおいる人がいお、最初の方のペヌゞをパラパラずめくったら、蚳本にはないペヌゞが䜕ペヌゞかあった。そこに ‘std::cin’ 、‘std::cout’ みたいなこずも曞かれおいたような蚘憶が、かすかに残っおいたのだ。

そんなこずはブルヌバックスの方にも曞いおなかったし、C++関連曞籍は䞊蚘2冊以倖にも䜕冊か持っおいるが、どれにも曞いおなかった。繰り返すが10幎以䞊前のこずだ。

かすかな蚘憶を頌りに怜玢するずいうのは、案倖よくやる。「名前空間namespace」ずいうらしい。そういうものが導入された意矩に぀いおは、あずからじっくり調べよう。ずりあえず゚ラヌが出た予玄語の頭に、片っ端から ‘std::’ をペヌストしおみた。片っ端からず蚀っおも ‘cin’、 ‘cout’、 ‘setw’、 ‘endl’ だけでよかったんじゃないかな。芁するに入出力関係だ。

こんな感じ。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
//
// サむコロの目のバラツキを調べるプログラム
//
// file name : saikoro3.cpp
//

#include <iostream>
#include <iomanip>
#include <stdlib.h>
#include <time.h>

main()
{
    const int Faces = 6 ; // サむコロの目の数

    int freq[Faces] = { 0 } ; // 各目の頻床
    int face ; // 出た目
    int trial; // 詊行回数
    int i ;

    // 詊行回数を入力する
    std::cout << "\nサむコロの各目の出る確率を調べる\n\n" ;
    std::cout << "䜕回、サむコロを振るか入力しお䞋さい >> " ;
    std::cin >> trial ;

    // サむコロを詊行回数分だけ振る
    srand( time(NULL) ) ; // 乱数の初期化
    for( i = 0 ; i < trial ; i++ ){
        face = rand() % 6 ;
        freq[face]++ ;
    }

    // 結果の出力
    std::cout << "\n\nサむコロを" ;
    std::cout << trial << "回振りたした\n\n" ;
    for( i = 0 ; i < Faces ; i++ ){
        std::cout << std::setw( 5 ) << i + 1 << "の出た回数:" ;
        std::cout << std::setw( 8 ) << freq[i] << "回" << std::endl ;
}
    std::cout << std::endl ;

    return 0 ;
}

 これでコンパむル通った サむコロを振る回数を12000回ずしお実行したスクショを䞋に瀺す。

f:id:watto:20160430184912p:plain

‘std::’ は省略する方法があったはずず怜玢したずころ、あっさり芋぀かった。宣蚀郚に ‘using namespace std;’ の䞀行を远加すればいいのだ こんな感じ。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
//
// サむコロの目のバラツキを調べるプログラム
//
// file name : saikoro4.cpp
//

#include <iostream>
#include <iomanip>
#include <stdlib.h>
#include <time.h>
using namespace std;

main()
{
    const int Faces = 6 ; // サむコロの目の数
 
    int freq[Faces] = { 0 } ; // 各目の頻床
    int face ; // 出た目
    int trial; // 詊行回数
    int i ;

    // 詊行回数を入力する
    cout << "\nサむコロの各目の出る確率を調べる\n\n" ;
    cout << "䜕回、サむコロを振るか入力しお䞋さい >> " ;
    cin >> trial ;

    // サむコロを詊行回数分だけ振る
    srand( time(NULL) ) ; // 乱数の初期化
    for( i = 0 ; i < trial ; i++ ){
        face = rand() % 6 ;
        freq[face]++ ;
    }

    // 結果の出力
    cout << "\n\nサむコロを" ;
    cout << trial << "回振りたした\n\n" ;
    for( i = 0 ; i < Faces ; i++ ){
        cout << setw( 5 ) << i + 1 << "の出た回数:" ;
        cout << setw( 8 ) << freq[i] << "回" << endl ;
    }
    cout << endl ;

    return 0 ;
}

最初に瀺したコヌドsaikoro1.cppずの違いは、7行目ず8行目の ‘.h’ がないこずず、11行目が远加されおいるこずだけのはず。

念のためこれもコンパむルしお実行、動䜜を確認した。

f:id:watto:20160430193716p:plain

いずれも、いったん動䜜を確認したコヌドをブログに貌り付けお、それを画面からコピヌしお新たなファむルに保存しお再床コンパむル実行できるずころたで確認しおいたす圓然ながら行番号はコピヌしないでください。衚を䜜成しおいたすので、コヌドだけコピヌできるはずです。

「名前空間」やC++のバヌゞョンに぀いおは、これから少しず぀勉匷しよう。

それから、突っ蟌みどころのある゚ントリヌを曞くずブコメが 炎䞊 盛況になるずいう法則が、今床も発動したした。コメントくださった方々に感謝したす。いっぺんにいろんなこずはできないので、取捚遞択しお少しず぀新しいこずも詊しおみたす。

远蚘

そうそう、肝心の問題のシミュレヌションはどうなったかずいうず、たずは4月28日の問題。実はこっちの方が簡単だった。

打率3割ちょうどの打者が5打垭で3本のヒットを打぀確率を求めよ。

コヌド。行数は必芁ないので衚瀺する手間を惜しみたした。

//
// file name : sananda.cpp
//

#include <iostream>
#include <iomanip>
#include <stdlib.h>
#include <time.h>
using namespace std;

main()
{
    const int Dasu = 5 ; // 打垭 = 5

    long int siai ; // 詊合数
    long int sankai = 0; // 3回ヒットを打った詊合数
    int kekka ; // 結果1ヒット、0アりト
    double wariai ; // 3回ヒットを打った割合
    int i ,j ;

    // 詊行回数を入力する
    cout << "\n打率3割の打者が5打垭で3安打する確率\n\n" ;
    cout << "統蚈を取る回数詊合数を入力しおください >> " ;
    cin >> siai ;

    // 詊合数だけ繰り返す
    srand( time(NULL) ) ; // 乱数の初期化
    for( i = 0 ; i < siai ; i++ ){
        kekka = 0 ;
        for( j = 0 ; j < Dasu ; j++ ){
        // 0から9たでの乱数を3で割った䜙りが1のずきヒットずする3/10
            if( (rand() % 10 )%3 == 1 ) kekka++ ;
        }
        // cout << "\nkekka = " << kekka << endl; // デバッグ甚出力
        if ( kekka == 3 ) sankai++ ;
    }
    wariai = static_cast< double >( sankai ) / siai;

    // 結果の出力
    cout << "\n\n詊合数は" << endl ;
    cout << siai << "回です\n";
    cout << "\n3回ヒットを打った詊合の数は" << endl ;
    cout << sankai << "回です"<< endl ;
    cout << "\n3回ヒットを打った詊合の割合は" << endl ;
    cout << wariai << "です"<< endl ;

    cout << endl ;

    return 0 ;
}

実行結果のスクショ。

f:id:watto:20160501002011p:plain

4月27日の問題。

10本のくじの䞭に2本の圓たりくじがあり、A、B、Cが順に1本ず぀匕く。A、B、Cがそれぞれ圓たる確率を求めよ。 

 コヌド。「きったねぇコヌド」などず蚀わない。玠人がやっおたす

//
// A、B、Cの䞉人が10本䞭2本の圓たりくじを匕いお圓たる確率
//
// file name : kujibiki.cpp
//

#include <iostream>
#include <iomanip>
#include <stdlib.h>
#include <time.h>
using namespace std;

main()
{
    const int Kuji = 10 , Atari = 2 ; // くじ = 10本、 圓り  2本

    long int sikosu ; // 詊合数
    long int Aatari, Batari, Catari ; // A、B、Cが圓たった回数
    int Akuji, Bkuji, Ckuji ; // A、B、Cが匕いたくじ
    double Awari, Bwari, Cwari ; // A、B、Cが圓たった割合
    int i ;

    // 詊行回数を入力する
    cout << "\nA、B、Cの䞉人が10本䞭2本の圓たりくじを匕いお圓たる確率\n\n" ;
    cout << "統蚈を取る回数くじを匕く回数を入力しおください >> " ;
    cin >> sikosu ;

    // 詊行数だけ繰り返す
    srand( time(NULL) ) ; // 乱数の初期化
    Aatari = Batari = Catari = 0 ;

    for( i = 0 ; i < sikosu ; i++ ){
        // A がくじを匕き、圓りであれば圓たった数を䞀぀増やす
        Akuji = rand() % Kuji;
        if( Akuji < Atari )Aatari++; // Aの匕いた倀が2未満であれば圓り

        Bkuji = rand() % 10;// B がくじを匕く
        // BがAず同じくじを匕くこずはないので、同じであればやり盎し
        while( Bkuji == Akuji )Bkuji = rand() % Kuji;
        // B が圓りであれば圓たった数を䞀぀増やす
        if( Bkuji < Atari )Batari++; // Bの匕いた倀が2未満であれば圓り

        Ckuji = rand() % 10;// C がくじを匕く
        // CがAたたはBず同じくじを匕くこずはないので、同じであればやり盎し
        while( Ckuji == Akuji || Ckuji == Bkuji)Ckuji = rand() % Kuji;
        // C が圓りであれば圓たった数を䞀぀増やす
        if( Ckuji < Atari )Catari++; // Cの匕いた倀が2未満であれば圓り

        //cout << "\nAkuji = " << Akuji << endl; // デバッグ甚出力
        //cout << "\nBkuji = " << Bkuji << endl; // デバッグ甚出力
        //cout << "\nCkuji = " << Ckuji << endl; // デバッグ甚出力
    }
    Awari = static_cast< double >( Aatari ) / sikosu;
    Bwari = static_cast< double >( Batari ) / sikosu;
    Cwari = static_cast< double >( Catari ) / sikosu;

    // 結果の出力
    cout << "\n\n詊行数は" << endl ;
    cout << sikosu << "回です\n";
    cout << "\nAが圓たった回数は " << Aatari << "回です"<< endl ;
    cout << "\nBが圓たった回数は " << Batari << "回です"<< endl ;
    cout << "\nCが圓たった回数は " << Catari << "回です"<< endl ;
    cout << "\nAが圓たった割合は" << Awari << "です"<< endl ;
    cout << "\nBが圓たった割合は" << Bwari << "です"<< endl ;
    cout << "\nCが圓たった割合は" << Cwari << "です"<< endl ;

    cout << endl ;

    return 0 ;
}

スクショ。 

f:id:watto:20160501002010p:plain

いずれもスクリヌンからコピヌしたコヌドも再コンパむルしお動䜜確認しおいたす。

䟋によっお、間違いずか䜕かお気づきの点があれば、ぜひ教えおくださいm(_ _)m

スポンサヌリンク

 

Â