C 언어로 동적 메모리(dynamic memory)를 할당빋으려면 malloc() 함수나 calloc() 함수를 사용하고, 해제할 때는 free() 함수를 사용한다.

C++ 언에서도 이를 사용해도 되지만 메모리 할당과 관리를 객체의 생성과 소멸 과정 중에 혹은 함수의 호출과 리턴의 과정 중에 프로그래머가 일일이 간섭하려면 귀찮기도 하고, 잠간의 실수로, 심각한 버그가 발생하여 치명적인 결함이 생길 수도 있다.

C++ 언어에서는 배열의 메모리 할당과 해제를 C 언어 보다 좀  더 안전하고 편하게 해 주는

new 타입[] 과  delete[] 포인터변수 형태의  구문이 있다.

예를 들어, 부동소수점수 double 타입의 값을 10개 저장하는 공간을 할당받고 해제하는 구문의 예는 다음과 같다.

 

    double *my_arr = new double[10] { 1, 2, 3 };

    ...........적당히 사용...................

    delete[] my_arr;

 

혹은

 

    double *my_arr = new double[10];

    my_arr[0] = 1;

    my_arr[1] = 2;

    my_arr[2] = 3;

    ...........적당히 사용...................

    delete[] my_arr;

 

그런데 가끔씩 배열의 크기를 변경헤야 하는 경우가 있는데,

이럴 때는 다음 예를 상황에 맞게 수정하여 쓰면 된다.

matrix 형태의 배열을 취급하는 예도 포함되어 있는 소스이다.

 

// Filename: TestResizeOfArray01.cpp
//
// Compile: g++  -o TestResizeOfArray01 TestResizeOfArray01.cpp
// Execute: ./TestResizeOfArray01
//     Or
// Compile: cl TestResizeOfArray01.cpp /EHsc /utf-8
// Execute: TestResizeOfArray01
// Output:
//     Original size. m = 5
//     (sizeof(data) / sizeof(int)) = 2
//     [ 1  2  3  0  0 ]
//
//     Changed size. m = 10
//     (sizeof(data) / sizeof(*data)) = 2
//     [ 1  2  3  0  0  0  0  0  0  0 ]
//
//
//     Original size. m = 3, n = 4
//     (sizeof(data) / sizeof(int)) = 2
//     [[    1    2    3    1  ]
 //     [    2    3    4    2  ]
 //     [    1    0    0    0  ]]
//
//     Changed size. m = 6, n = 8
//     (sizeof(data) / sizeof(*data)) = 2
//     [[    1    2    3    1    0    0    0    0  ]
//      [    2    3    4    2    0    0    0    0  ]
//      [    1    0    0    0    0    0    0    0  ]
//      [    0    0    0    0    0    0    0    0  ]
//      [    0    0    0    0    0    0    0    0  ]
//      [    0    0    0    0    0    0    0    0  ]]
//
// Data: 2021.02.23 ~ 2021.02.24
//
// Copyright 2021 (C) pkim (_AT_) scripts (_DOT_) pe (_DOT_) kr

#include <stdlib.h>
	
#include <iostream>
#include <iterator>   // for std::size
#include <algorithm> // for copy
#include <array>
#include <iomanip>

void resize(int*& a, size_t& n)
{
   size_t new_n = 2 * n;
   int* new_a = new int[new_n];

   for (size_t i = 0; i < new_n; i++)
   {
       new_a[i] = (int) 0;
   }

   std::copy(a, a + n, new_a);
   delete[] a;
   a = new_a;
   n = new_n;
}

void print1DArray(int *data, size_t n)
{
    std::cout << "[";
    for (size_t i = 0; i < n; i++)
    {
        std::cout << " " << data[i] << " " ;
    }
    std::cout << "]" <<std::endl;
}

void test1DArray()
{
    size_t m = 5;
    int *data = new int[5] { 1, 2, 3 };

    std::cout << "Original size. m = " << m << std::endl;
    std::cout << "(sizeof(data) / sizeof(int)) = " << (sizeof(data) / sizeof(int)) << std::endl;
    print1DArray(data, m);
    std::cout << std::endl;

    resize((int *&)data, m);

    std::cout << "Changed size. m = " << m << std::endl;
    std::cout << "(sizeof(data) / sizeof(*data)) = " << (sizeof(data) / sizeof(*data)) << std::endl;
    print1DArray(data, m);
    std::cout << std::endl;
    std::cout << std::endl;
}

 resize2D(int*& a, size_t& m, size_t& n)
{
   size_t new_m= 2 * m, new_n = 2 * n, i = 0;
   int* new_a = new int[new_m * new_n];

   for (i = 0; i < new_n*new_m; i++)
   {
       new_a[i] = (int) 0;
   }

   for (i = 0; i < m; i++)
   {
       std::copy(a + i*n, a + i*n + n, new_a + i*new_n);    // copy(a[i], a[i] + 100, new_a[i]);
   }

   delete[] a;
   a = new_a;
   m = new_m;
   n = new_n;
}

