Boost Library 1.75.0 을 설치하고

Visual Studio 2019 의 명령행 컴파일러 cl 로 컴파일하였다.

컴파일하기 전에 미리 환경변수 BOOST_LIB_PATH 와 MPIR_LIB_PATH 를 각각

Boost Library 와 MPIR Library 가 있는 경로로 설정해 놓아야 한다.

 

/*
 * Filename: CalculateAreaOfDiskWithBoosLibrary.cpp
 *
 *       Purpose: Test floating point numbers of arbitrary precision.
 *
 * Compile: cl CalculateAreaOfDiskWithBoosLibrary.cpp /I%BOOST_LIB_PATH% /I%MPIR_LIB_PATH% /EHsc /utf-8 MPIR_LIB_PATHmpir.lib
 * Execute: CalculateAreaOfDiskWithBoosLibrary
 *
 * Date: 2021.03.29
 * Revised Author: pkim ((AT)) scripts ((DOT)) pe ((DOT)) kr 
 *
 * See: www.boost.org/doc/libs/1_56_0/libs/multiprecision/doc/html/boost_multiprecision/tut/floats/gmp_float.html
 */
 
#include<iostream>
#include <boost/multiprecision/cpp_bin_float.hpp>
#include <boost/multiprecision/cpp_dec_float.hpp>
#include <boost/math/constants/constants.hpp>

using boost::multiprecision::cpp_dec_float_50;
using boost::multiprecision::cpp_dec_float_100;
using boost::multiprecision::cpp_dec_float;
using boost::multiprecision::cpp_bin_float_quad;

#include <boost/multiprecision/gmp.hpp>
using namespace boost::multiprecision;

typedef boost::multiprecision::number<boost::multiprecision::cpp_dec_float<40> > flp_type_dec_40;
typedef boost::multiprecision::number<boost::multiprecision::cpp_dec_float<49> > flp_type_dec_49;
typedef boost::multiprecision::number<boost::multiprecision::cpp_dec_float<99> > flp_type_dec_99;
typedef boost::multiprecision::number<boost::multiprecision::cpp_dec_float<101> > flp_type_dec_101;


using namespace std;

template<typename T>
inline T area_of_a_circle(T r)
{
    // pi represent predefined constant having value
    // 3.1415926535897932384...
    using boost::math::constants::pi;
    return pi<T>() * r * r;
}



void testFloatNumbers()
{
	float radius_f = 123.0/ 100;
	float area_f = area_of_a_circle(radius_f);

	double radius_d = 123.0 / 100;
	double area_d = area_of_a_circle(radius_d);

	cpp_dec_float_50 r_mp = 123.0 / 100;
	cpp_dec_float_50 area_mp = area_of_a_circle(r_mp);

	cpp_dec_float_100  r_100 = 123.0 / 100;
	cpp_dec_float_100 area_100 = area_of_a_circle(r_100);


	cpp_bin_float_quad  r_quad= 123.0 / 100;
	cpp_bin_float_quad area_quad = area_of_a_circle(r_quad);


	flp_type_dec_40  r_40 = 123.0 / 100;
	flp_type_dec_40 area_40 = area_of_a_circle(r_40);


	flp_type_dec_49  r_49 = 123.0 / 100;
	flp_type_dec_49 area_49 = area_of_a_circle(r_49);


	flp_type_dec_99  r_99 = 123.0 / 100;
	flp_type_dec_99 area_99 = area_of_a_circle(r_99);


	flp_type_dec_101  r_101 = 123.0 / 100;
	flp_type_dec_101 area_101 = area_of_a_circle(r_101);


      using boost::math::constants::pi;
      cout << "Let be given a circle with radius, r = " << radius_d << endl;
      cout << "Calculate the area of the given circle,\n        Area = PI*r^2 = " << pi<double>() << "*" << radius_d << "^2 = " << pi<double>() << "*" << (radius_d * radius_d) << ",\nin various precisions." << endl << endl;;

	// numeric_limits::digits10 represent the number
	// of decimal digits that can be held of particular
	// data type without any loss.
	
	// Area by using float data type
	cout << " Float: "
		<< setprecision(numeric_limits<float>::digits10)
		<< area_f << endl;

	// Area by using double data type
	cout << "Double: "
		<<setprecision(numeric_limits<double>::digits10)
		<< area_d << endl;


	// Area by using Boost 40 precision Multiprecision
	cout << "Boost Multiprecision  (40 digits): "
		<< setprecision(numeric_limits<flp_type_dec_40>::digits10)
		<< area_49 << endl;

	// Area by using Boost 49 precision Multiprecision
	cout << "Boost Multiprecision  (49 digits): "
		<< setprecision(numeric_limits<flp_type_dec_49>::digits10)
		<< area_49 << endl;

	// Area by using Boost 50 precision Multiprecision
	cout << "Boost Multiprecision  (50 digits): "
		<< setprecision(numeric_limits<cpp_dec_float_50>::digits10)
		<< area_mp << endl;

	// Area by using Boost 99 precision Multiprecision
	cout << "Boost Multiprecision  (99 digits): "
		<< setprecision(numeric_limits<flp_type_dec_99>::digits10)
		<< area_99 << endl;

	// Area by using Boost 100 precidion Multiprecision
	cout << "Boost Multiprecision (100 digits): "
		<< setprecision(numeric_limits<cpp_dec_float_100>::digits10)
		<< area_100 << endl;

	// Area by using Boost 101 precision Multiprecision
	cout << "Boost Multiprecision (101 digits): "
		<< setprecision(numeric_limits<flp_type_dec_101>::digits10)
		<< area_100 << endl;

	// Area by using Boost Quaduple Multiprecision
	cout << "Boost Multiprecision  (Quadruple): "
		<< setprecision(numeric_limits<cpp_bin_float_quad>::digits10)
		<< area_quad << endl;
}


