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
,