void print2DArray(int *data, size_t m, size_t n)
{
    std::cout << "[[ " ;
    if ( m == 0)
    {
      	   std::cout << "]]" << std::endl;
      	   return;
    }

	if (m > 0)
	{
           for (size_t j = 0; j < n; j++)
           {
               std::cout<< " " << std::setw(3) << data[j] << " " ;
           }
           if (m > 1)
           {
               std::cout << " ]"  << std::endl;
           }
           else
           {
               std::cout << " ]]"  << std::endl;
           }

           if (m > 1)
           {
                for (size_t i = 1; i < m; i++)
                {
                	std::cout << " [ " ;
                    for (size_t j = 0; j < n; j++)
                    {
                        std::cout << " "<< std::setw(3) << data[i*n + j] << " " ;
                    }

     	              if (i < m - 1)
    	              {
                         std::cout << " ]"  << std::endl;
                    }
    	              else
    	              {
                         std::cout << " ]]"  << std::endl;
                     }
                }
           }
    }
}

void test2DArray()
{
    size_t m = 3;
    size_t n = 4;
    int *data = new int[m*n]  {  1, 2, 3 , 1, 2, 3, 4 , 2, 1 };    // { { 1, 2, 3 }, { 1, 2, 3, 4 }, {2, 1} };

    std::cout << "Original size. m = " << m << ", n = " << n << std::endl;
    std::cout << "(sizeof(data) / sizeof(int)) = " << (sizeof(data) / sizeof(int)) << std::endl;
    print2DArray((int *)&data[0], m, n);
    std::cout << std::endl;

    resize2D((int *&)data, m, n);

    std::cout << "Changed size. m = " << m << ", n = " << n << std::endl;
    std::cout << "(sizeof(data) / sizeof(*data)) = " << (sizeof(data) / sizeof(*data)) << std::endl;
    print2DArray((int *)&data[0], m, n);
    std::cout << std::endl;
}

int main()
{
    test1DArray();
    test2DArray();
    return 0;
}
Posted by Scripter

댓글을 달아 주세요

Visual Studio 2019 와 MSYS2 MinGW64 에서 테스트 된 소스입니다.

 혹시 MinGW 에서 컴파일되지 않으면

$ packman -S mpfr

명령으로 mpfr 라이브러리를 설치하고 컴파일하면 된다.

 

// Filename: calcGammaFn.c
//
// Compile: gcc -o calcGammaFn calcGammaFn.c -lmpfr -lgmp
// Execute: ./calcGammaFn
//     Or
// Compile: cl calcGammaFn.c /I. mpfr.lib
// Execute: calcGammaFn
//
// Date: 2021.01.28


#include <stdio.h>
#include <math.h>    // for log(10)
#include <mpfr.h>

int main()
{
  mpfr_t x; 
  int i, inex;

  mpfr_set_emin (-41);
  mpfr_init2 (x, 42);

  for (i = 1; i <= 17; i++)
  {
      mpfr_set_ui (x, i, MPFR_RNDN);
      inex = mpfr_gamma (x, x, MPFR_RNDZ);      
      mpfr_subnormalize (x, inex, MPFR_RNDZ);
      mpfr_dump (x);
  }

  printf("\n");

  for (i = 1; i <= 17; i++)
  {
      mpfr_set_ui (x, i, MPFR_RNDN);
      inex = mpfr_gamma (x, x, MPFR_RNDZ);
      mpfr_printf("Gamma(%2d) = %2d! = %Rf\n", i, i - 1, x);
  }

  printf("\n");

  for (i = 1; i <= 17; i++)
  {
      mpfr_set_ui (x, i, MPFR_RNDN);
      inex = mpfr_lngamma (x, x, MPFR_RNDZ);
      mpfr_printf("LogGamma(%2d) = Log(%2d!) = %Rf\n", i, i - 1, x);
  }

  printf("\n");

 double t10 = log(10.0);
 printf("log(10) = %f\n", t10);
 
  printf("\n");

  for (i = 1; i <= 17; i++)
  {
      mpfr_set_ui (x, i, MPFR_RNDN);
      inex = mpfr_lngamma (x, x, MPFR_RNDZ);      
      inex = mpfr_div_d(x, x, t10,  MPFR_RNDZ);
      mpfr_printf("Log10Gamma(%2d) = Log10(%2d!) = %Rf\n", i, i - 1, x);
  }

  mpfr_clear (x);
  
  return 0;
}