int main()
{ 
	testFloatNumbers();
	return 0;
}


/*
Output:
-------------------------------------------
Let be given a circle with radius, r = 1.23
Calculate the area of the given circle,
        Area = PI*r^2 = 3.14159*1.23^2 = 3.14159*1.5129,
in various precisions.

 Float: 4.75292
Double: 4.752915525616
Boost Multiprecision  (40 digits): 4.752915525615998053187629092943809341311
Boost Multiprecision  (49 digits): 4.752915525615998053187629092943809341310825398145
Boost Multiprecision  (50 digits): 4.7529155256159980531876290929438093413108253981451
Boost Multiprecision  (99 digits): 4.75291552561599805318762909294380934131082539814514244132288567973008216166037385350291572422559648
Boost Multiprecision (100 digits): 4.752915525615998053187629092943809341310825398145142441322885679730082161660373853502915724225596483
Boost Multiprecision (101 digits): 4.7529155256159980531876290929438093413108253981451424413228856797300821616603738535029157242255964827
Boost Multiprecision  (Quadruple): 4.75291552561599805318762909294381
-------------------------------------------
*/

 

 

 

Posted by Scripter

댓글을 달아 주세요

 

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

댓글을 달아 주세요

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

댓글을 달아 주세요

Cygwin 에서는 printf 와 wprint 를 동시에 사용하는 경우, 컴파일은 성공하지만 실행하면 wprintf 가 제대로 동작하지 않는다.  그리고 wprint 나 swptinf 사용 시 스트링을 출력하기 위해서는 %s 대신 %ls 포맷을 사용해야 한다.

Cygwin 의 경우 wchar_t 의 크기는 2바이트이다.

C++ 언어에서는 스트링(문자열) 클래스인 string 이 준비되어 있지만, utf-8  스트링을 db위해서는 wstring 을 써야 한다. 또 표준 입출력 cin 과 cout 대신 wcin 과 wcout 을 써야 허며 이를 위해서는  헤더 파일 iostream 을 인클루드(포함)해야 하고 이름 공간 std 를 써야 한다. 또 C 언어 처럼 setlocale(LC_ALL,""); 도 해야 한다. 헤더 파일 locale.h 는 포함하지 않아도 된다.

http://blog.naver.com/PostView.nhn?blogId=manhwamani&logNo=10083589211 도 참조한다.

#include <iostream>
// #include <cwchar>
// #include <string>
#include <stdio.h>
#include <string.h>
#include <wchar.h>
// #include <locale.h>

