素数の一覧を表示する

VC++ でエラトステネスのふるいを使って 1000 以下の素数を求めて表示します。

前田稔(Maeda Minoru)の超初心者のプログラム入門

【ヒント】

  1. 素数とは「2以上の1と自分自身以外に約数を持たない整数」のことを言います。
    素数は「エラトステネスのふるい」を使って求めます。
    1. step 1: 2からnまでのすべての整数を「ふるい」に入れる
    2. step 2: 「ふるい」に入っている数の中で最小の数を取り出し「素数」に加える。
    3. step 3: この数の倍数を全て「ふるい」から除く。
    4. step 4: 「ふるい」が空になるまで、step 2,3 を繰り返す。
  2. この考え方に基づいてプログラムしたのが SetSosu() 関数です。
    tbl[1000] に1000以下の素数を求めて格納します。
    求めた素数は、印字の時に便利なように tbl[] の先頭から詰めて下さい。
    SetSosu() の関数値として求めた素数の個数をリターンします。
        int     tbl[1000];
    
        int     SetSosu(void)
        {   int     i,j;
                :
                :
            return(j);      //素数の個数
        }
        
  3. 1000までの素数の数は168個です。
    素数を表示する前に「168個の数字を一行に10個ずつ」並べて表示してみましょう。
        void    ShowSosu(HDC hdc)
        {   int     n;
            char    str[8];
    
            for(n=0; n<168; n++)
            {   wsprintf(str,"%5d",n);
                TextOut(hdc,(n%10)*70+50,n/10*28+60,str,5);
            }
        }
        

プロジェクトの設定

  1. 新規プロジェクトを作成して 1000 までの素数を求める領域と求めた素数の個数を格納する領域を定義します。
        // グローバル変数 :
        HINSTANCE hInst;
        TCHAR szTitle[MAX_LOADSTRING];
        TCHAR szWindowClass[MAX_LOADSTRING];
        int     tbl[1000];
        int     cnt;
        
  2. 素数を求める関数と画面に表示する関数と罫線を描画する関数を定義します。
    自動的に生成される「関数の宣言」に続いて以下のソースコードを追加して下さい。
    関数のプロトタイプを宣言して、続いて関数の本文を記述します。
        // このコード モジュールに含まれる関数の宣言を転送します :
        ATOM                MyRegisterClass(HINSTANCE hInstance);
        BOOL                InitInstance(HINSTANCE, int);
        LRESULT CALLBACK    WndProc(HWND, UINT, WPARAM, LPARAM);
        LRESULT CALLBACK    About(HWND, UINT, WPARAM, LPARAM);
        int                 SetSosu(void);
        void                ShowSosu(HDC hdc);
        void                Keisen(HDC hdc);
        // 関数の本文を記述します
                :
                :
        
  3. WndProc() に WM_CREATE: を追加して SetSosu() を呼び出すコードを記述します。
    WM_CREATE: にはウインドウが生成されたときに制御が渡されます。
    アプリケーションの初期化や最初に一度だけ実行したい処理はここで行います。
        switch (message)
        {
            case WM_CREATE:
                cnt= SetSosu();
                break;
        
  4. WM_PAINT に素数の一覧を表示するコードを追加します。
    実際の描画は ShowSosu() で行うので、ここでは関数を呼ぶだけです。
        case WM_PAINT:
            hdc = BeginPaint(hWnd, &ps);
            // TODO: 描画コードをここに追加してください...
            ShowSosu(hdc);
            EndPaint(hWnd, &ps);
            break;
        
  5. 描画される大きさに合わせてウインドウサイズを決めています。
    実行環境によっては、ウインドウサイズや罫線が合わないかも知れません。
    環境に合わせてソースコードを修正して下さい。
        hWnd = CreateWindow(szWindowClass, szTitle,
                     WS_CAPTION | WS_OVERLAPPED | WS_SYSMENU,
                     0, 0, 800, 600,
                     NULL, NULL, hInstance, NULL);
        
  6. [デバッグ][デバッグなしで開始]を選択して、ビルドに続いて実行を行います。
    ページ先頭の画像が表示されたら完成です。

【演習】

関数を作成して、プログラムを完成して下さい。
なるべく解答を見ないで自分の力で作成して下さい。

関数のソースコード

超初心者の方のために関数のソースコードを掲載します。 (^_^;)

//★ tbl[1000] に素数を格納する
int     SetSosu(void)
{   int     i,j;
    for(i=0; i<1000; i++)   tbl[i]= i;
    tbl[1]= 0;
    for(i=2; i<33; i++)
        for(j=i*2; j<1000; j+=i)   tbl[j]= 0;
    for(i=j=0; i<1000; i++)
    {   if (tbl[i]!=0)
        {   tbl[j]= i;
            j++;
        }
    }
    return(j);
}

//★ 文字列を表示する
void    ShowSosu(HDC hdc)
{   int     n;
    char    str[8];

    Keisen(hdc);
    TextOut(hdc,10,10,"素数を求めて表示する", 20);
    for(n=0; n<cnt; n++)
    {   wsprintf(str,"%5d",tbl[n]);
        TextOut(hdc,(n%10)*70+50,n/10*28+60,str,5);
    }
}

//★ 罫線を引く
void    Keisen(HDC hdc)
{   HPEN    hPen,hOldPen;
    int     i;

    hPen= CreatePen(PS_SOLID,3,RGB(180,180,180));
    hOldPen= (HPEN)SelectObject(hdc,hPen);
    for(i=0; i<18; i++)
    {   MoveToEx(hdc,26,i*28+57,NULL);
        LineTo(hdc,725,i*28+57);
    }
    for(i=0; i<11; i++)
    {   MoveToEx(hdc,i*70+26,57,NULL);
        LineTo(hdc,i*70+26,532);
    }
    SelectObject(hdc,hOldPen);
    DeleteObject(hPen);
}

超初心者のプログラム入門(Win32API C++)