/*
Output:
LogGamma( 1) = Log( 0!) = 0
LogGamma( 2) = Log( 1!) = 0
LogGamma( 3) = Log( 2!) = 0.693147
LogGamma( 4) = Log( 3!) = 1.791759
LogGamma( 5) = Log( 4!) = 3.178054
LogGamma( 6) = Log( 5!) = 4.787492
LogGamma( 7) = Log( 6!) = 6.579251
LogGamma( 8) = Log( 7!) = 8.525161
LogGamma( 9) = Log( 8!) = 10.604603
LogGamma(10) = Log( 9!) = 12.801827
LogGamma(11) = Log(10!) = 15.104413
LogGamma(12) = Log(11!) = 17.502308
LogGamma(13) = Log(12!) = 19.987214
LogGamma(14) = Log(13!) = 22.552164
LogGamma(15) = Log(14!) = 25.191221
LogGamma(16) = Log(15!) = 27.899271
LogGamma(17) = Log(16!) = 30.671860

log(10) = 2.302585

Log10Gamma( 1) = Log10( 0!) = 0
Log10Gamma( 2) = Log10( 1!) = 0
Log10Gamma( 3) = Log10( 2!) = 0.301030
Log10Gamma( 4) = Log10( 3!) = 0.778151
Log10Gamma( 5) = Log10( 4!) = 1.380211
Log10Gamma( 6) = Log10( 5!) = 2.079181
Log10Gamma( 7) = Log10( 6!) = 2.857332
Log10Gamma( 8) = Log10( 7!) = 3.702431
Log10Gamma( 9) = Log10( 8!) = 4.605521
Log10Gamma(10) = Log10( 9!) = 5.559763
Log10Gamma(11) = Log10(10!) = 6.559763
Log10Gamma(12) = Log10(11!) = 7.601156
Log10Gamma(13) = Log10(12!) = 8.680337
Log10Gamma(14) = Log10(13!) = 9.794280
Log10Gamma(15) = Log10(14!) = 10.940408
Log10Gamma(16) = Log10(15!) = 12.116500
Log10Gamma(17) = Log10(16!) = 13.320620
*/

 

 

 

 

 

Posted by Scripter

댓글을 달아 주세요

C 언어 또는 C++ 언어에서는 문자열 인코딩을 처리할려면 무척 애을 먹는다.

반면에 Java 언어나 Python 언어에서는 문자열 인코딩 문제가

일치 감치 해결되어 있으므로 조금만 주의하면 별 어려움이 없다.

 

우선 간단한 Python 소스를 보자.

 

# -- coding: utf=8 -*-

greetings = [
        "Hello~",         # English
        "안녕하세요?",  # Korean
        "んにちは。",   # Japanese
        "您好!"          # Chinesse
    ]
for msg in greetings:
    print(msg)
    
"""
Output:
Hello~
안녕하세요?
んにちは。
您好!
"""

 

위의 소스를 저장할 때 utf8 인코딩으로 저장하면

실행 시에 터미널 환경의 문자셋 여부에 상관없이 정상적으로 잘 출력된다,

 

그러너  C 언어나 ㅊ++ 언어의 경우레는 문자열을 처리하는 방식이 너무나 다양하여

환경에 따라 정확한 처리 방식을 찾는데 꽤 고생하게 된다.

여기에 그런 수고를 덜기 위한 (중국어 간체 때문에 다소(?) 불완전한) 팁을 소개한다.

아래의 소스는 윈도우 10 환경에서

Visual Studio 2019 의 명령줄(command line) 컴파일러 cl 및

MinGW64 의 컴파알러 g++ 로 테스트된 C++ 소스이다

 

// Filename: helloUTF8_002.cpp
//
//       This source should besaved as utf-8 file=encoding.
//
// Compile: g++ -o helloUTF8_002 helloUTF8_002.cpp
// Execute: ./helloUTF8_002
//    Or
// Compile: cl helloUTF8_002.cpp /EHsc /utf-8 /std:c++17
// Execute: helloUTF8_002.cpp
// Output:
//         Hello~
//         안녕하세요?
//         んにちは。
//         ?好!
//
// Date: 2021.01.23

#include <iostream>
#include <cstddef>
#include <locale>
#include <stdio.h>
#include <wchar.h>