int main(int argc, const char *argv[]) {
    wchar_t wt[100];
    std::wstring ws;

    /// setlocale(LC_ALL,"kr_KR.UTF-8");
    setlocale(LC_ALL,"");
    // printf("sizeof(wchar_t) = %d\n", sizeof(wchar_t));
    // printf("For more informations, \nsee: http://www.firstobject.com/wchar_t-string-on-linux-osx-windows.htm\n");

    std::wcout << L"sizeof(wchar_t) = " << sizeof(wchar_t) << std::endl;
    std::wcout << L"For more informations, \nsee: http://www.firstobject.com/wchar_t-string-on-linux-osx-windows.htm" << std::endl;

    std::wcout << L"\n";
    wcscpy(wt, L"abc 가나다");
    std::wcout << L"Using wchar_t[],\n";
    std::wcout << wt << std::endl;
    swprintf(wt, wcslen(L"abc 가나다") + 1, L"%ls", L"abc 가나다");
    std::wcout << wt << std::endl;
    std::wcout << L"The length of \"" << wt << L"\" is " << wcslen(wt) << L"." <<  std::endl;
    wprintf(L"%ls\n", L"abc 가나다");
    std::wcout << L"\n";
    ws = L"abc 가나다";
    std::wcout << L"Using wstring,\n";
    std::wcout << ws << std::endl;
    std::wcout << L"The length of \"" << ws << L"\" is " << ws.length() << L"." <<  std::endl;
    std::wcout << L"abc 가나다" << std::endl;

    return 0;
}

 

컴파일:

$ g++ -o testWstring_02 testWstring_02.cpp

실행:

./testWstring_02
sizeof(wchar_t) = 2
For more informations,
see: http://www.firstobject.com/wchar_t-string-on-linux-osx-windows.htm

Using wchar_t[],
abc 가나다
abc 가나다
The length of "abc 가나다" is 7.
abc 가나다

Using wstring,
abc 가나다
The length of "abc 가나다" is 7.
abc 가나다

 

 

 

 

Posted by Scripter

댓글을 달아 주세요

locale을 적용하지 않은 경우:

#include <iostream>
#include <string>
#include <algorithm>
 
int main()
{
  std::string s;
  std::getline(std::cin, s);
  std::reverse(s.begin(), s.end()); // modifies s
  std::cout << s << std::endl;
  return 0;
}

 

컴파일:

$ g++ -o testReverseUTF8_003 testReverseUTF8_003.cpp

실행:

$ ./testReverseUTF8_003
안녕하세요?
?▒▒츄옕핅눕▒

 

locale을 적용하고 wstring, wcout, wcin을 사용한 경우:

#include <iostream>
#include <string>
#include <algorithm>
 
int main()
{
  std::setlocale(LC_ALL, "ko_KR.UTF-8");
  std::wstring s;
  std::getline(std::wcin, s);
  std::reverse(s.begin(), s.end()); // modifies s
  std::wcout << s << std::endl;
  return 0;
}

 

컴파일:

$ g++ -o testReverseUTF8_003 testReverseUTF8_003.cpp

실행:

$ ./testReverseUTF8_003
안녕하세요?
?요세하녕안


 

 

 

Posted by Scripter

댓글을 달아 주세요

다음은 utf-8 인코딩으로 저장한 C++ 소스이다.

Cygwin의 g++ tkdyd tl,  만일  아래의 소스에서
        std::setlocale(LC_ALL, "ko_KR.UTF-8");
대신  
        std::locale::global (std::locale ("ko_KR.UTF-8"));
로 하면 캄핑ㄹ은 되지만 실행 시에

        Segmentation fault (core dumped)

에러가 난다.

* 소스 파일명: testLocale_003.cpp

// Filename: testLocale_003.cpp
//
// Compile:  g++ -std=c++11 -o testLocale_003 testLocale_003.cpp
//    or         g++ -std=c++0x -o testLocale_003 testLocale_003.cpp
//    or         g++ -o testLocale_003 testLocale_003.cpp

#include <iostream>
#include <locale>
#include <cstring>   // for strlen()

using namespace std;

int main() {
  //// std::locale::global (std::locale ("ko_KR.UTF-8"));
  std::setlocale(LC_ALL, "en_US.UTF-8");
  wcout << L"한글\n";
  wcout << wcslen(L"한글") << L"\n";
  wcout << L"韓國語\n";
  wcout << wcslen(L"韓國語") << L"\n";

  cout << u8"한글\n";
  cout << strlen(u8"한글") << "\n";
  cout << u8"韓國語\n";
  cout << strlen(u8"韓國語") << "\n";
}

 

위의 소스에서 처럼 u8"스트링" 구문을 사용하면, g++ 명령으로 컴파일 시에 -std=c++11 또는 -std=gnu11 옵션을 주어야 한다.

 

