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
,