int main(void)
{
    const std::wstring greetings[] = {
			L"Hello~",         // English
			L"안녕하세요?",  // Korean
			L"んにちは。",   // Japanese
			L"您好!"          // Chinesse
        };

    setlocale(LC_ALL,"");   // <--- works both on cmd of Windows 10 and mys64 terminal of Windows 10

    /////////////////////////////////////////////////
    // Get the counting of an array of wstrins
    // int size = (int) size(greetings);  // <--- works on vc++, but nor on g++
    int size = *(&greetings+1)-greetings;  
            
    for (int i = 0; i <  size; ++i)
    {
          wprintf(L"%lS\n", (wchar_t *)&(greetings[i][0]));
          /// wprintf(L"%ls\n", (wchar_t *)&(greetings[i][0]));
		 	
          // std::wcout << greetings[i] << std::endl; 
    }
	
    return 0;
}

 

 

중국어 간체 您가 정상적으로 출력되지 않는 문제점이 아직 해결되지 않았다.

문자 您를 你로 바꾸어도 마찬가지이다.

Python 소스로는 잘 출력되는 것을 보면 터미널의 폰트 문제는 아난 것 같다.

 

 

Posted by Scripter

댓글을 달아 주세요

일반적으로 C 언어로 작성된 함수를 C++ 언어에서 불러 사용하려면

extern "C" 라는 키워드가 필요하다.

C 언어의 함수 정의를 ****.h 라는 헤더 파일에 기록해 두고

이 헤더 파일응 C++ 소스에서 포함(include)하려면 몇 가지 주의할 점이 있다.

 

우선 함수의 정의가 있는 C  소스와 C 언어용 헤더 파일을 보자.

[(구현) 파일명: sayHello.c] ------------------------------------

#include <stdio.h>

void print_message(char *message) {
    printf("%s\n", message);
}

 

위는 print_message(char *) 라는 함수 하나만 달랑 구현되어 있는 C 소스 파일이다.

 

 

[(정의) 파일명: sayHello.h] ------------------------------------

#ifndef HELLO_H_INCLUDED
#define HELLO_H_INCLUDED

#ifdef __cplusplus
extern "C" {
#endif

void print_message(char *message);

#ifdef __cplusplus
}  /* end of the 'extern "C"' block */
#endif

#endif // HELLO_H_INCLUDED

 

 

위는 함수 print_message(char *) 를 다른 C 또는 C++ 소스파일에서 불러 쓸 수 있도록

그 함수의 정의를 기헉힌 헤더 파일이다. exterb "C" { ....... } 라고 힐 경우

......... 부분이 C 언어 양식이고 이를 C++ 에서 인식할 수 있도록 하는 키워드가 extern "C" 이다.

그러나 헤더 파일에 이렇게만 적어 두면 C++ 소스에서는 불러 올 순,ㄴ 있지만, C 소스에서는

불러오지 못하는 문제사 생긴다. 이를 해경하기 위해 (즉, C 소스나 C++ 소스에서 이를 불러 쓰기 위해

추가한 것이 그 위와 아래에 적어 준 

#ifdef __cplusplus
extern "C" {
#endif

...............................................

#ifdef __cplusplus
}  /* end of the 'extern "C"' block */
#endif

부분이다.

그리고 이 헤더 파일의 시작과 끝 부분에 적어 준

#ifndef HELLO_H_INCLUDED
#define HELLO_H_INCLUDED

............................................

#endif // HELLO_H_INCLUDED

부분은 이 헤더 파일이 다른 소스에 포함(include)될 경우 단 한번 만 포함되게 하는 구문이다.

 

 

 

[파일명: hello.hpp] -------------------------------------

#ifndef HELLO_HPP_INCLUDED
#define HELLO_HPP_INCLUDED

#include "sayHello.h"

#endif // HELLO_HPP_INCLUDED

 

 

위는 C++ 소소에서 포함할 헤더 파일이다.

 

 

[파일명: callSayHello.cpp] -----------------------------------

// Filename: callSayHello.cpp
//
// Compile & Link: g++ -o callSayHello callSayHello.cpp sayHello.o
// Execute: ./callSayHello
// Output:
//     Hello world!
//     Hello world!
//
//   Or
//
// Compile: cl /c sayHello.c
// Compile & Link: cl callSayHello.cpp sayHello.c /EHsc
// Execute: .\callSayHello

// Date: 2021.01.07
//

#include <iostream>
#include "hello.hpp"

using namespace std;

int main() 
{
    cout << "Hello world!" << endl;

    // print_message ("Hello world!");
    print_message ((char *)"Hello world!");
    
    return 0; 
}

 

위는 C 언어로 작성된 함수 print_message(char *) 를 불러 사용하는 C++ 소스의 내용이다.

참고로 27째 줄 // print_message ("Hello world!"); 의 주석문 표시 // 를 제거하면,

아래와 같은 컴파일 경고(warning)가 뜬다. 이 경고가 뜨더라도 컴파일되고 실행도 되지만,

그 아래 줄 처럼 (char *) 라는 캐스팅을 추가하면 경고 없이 컴파일도 잘 되고 실행도 잘 된다.

 

$ g++ -o callSayHello callSayHello.cpp sayHello.o
callSayHello.cpp: In function 'int main()':
callSayHello.cpp:27:20: warning: ISO C++ forbids converting a string constant to 'char*' [-Wwrite-strings]
   27 |     print_message ("Hello world!");

 

Posted by Scripter

댓글을 달아 주세요

C# 언어로 부동소수점수 계산할 때 실수할 수 있는 경우이다.

반복문의 탈출 조건에 저런 것을 이용하다 자칫하면

무한 반복의 늪에 빠질 수 있다.

금액 계산의 경우에 정확한 계산이 요구되기 때문에

float 타입이니 double 타입 보다는 decimal 타입을 사용하는것이

더 바람직할 것이다.

정확한 소수점수 계산을 위해 decimal 타입을 사용한 다음 C# 소스의 실행 결과를 보자.

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CalcDecimalConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Use double type:");
            Console.WriteLine("{0:F20}", 0.3 - 0.1);
            Console.WriteLine("{0}", 0.3 - 0.1 == 0.2);
            Console.WriteLine("Use Decimal type:");
            Console.WriteLine("{0:F20}", new Decimal(0.3) - new Decimal(0.1));
            Console.WriteLine("{0}", new Decimal(0.3) - new Decimal(0.1) == new Decimal(0.2));
        }
    }
}