* 컴파일

$ gcc -std=c++11 -o testLocale_003 testLocale_003.cpp

* 실행

$ ./testLocale_003

한글
2
韓國語
3
한글
6
韓國語
9

 

Posted by Scripter

댓글을 달아 주세요

* Qt 5.2.1 내려받기  (아래의 예는 Visual Studio 2010 용을 받아서 설치한 경우이다. Qt Creator 3.0.1 은 자동으로 함께 설치된다,)

 

Qt Creator 를 시작한 후 메뉴에서

         File --> New File or Project...

를 택한다. 그리고 New 창에서 다음 그림에서와 같이

        Applications --> Qt Quick Application

을 택하고 "Choose..." 버튼을 클릭한다.

 

이어 나타나는 New Qt qUICK aPPLICATION 창에서 애플리케이션이 생성될 폴더와 이름을 정한다. 원하는 폴더거 없는 경우 그 우측의 "Browse" 버튼을 클릭하여 생성하거나 선택한다.

 

다음 창에서는 Qt Quick Componenet Set 을 정한다. Qt 5.0 이상은 "Qt Quick 2.0" 으ㅜㄹ 택한다.

 

다음 창에서는 Kit Selection 을 설정한다. (이 예에서는 Visual C 2010 용으로 설치한 경우이다.)

 

다음 창에서는 Project Management 를 확인한다. 앞으로 main.qml 파일만 수정하고 저장한 후 실행하면 된다. (실행 버튼만 누르면 빌드는 저절로 된다.)

 

 

* main.cpp 의 내용 (자동으로 생성된 후 수정되지 않음)

 

#include <QtGui/QGuiApplication>

#include "qtquick2applicationviewer.h"

int main(int argc, char *argv[])
{
    QGuiApplication app(argc, argv);

    QtQuick2ApplicationViewer viewer;
    viewer.setMainQmlFile(QStringLiteral("qml/ThirdHelloQtQuickApp/main.qml"));
    viewer.showExpanded();

    return app.exec();
}
 

 

* main.qml 의 내용 (자동 생성된 main.qml 파일의 내용을 아래 처럼 수정한다.)

import QtQuick 2.0

Rectangle {
    id: page
    width: 320; height: 160
    color: "lightgray"

    Text {
        id: helloText
        text: "Hello, world!<br /><br />안녕하세요?"
        y: 25
        anchors.horizontalCenter: page.horizontalCenter
        font.pointSize: 24; font.bold: true; font.italic: true
    }
}

 

 

* Releae/Debug 변경하기 그리고 실행하기 (Qt Creator 창의 좌측 아래 부분)

 

 

* Release 배포를 위해 PATH 에 지정된 폴더에 꼭 있어야 하는 파일들:

icudt51.dll
icuin51.dll
icuuc51.dll
libEGL.dll
libGLESv2.dll
Qt5Core.dll
Qt5Gui.dll
Qt5Network.dll
Qt5Qml.dll
Qt5Quick.dll
ThirdHelloQtQuickApp.exe
 
 

 

* 만일 PATH 로 지정된 경로에 libEGL.dll 이 없으면 다음 에러 메시지 창이 뜬다.

 

 

 

* 실행 결과:

 

 

 

 

 

Posted by Scripter

댓글을 달아 주세요

SymbolicC++  는 GiNaC 처럼 심볼 처리 수학식 계산을 지원하지만, 리눅스 계열 뿐만 아니라 윈도우 환경에서도 Visual C++ 나 MinGW 의 g++ 와 함께 사용할 수 있는 수학 심볼 처리 라이브러리이다.

 

* SymbolicC++  내려받기

* Wikipedia 에서 설명하는 SymbolicC++

 

* MinGW 의 g++ 를 위한 SymbolicC++  라이브러리 만들기

모든 작업은 MinGW\msys\1.0 폴더에 있는 msys.bat 파일을 실행하여 msys 창에서 한다.

$ ./configure

$ make

$ make install

$ make clean

생성된 라이브러리 파일 libsymbolicc++.a 와 libsymbolicc++.la 는 /usr/local/lib 폴더에 존재하고, 헤더 파일 symbolicc++.h 는 /usr/local/include 폴더에 존재한다.

 

* 간단한 인터프리터 소스