/****************************************
Output: -------------------------
Use double type:
0.20000000000000000000
False
Use Decimal type:
0.20000000000000000000
True. . .
****************************************/

 

 

 

 

 

 

Posted by Scripter

댓글을 달아 주세요

최근에 PHP 8 릴리즈가 발표되었다.

변한 것은 여러가지 있지만, 사소한 변화 한 가지만 소개한다.

PHP 8에서는 부동소수점수 나눗셈 함수 fdiv($a, $b) 가 추가되었다.

기존의 나눗셈 $a / $b 는 나누는 수 $b 가 0일 경우 에외가 발생하지만,

IEEE 754 의 권고에 따라 0으로 나누는 경우 나누어지는 수가

양수냐 움수냐 0이냐에 따라 나눈 결과가 각각 +INF, -INF, NAN 로 된다.

PHP 7,xx 까지에는 fmod($a, $b) 함수와 intdiv($a, $b) 함수가 이미 있었는데.

여기에 보조를 맞추어 fdiv($a, $b) 가 PHP 8에 새롭게 추가되었다고 한다.

intdiv() 와 대비되는 이름 floatdiv() 으=로 할까도 고려해보았지만,

fmod() 와 대비되는 이름 fdiv() 로 정했다고 한다.

다음은 인터프리터 명령 php -a 로 실행한 예이다.

Interactive shell

php > $a = 45.3;
php > $b = 11.2;
php > $c = fdiv($a, $b);
php > echo $c;
4.0446428571429
php > echo ($a . $b);
45.311.2
php > echo ($a / $b);
4.0446428571429
php > fdiv(11, 3);
php > echo fdiv(11, 3);
3.6666666666667
php > echo 11 / 3;
3.6666666666667
php > 11 / 0;

Warning: Uncaught DivisionByZeroError: Division by zero in php shell code:1
Stack trace:
#0 {main}
  thrown in php shell code on line 1
php > echo fdiv(11, 0);
INF
php > echo fdiv(-11, 0);
-INF
php > echo fdiv(-0, 0);
NAN
php > echo fdiv(0, 0);
NAN
php > echo fmod(-11, 0);
NAN
php > echo intdiv(-11, 3);
-3
php > echo -11/ 3;
-3.6666666666667
php > echo fmod(-11, 3);
-2
php > echo fdiv(-11 - fmod(-11, 3), 3);
-3
php > echo fdiv(22 - fmod(22, 3), 3);
7
php > echo fdiv(10, 0);
INF
php > echo fdiv(-1.2, 0);
-INF
php > echo fdiv(-0, 0);
NAN
php > echo (fdiv(12 - 5, 1 - 1) == INF);
1
php > echo (fdiv(-12 + 5, 1 - 1) == INF);
php > echo (fdiv(-12 + 5, 1 - 1) == INF);
php > echo (fdiv(-12 + 5, 1 - 1) == -INF);
1
php > echo (fdiv(-5 + 5, 1 - 1) == -INF);
php > echo (fdiv(-5 + 5, 1 - 1) == INF);
php > echo (fdiv(-5 + 5, 1 - 1) == NAN);
php > echo (fdiv(0, 0) == NAN);
php > echo (is_nan(fdiv(0, 0)));
1
php > echo (is_nan(fdiv(1, 0)));
php > echo (is_infinite(fdiv(1, 0)));
1
php > echo (is_finite(fdiv(1, 0)));
php > echo (is_finite(fdiv(1, 2)));
1
php > echo (is_infinite(fdiv(-1, 0)));
1
php > echo (is_finite(fdiv(-1, 0)));

   

관련 자료:

[1] PHP 홈페이지

[2] PHP8 다운로드

[3] PHP7과 PHP8의 간단 비교

[4] PHP8의 새 기능 몇 가지

 

 

 

 

Posted by Scripter

댓글을 달아 주세요

wx,html 모듈을 이용하는 첫째 소스는 http 프로토콜만 지원하고 https 프로토콜은 지원하지 않습니다.

그러나,  wx,html2 모듈을 이용하는 둘째 소스는 http 프로토콜과 https 프로토콜 모두를 지원합니다.

셋째 소스는 둘째 소스에 네비게이터(뒤로 가기, 앞으로 가기) 가능을 추가한 소스입니다.

[1] wx.html 모듈을 이용한 소스: simple_html_browser.py

# -*- coding: utf-8 -*-
#!/usr/bin/env python

# Filename: simple_html_browser.py
# Execute: python simple_html_browser.py
#    or
# Execute: ./simple_html.browser.py

import wx
import wx.html

class MyHtmlDialog(wx.Dialog):
    def __init__(self, parent, title):
        wx.Dialog.__init__(self, parent, -1, title, size=(600,400))
        html = wx.html.HtmlWindow(self)
        if "gtk2" in wx.PlatformInfo:
            html.SetStandardFonts()

        wx.CallAfter(html.LoadPage, "http://www.google.com")

if __name__ == "__main__":
    app = wx.App()
    dlg = MyHtmlDialog(None, "Simple HTML Browser")
    dlg.ShowModal()
    dlg.Destroy()
    app.MainLoop()

 

[2] wx.html2 모듈을 이용한 소스: simple_html2_browser.py

# -*- coding: utf-8 -*-
#!/usr/bin/env python

# Filename: simple_html2_browser.py
# Execute: python simple_html2_browser.py
#    or
# Execute: ./simple_html2_browser.py

import wx
import wx.html2

class MyHtml2Dialog(wx.Dialog):
    def __init__(self, parent, title):
        wx.Dialog.__init__(self, parent, -1, title, size=(600,400))
        html = wx.html2.WebView.New(self)
        if "gtk2" in wx.PlatformInfo:
            html.SetStandardFonts()

        wx.CallAfter(html.LoadURL, "https://www.google.com")

if __name__ == "__main__":
    app = wx.App()
    dlg = MyHtml2Dialog(None, "Simple HTML2 Browser")
    dlg.ShowModal()
    dlg.Destroy()
    app.MainLoop()

 

 

[3] 위의 둘째 것을 쓸 만 한하게 수정한 웹 브라우저 소스: simple_browser_wk.py

# -*- coding: utf-8 -*-
#!/usr/bin/env python

# Filename: simple_browser_wk.py
#
# Execute: python3 simple_browser_wk.py
#    or
# Execute: pythonw simple_browser_wk.py
#    or
# Execute: ./simple_browser_wk.py
#
# Date: 2020.11.29   Version 0.0.4

import wx 
import wx.html2 