/*
    SymbolicC++ : An object oriented computer algebra system written in C++

    Copyright (C) 2008 Yorick Hardy and Willi-Hans Steeb

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License along
    with this program; if not, write to the Free Software Foundation, Inc.,
    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/


// interpreter.cpp

#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <map>
#include <cstdlib>
#include <cmath>
#include "symbolicc++.h"
using namespace std;

double error(string s)
{ cerr << "Error: " << s << ", using 0." << endl; return 0.0; }

class token
{
  private:
   int is_value;
   Symbolic v;
   string t;
   static map<string,Symbolic> values;
  public:
   token() : is_value(0), v(0), t("") {};
   token(const Symbolic &s) : is_value(1), v(s), t("") {};
   token(const string &s) : is_value(0), v(0), t(s)  {};
   Symbolic value();
   string name() { return t; }
   int isvalue() { return is_value; }
   Symbolic set(const Symbolic &d) { return values[t]=d; }
   int operator==(string s) { return (!is_value) && (t == s); }
   friend ostream& operator << (ostream&,token);
};

map<string,Symbolic> token::values;

Symbolic token::value()
{
  if(is_value) return v;
  char *end;
  int vali=(int)strtol(t.c_str(),&end,10);
  if(*end == '\0') return Symbolic(vali);
  double vald=strtod(t.c_str(),&end);
  if(*end == '\0') return Symbolic(vald);
  if(values.count(t)>0) return values[t];
  return Symbolic(t);
}

ostream& operator << (ostream& o,token t)
{ if(t.is_value) o << t.v; else o << t.t; return o;}

vector<token>
get_tokens(string s,string separator[],string ignore[])
{
  int i = 0, j, istoken = 0;
  vector<token> v;
  string value = "";
  while(i<(int)s.length())
  {
   istoken = 0;
   for(j=0;ignore[j] != "" && i<(int)s.length();j++)
    if(s.substr(i,ignore[j].length()) == ignore[j])
     i += ignore[j].length(), j = -1, istoken = 1;
   for(j=0;separator[j] != "" && !istoken;j++)
    if(s.substr(i,separator[j].length()) == separator[j])
    {
     if(value != "") { v.push_back(token(value)); value = ""; }
     v.push_back(token(separator[j]));
     i += separator[j].length();
     istoken = 1;
    }
   if(!istoken) value += s[i++];
   else if(value!="") { v.push_back(token(value)); value = ""; }
  }
  if(value != "") v.push_back(token(value));
  return v;
}

Symbolic spow(const Symbolic &x,const Symbolic &y) { return (x^y); }
Symbolic smul(const Symbolic &x,const Symbolic &y) { return x*y;   }
Symbolic sdiv(const Symbolic &x,const Symbolic &y) { return x/y;   }
Symbolic sadd(const Symbolic &x,const Symbolic &y) { return x+y;   }
Symbolic ssub(const Symbolic &x,const Symbolic &y) { return x-y;   }

Symbolic ssqrt(const vector<Symbolic> &x)  { return sqrt(x[0]);           }
Symbolic scos(const vector<Symbolic> &x)   { return cos(x[0]);            }
Symbolic ssin(const vector<Symbolic> &x)   { return sin(x[0]);            }
Symbolic stan(const vector<Symbolic> &x)   { return tan(x[0]);            }
Symbolic sexp(const vector<Symbolic> &x)   { return exp(x[0]);            }
Symbolic sln(const vector<Symbolic> &x)    { return ln(x[0]);             }
Symbolic slog(const vector<Symbolic> &x)   { return log(x[0],x[1]);       }
Symbolic sdf(const vector<Symbolic> &x)    { return df(x[0],x[1]);        }
Symbolic ssubst(const vector<Symbolic> &x) { return x[0].subst(x[1],x[2]);}
Symbolic sfunc(const vector<Symbolic> &x)  { return x[0][x[1]];           }

Symbolic evaluate(token t);

struct function {
 string name;
 int    args;
 Symbolic (*impl)(const vector<Symbolic>&);
};

Symbolic evaluate_tokens(vector<token> v)
{
  vector<token> v2, v3;
  int parenthesis, i, j, k;
  // function names, arity, and their implementation
  function functions[] = {
   { "sqrt",     1, ssqrt  },
   { "cos",      1, scos   },
   { "sin",      1, ssin   },
   { "tan",      1, stan   },
   { "exp",      1, sexp   },
   { "ln",       1, sln    },
   { "log",      2, slog   },
   { "df",       2, sdf    },
   { "subst",    3, ssubst },
   { "function", 2, sfunc  },
   { "" } };

  // default left operands for binary operators
  double initleft[] = { 1.0, 1.0, 0.0 };
  // binary operators and their implementation
  string opnames[][4] = { { "^", "" }, { "*", "/", "" }, { "+", "-", "" } };
  Symbolic (*opimpl[][3])(const Symbolic&,const Symbolic&) =
     { { spow }, { smul, sdiv }, { sadd, ssub } };

  // check for the assignment statement
  if(v.size()>2 && v[1] == "=") {
    for(j=2;j<(int)v.size();j++) v2.push_back(v[j]);
    return v[0].set(evaluate_tokens(v2));
  }

  // evaluate parenthesis first
  for(j=0;j<(int)v.size();j++)
  {
   if(v[j] == ")") return error("unbalanced parenthesis");
   else if(v[j] == "(")
   {
    for(parenthesis=1,j++;parenthesis && j<(int)v.size();j++)
    {
     if(v[j] == "(") parenthesis++;
     if(v[j] == ")") parenthesis--;
     // artificially end the parenthesized expression
     if(v[j] == "," && parenthesis == 1)
     {
      v2.push_back(token(evaluate_tokens(v3)));
      v3.clear();
     }
     else if(parenthesis) v3.push_back(v[j]);
    }
    if(parenthesis) return error("unbalanced parenthesis");
    v2.push_back(token(evaluate_tokens(v3)));
    v3.clear(); j--;
   }
   else v2.push_back(v[j]);
  }

  // evaluate functions
  for(j=0,v.clear();j<(int)v2.size();j++)
  {
   for(i=0;functions[i].name!="";i++)
   if(v2[j] == functions[i].name)
   {
    if(j+functions[i].args<(int)v2.size())
    {
      vector<Symbolic> args;
      for(k=1;k<=functions[i].args;k++)
       args.push_back(evaluate(v2[j+k]));
      v.push_back(token(functions[i].impl(args)));
      j+=functions[i].args;
    }
    else return error(functions[i].name           +
                      " without "                 +
                      char('0'+functions[i].args) +
                      " arguments");
    break;
   }
   if(functions[i].name=="") v.push_back(v2[j]);
  }
  // evaluate operators in order of precedence
  for(k=0,v2.clear();k<3;k++,v = v2,v2.clear())
  {
   token left(initleft[k]);
   for(j=0;j<(int)v.size();j++)
   {
    for(i=0;opnames[k][i]!="";i++)
    if(v[j] == opnames[k][i])
    {
     if(v2.size()) v2.pop_back();
     if(j+1<(int)v.size())
      v2.push_back(token(opimpl[k][i](evaluate(left),
                                      evaluate(v[++j]))));
     else return error(opnames[k][i]+" without second argument");
     break;
    }
    if(opnames[k][i]=="") v2.push_back(v[j]);
    left = v2.back();
   }
  }
  // check that evaluation gave a single result
  if(v.size() != 1)
  {
   for(j=0;j<(int)v.size();j++)
    cerr << "token " << j+1 << " : " << v[j] << endl;
   return error("could not evaluate expression");
  }
  return v[0].value();
}

Symbolic evaluate(token t)
{ vector<token> v; v.push_back(t); return evaluate_tokens(v); }

Symbolic evaluateformula(istream &s)
{
  char c;
  string expression;
  static string ws[] = { " ", "\t", "\n", "\r", "" };
  static string separator[] = { "=", "+", "-", "*", "/",
                                "^", "(", ")", ",", "" };
  do if((c = s.get()) != ';' && !s.eof()) expression += c;
  while(c != ';' && !s.eof());
  if(c != ';') return error("formula not terminated");
  vector<token> v = get_tokens(expression,separator,ws);
  return evaluate_tokens(v);
}

int main(void)
{
  while(!cin.eof())
  cout << " -> " << evaluateformula(cin) << endl;
  return 0;
}

 

* 컴파일 및 실행 (인터프리터를 실행하면 세미콜론(;)으로 끝나는 구문을 계산해준다.)

$ g++ -o interpreter interpreter.cpp -lsymbolicc++

$ ./interpreter
(x - 1)^3;
 -> x^(3)-3*x^(2)+3*x-1
2^3 - 2*3 + 5;
 -> 7
(x^2 - x + 1)*(x^2 + x + 1) ;
 -> x^(4)+x^(2)+1
2^10;
 -> 1024


 

Posted by Scripter

댓글을 달아 주세요

SymbolicC++  는 GiNaC 처럼 심볼 처리 수학식 계산을 지원하지만, 리눅스 계열 뿐만 아니라 윈도우 환경에서도 Visual C++ 나 MinGW 의 g++ 와 함께 사용할 수 있는 수학 심볼 처리 라이브러리이다.

 

* SymbolicC++  내려받기

* Wikipedia 에서 설명하는 SymbolicC++

 

* Visual C++ 를 위한 SymbolicC++  라이브러리 만들기

Visual Studio 에서 솔루션 파일 SymbolicC++3.sin 을 열고 아래 그림 처럼 메뉴 탭에서 Dynamic 이라고 설정된 곳을 Static 으로 변경하고 빌드한다.

그러면 에러와 경고가 몇 개 쏟아질 것이다.

 

* 에러 해결하기

SymbolicC++ 를 빌드하는 과정에서 C:\Program Files (x86)\Microsoft Visual Studio 10\VC\include 폴더에 있는 파일 xlocmon 410 째 줄에서 에러가 걸린다. 이 줄을

                 _Str2 += '-', ++_Off;   ------>    _Str2 += '-'; ++_Off;

처럼 수정(즉 콤마를 세미콜론으로 수정)하여 다시 저장한다.

그러면 에러는 해결되고 경고(warning) 몇 개가 남는다.

 

* 몇 가지 경고(warning) 해결하기

1) SymbolicC++ 의 소스 파일 중에 integrate.cpp 파일에서 "변수 se 가 선언되었지만 사용되지 않았다"는 경고가 몇 곳 나온다.  이런 경고를 해결하려면, integrate.cpp 파일에서

        } catch(const SymbolicError &se) {}

처럼 된 중을 모두 찾아

        } catch(const SymbolicError &se) { std::cout << se.message() << std::endl; }

처럼 수정하고, 이 파일의 선두 부분에 include 문

        #include <iostream>

을 추가한다..

 

2) equation.cpp 파일의 95 째 줄

        { return lhs.compare(rhs); }


        { return (lhs.compare(rhs) == 0) ? false : true; }

로 수정한다.

 

3) sum.cpp 파일의 373 째 줄

        if(j != matchpart.end()); matchpart.erase(j);


         (j != matchpart.end()) matchpart.erase(j);

로 수정한다. (세미콜론 하나 제거)

 

* SymbolicC++ 를 이용하는 간단한 부정적분 예제

/*
    SymbolicC++ : An object oriented computer algebra system written in C++

    Copyright (C) 2008 Yorick Hardy and Willi-Hans Steeb

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License along
    with this program; if not, write to the Free Software Foundation, Inc.,
    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/


// integration.cpp

#include <iostream>
#include "symbolicc++.h"
using namespace std;

int main(void)
{
  Symbolic x("x"), c("c"), z("z"), y;

  z = z[x];
  y = (1-x)*(1-x)+cos(x)+x*exp(x)+c+z;

  cout << "y = " << y << endl;

  for(int i=0;i<3;i++)
  {
   y = integrate(y,x);
   y = y[integrate(x*exp(x),x) == x*exp(x) - exp(x)];
   cout << "y = " << y << endl;
  }

  return 0;
}

 

 

* 위의 예제 소스 컴파일하기 (컴파일 옵션 /MD 가 중요)

프롬프트> cl /EHsc /I SymbolicC++3-3.35-vc\include integration.cpp SymbolicC++3.lib /MD

 

* 실행하기

프롬프트> integration
y = x^(2)-2*x+cos(x)+x*e^x+c+z[x]+1
y = 1/3*x^(3)-x^(2)+sin(x)+x*e^x-e^x+c*x+int(z[x],x)+x
y = 1/12*x^(4)-1/3*x^(3)-cos(x)+x*e^x-2*e^x+1/2*c*x^(2)+int(z[x],x,x)+1/2*x^(2)
y = 1/60*x^(5)-1/12*x^(4)-sin(x)+x*e^x-3*e^x+1/6*c*x^(3)+int(z[x],x,x,x)+1/6*x^(3)

 

 

Posted by Scripter

댓글을 달아 주세요