class MyBrowser(wx.Frame): 
    def __init__(self, parent, title): 
        super(MyBrowser, self).__init__(parent, title = title,size = (800,400))  
        sizer = wx.BoxSizer(wx.VERTICAL) 

        hsizer = wx.BoxSizer(wx.HORIZONTAL) 
        emptyText = wx.StaticText(self, -1 , "     ", (10, 10), (10, -1))
        emptyText.SetBackgroundColour('#DDDDDD')
        self.addrText = wx.TextCtrl(self, wx.ID_ANY, value="", size=(300, 30))
        self.addrText.SetFont( wx.Font(12, wx.ROMAN, wx.NORMAL, wx.NORMAL)  )
        self.addrText.SetBackgroundColour('white')
        self.addrText.Bind(wx.EVT_CHAR, self.OnCharEvent)
        self.prevButton = wx.Button(self, 1, '<', (10, 10), (20, -1))
        self.prevButton.Bind(wx.EVT_BUTTON, self.OnPrevButton, id=1)
        self.nextButton = wx.Button(self, 1, '>', (10, 10), (20, -1))
        self.nextButton.Bind(wx.EVT_BUTTON, self.OnNextButton, id=1)
        self.homeButton = wx.Button(self, 1, 'Home', (10, 10), (80, -1))
        self.homeButton.Bind(wx.EVT_BUTTON, self.OnHomeButton, id=1)
        self.exitButton = wx.Button(self, 1, 'Exit', (10, 10), (80, -1))
        self.exitButton.Bind(wx.EVT_BUTTON, self.OnCloseButton, id=1)

        hsizer.Add(self.exitButton, 3, wx.EXPAND, 10) 
        hsizer.Add(self.homeButton, 3, wx.EXPAND, 10) 
        hsizer.Add(self.prevButton, 1, wx.EXPAND, 10) 
        hsizer.Add(self.nextButton, 1, wx.EXPAND, 10) 
        hsizer.Add(self.addrText, 30, wx.EXPAND, 10) 
        hsizer.Add(emptyText, 1, wx.EXPAND, 10) 
        sizer.Add(hsizer, 1, wx.EXPAND, 10) 
        self.browser = wx.html2.WebView.New(self) 
        sizer.Add(self.browser, 20, wx.EXPAND, 10) 
        self.SetSizer(sizer) 
        self.SetSize((800, 700)) 
        self.Bind(wx.html2.EVT_WEBVIEW_NAVIGATED, self.OnNavigated)
        self.OpenWebPage("https://www.google.com")

    def OnCharEvent(self, event):
        keycode = event.GetKeyCode()
        controlDown = event.CmdDown()
        altDown = event.AltDown()
        shiftDown = event.ShiftDown()

        if (not shiftDown) and (not altDown) and (not controlDown) and keycode == 13 :      # [Enter] key
            self.OpenWebPage(self.addrText.GetValue())

    def OnCloseButton(self, event):
        self.Destroy()
        quit()

    def OnHomeButton(self, event):
        self.OpenWebPage("https://scripting.tistory.com")
        event.Skip()

    def OnPrevButton(self, event):
         if self.browser.CanGoBack():
             self.browser.GoBack()
         event.Skip()

    def OnNextButton(self, event):
         if self.browser.CanGoForward():
             self.browser.GoForward()
         event.Skip()

    def OnNavigated(self, event): 
        self.addrText.SetLabel(self.browser.CurrentURL)
        # print(self.browser.CurrentTitle)
        self.SetTitle("SimpleBrowser - {0}".format(self.browser.CurrentTitle))
        event.Skip()

    def OpenWebPage(self, addr): 
        self.browser.LoadURL(addr)
        self.SetTitle("Simpl Browser")
        self.addrText.SetLabel(addr)
        self.Show() 


if __name__ == "__main__":	
    ex = wx.App() 
    f = MyBrowser(None,'Simple Btowser') 
    f.Show()
    ex.MainLoop()
    

 

 

 

 

 

Posted by Scripter

댓글을 달아 주세요

최근(2020년 11월 21일)에 릴리즈 4.1.1이 발표되었습니다.

C++ 언어로 작성된 wxPython은 Python2 와 Python3  모두에 사용가능한

Python의 GUI 래퍼(wrapper)입니다.

 

[1] wxPython 홈페이지

[2] wxPython 4.1.1 설치하기

   처음 설치 명령: pippip install wxPython==4.1.1

   업그레이드 명령: pippip install --upgrade wxPython==4.1.1

 

[3] 설치 후 버전 확인하기

>>> import wx
>>> wx.version()
'4.1.1 msw (phoenix) wxWidgets 3.1.5'
>>> wx.__version__
'4.1.1'

[4] 설치된 wxPython의 버전을 확인하는 GUI 소스

# -*- coding: utf-8 -*-
#!/usr/bin/env python

# Filename: versionGUI.py
#
# Date: 2020.11.28

import wx


class VersionDialog(wx.Dialog):
    def __init__(self, parent, title):
        wx.Dialog.__init__(self, parent, -1, title, size=(475, 240))
        self.sbox = wx.StaticBox(self, -1, 'Version Information', (10, 20), size=(440, 100))        
        self.sbox.SetFont( wx.Font(10, wx.ROMAN, wx.NORMAL, wx.NORMAL)  )
        
        font = wx.Font(11, wx.ROMAN, wx.NORMAL, wx.NORMAL) 
        a = wx.StaticText(self, -1 , "wx.version() = {0}".format(wx.version()), (15, 60))
        a.SetFont( font )
        b = wx.StaticText(self, -1 , "wx.__version__ = %s" % wx.__version__, (15, 85))
        b.SetFont( font )
        
        wx.StaticLine(self, 1,  (15, 145), (430, 2))
        wx.Button(self, 1, 'Okay', (340, 165), (100, -1))
        self.Bind(wx.EVT_BUTTON, self.OnClose, id=1)

    def OnClose(self, event):
        self.Destroy()
        quit()


if __name__ == "__main__":
    app = wx.App()
    dia = VersionDialog(None, "Version of wxPython")
    dia.ShowModal()
    if dia != None:
        dia.Destroy()
    app.MainLoop()

실행 결과:

 

 

 

Posted by Scripter

댓글을 달아 주세요

아래의 글은 MS의 유닛 테스트 적성하기 문서에 오류가 있어 바로 잡기 위한 글입니다.

유닛 테스트하는 도구로는 MSTest, NUnit, xUnit 등 몇 가지가 있는데

이 중에 MSTest를 이용하여 유닛 테스트하는 예를 작성해 보고자 한다.

컨솔 창에 Hello World! 라는 문구가 정상적으로 출력되는지 알아보는 유닛 테스트이다.

Visual Studio 2019 의 메뉴에서 "파일(F)" -> "새로 만들기" -> "프로젝트(P)"를 선택하고, "새 프로젝트 만들기" 창에서아래와 같이 선택하고 "다음(N)" 버큰을 클릭한다.

<새 프로젝트 만들기 창>

 

다음에 프로젝트 이름과 폴토를 선택하는 창에서 아래와 같이 "프로젝트 이름(N)" 입력 난에 HelloWorldTests 라고 입력하고, 그 아래 항목 "위치(L)" 난에서 적당한 폴더를 선택해 준다.

그리고 "다름(N)" 바튼을 클릭하면  Visual Studio 가 소스 작성하는 환경으로 된다.

 

<새 프로젝트 구성 창>

그리고 "다름(N)" 바튼을 클릭하면 Visual Studio 가 소스 작성하는 환경으로 된다.

이제 C# 소스 UnitTest1.cs 를 작성하는 곳의 소스를 다음 처럼 작성한다.

using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.IO;
using System;

namespace HelloWorldTests
{
    [TestClass]
    public class UnitTest1
    {
        private const string Expected = "Hello World!";
        [TestMethod]
        public void TestMethod1()
        {
            using (var sw = new StringWriter())
            {
                Console.SetOut(sw);
                HelloWorldTests.Program.SayHello();

                var result = sw.ToString().Trim();
                Assert.AreEqual(Expected, result);
            }
        }
    }

    class Program
    {
        public static void SayHello()
        {
            Console.WriteLine("Hello World!");
        }
    }
}

 

소스기 잘 작성되었으면 Visual Studio 의 메뉴에서 "빌드(B)" -> "솔루션 다시 빌드(R)" 을 선택하여

솔루션을 빌드한다.

빌드가 성공되면 아래 그림 처럼 Visual Studio의 메뉴에서 "테스트(S)" -> "테스트 탐색기(T)"를 선택한다.

<테스트 탐색기(T) 선택 메뉴>

 

아래의 테스트 탐색기 창의 도구바 메뉴 중에 가장 좌측에 있는 도구 버튼을 누르고 참시 기다리면 성공한 결과가 아래 처럼 나온다.

 

<유닛 테스트가 성공한 결과>

Posted by Scripter

댓글을 달아 주세요

 

VisualStudio 2019 의 메뉴에서 "도구(T)" -> "명령줄(L)" -> "개발자 PowerShell(P)" 을 선택하거나

윈도우 10에서 '윈도우 키' + 'R' 을 누른 다음 명령어 입력 난에 powershell 을 입력하여

나타난 PowerShell 창에서 다음을 입력한다.

 

function multarrays($a, $b) {
    $n,$m,$p = ($a.Count - 1), ($b.Count - 1), ($b[0].Count - 1)
    if ($a[0].Count -ne $b.Count) {throw "Multiplication impossible"}
    $c = @(0)*($a[0].Count)
    foreach ($i in 0..$n) {    
        $c[$i] = foreach ($j in 0..$p) { 
            $sum = 0
            foreach ($k in 0..$m){$sum += $a[$i][$k]*$b[$k][$j]}
            $sum
        }
    }
    $c
 }
 
function show($a) { $a | foreach{"$_"}}

 

계속해서 다음을 입력한다.

$a = @(@(1,2),@(3,4))
$b = @(@(5,6),@(7,8))
$c = @(5,6)

 

이제 다음을 한 줄씩 입력하면 각각의 곱셈 결과가 표시된다.

"`$a ="; show $a
""
"`$b ="; show $b
""
"`$c ="; $c
""
"`$a * `$b ="; show (multarrays $a $b)
""
"`$a * `$c ="; show (multarrays $a $c)

 

 

[참고 자료] Rosetta Code - Matrix Mulriplication

Posted by Scripter

댓글을 달아 주세요