커스텀 에디터를 만들 때 가장 중요한 항목은 사용자의 확인, 취소에 대한 입력을 받는 것입니다.

그리고 실수로 잘 못 된 버튼을 누르는 것을 방지하거나 무언가 오류가 생길시 알림을 주는 기능도 할 수 있습니다.

 

C#으로 치면 MessageBox 기능이고

유니티에서는 UnityEditor.EditorUtility.DisplayDialog 를 통해 메시지 출력이 가능합니다.

 

에디터 모드에서도 가능하지만 실시간 게임 중에도 출력이 가능하기에 우선

플레이 버튼 시 메시지가 뜨도록 MonoBehaviour에 작성하여 실행시켜보았습니다.

 

파라미터 개수에 따라 확인만 가능하거나 취소까지 가능하며

해당 결과를 bool 값으로 받을 수 있습니다.

using UnityEngine;
using UnityEditor;

public class ShowMessage : MonoBehaviour
{
    void Start()
    {
        bool result = EditorUtility.DisplayDialog("제목", "메시지", "확인", "취소");

        if (result)
        {
            EditorUtility.DisplayDialog("클릭 결과", "확인 메시지가 클릭되었습니다.", "확인");
        }
        else
        {
            EditorUtility.DisplayDialog("클릭 결과", "취소 메시지가 클릭되었습니다.", "확인");
        }
    }
}

 

초기 메시지

 

https://ko.wikipedia.org/wiki/RSA_%EC%95%94%ED%98%B8

 

RSA 암호 - 위키백과, 우리 모두의 백과사전

RSA 암호는 공개키 암호시스템의 하나로, 암호화뿐만 아니라 전자서명이 가능한 최초의 알고리즘으로 알려져 있다. RSA가 갖는 전자서명 기능은 인증을 요구하는 전자 상거래 등에 RSA의 광범위한

ko.wikipedia.org

위의 내용을 참고하였습니다.

 

RSA 방식 간단한 소개

공개키 <e, n>

개인키 <d, n>

암호화 작업 복호화 작업
메시지^d % n 메시지^e % n
메시지^e % n 메시지^d % n

d와 e는 서로 암호화 및 복호화에 필요하며 e만 공개하고

d는 개인키로 숨겨둬야 됩니다.

 

공개키와 개인키를 구하는 방법을 살펴보겠습니다.

사실 엄청나게 큰 소수를 선택하여 d를 계산해내지 못하게 해야되지만

지금은 작은 숫자를 통해 동작을 살펴보았습니다. 

 

소수 2개 (p, q)를 입력받습니다.  p = 23, q = 29

n = p * q 로 정의해줍니다. (n = 667)

오일러피 함수 (n) = (23 - 1) * (29 - 1) 을 얻고,

 오일러피 함수 결과와 서로소인 값을 하나 선택합니다. 해당 값이 공개키 e 값이 됩니다. e = 307을 선택하였습니다.

 

개인키 d를 구합니다. d는 e * d % n == 1 이 되는 d값을 구해주면 됩니다.

d = 2155를 선택하였습니다.

 

공개키와 개인키가 만들어졌습니다. 이제 메시지를 작성해봅니다.

이 때 n이 충분히 크지 않다면..! 아래 결과 내용을 읽어보시길..

"암호화할 메시지 입니다~~ !@#$$% 1234567" 까지가 메시지 입니다.

 

암호화 한 후 출력, 이 후 다시 복호화한 작업입니다.

 

 

기본 개념

 

1. 공개키와 개인키는 서로 암호화/복호화 작업에 필요한 키입니다.

2. 공개키 e는 외부에 공개하지만 d는 개인키로 알려져선 안됩니다. d는 복호화 작업에 쓰이는 중요한 키입니다.

 

키 생성 방법

1. 소수 2개 (p, q)를 고릅니다.

2. 둘의 곱 n = p * q 를 얻습니다.

3. 오일러phi (n) 값을 구합니다. n = 소수 * 소수 이므로

   eulerPhi = (p - 1) * (q - 1) 를 얻습니다.

(오일러피 함수 : 

https://ko.wikipedia.org/wiki/%EC%98%A4%EC%9D%BC%EB%9F%AC_%ED%94%BC_%ED%95%A8%EC%88%98)

 (오일러피 함수 (n)은 n보다 작고 n과 서로소인 (서로소: 최대 공약수가 1인 숫자) 숫자의 개수를 의미합니다.

오일러피 함수의 성질에 따라 두 소수는 (p - 1) * (q - 1) 로 정의됩니다.)

  •  phi(소수) = 소수 - 1
  •  phi(소수1 * 소수2) = phi(소수1) * phi(소수2) = (소수1 - 1) * (소수2 - 1)

4. eulerPhi 보다 작고 eulerPhi와 서로소인 정수 e를 찾아 선택합니다. (e가 공개키가 됩니다.)

5. d * e % eulerPhi == 1 인 d를 찾습니다. (d가 개인키가 됩니다.)

6. 최종적으로 키가 생성됩니다.

 <e, n> 공개키,    <d, n> 개인키

 

암호화 방법

 메시지를 e번 제곱해주고 n으로 나눈 나머지를 얻습니다.

 

복호화 방법

 메시지를 d번 제곱해주고 n으로 나눈 나머지를 얻습니다.

 

주의사항) n은 우리가 사용하는 문자 값보다 커야됩니다.

 n이 'A' (65) 보다 작다면 A라는 의미를 잃어버리기 때문입니다.

 

프로그램에선 숫자가 너무 커지므로 제곱할 때마다 n으로 나눠주고 있습니다.

코드가 좀 길어서 제가 다시 볼지 모르겠습니다 ㅋㅋ;

 

코드 흐름

1. InitPrime() : 에라토스테네스의 체를 통해 notPrime배열에 소수를 구해두기

2. 소수 p, q를 입력받기

3. 오일러피 값을 구합니다. eulerPhi = (p - 1) * (q - 1)

4. GetRelativePrime() : eulerPhi 에 서로수인 숫자를 구합니다. (최대공약수를 찾기 위해 GCD 가 쓰입니다)

5. 공개키 e 입력 받기

6. FindPrivateDKey() : 개인키 후보를 찾습니다.

7. 개인키 d 입력 받기

8. 문자열 입력

9. Encryption() : 암호화 및 출력

 (여기서 char 배열에서 int 배열로 바꿔서 저장합니다.

 char는 1byte (=8bit) 최대 255까지밖에 표현되지 않아 값을 잃어버리기 때문입니다.)

10. Decryption() : 암호를 복호화하여 출력

 

#include <cstdio>
#include <cstring>
#include <vector>

using namespace std;

const int MaxSize = 10000;
const int Size = 100;
const int LineLength = 14;

bool notPrime[MaxSize];
bool relativePrime[MaxSize]; //서로소
char input[100];
int encryptToInt[100];

vector<long long> dList;

void InitPrime()
{
	notPrime[0] = notPrime[1] = true;

	for (int i = 2; i * i <= MaxSize; ++i)
	{
		if (notPrime[i])
		{
			continue;
		}

		for (int j = i * i; j <= MaxSize; j += i)
		{
			notPrime[j] = true;
		}
	}
}

void PrintPrime(int enterLine, int size)
{
	printf("====소수 목록====\n");
	int line = 0;
	for (int i = 2; i < Size; ++i)
	{
		if (notPrime[i])
		{
			continue;
		}

		printf("%3d ", i);
		line++;

		if (line >= enterLine)
		{
			line = 0;
			printf("\n");
		}
	}
}

int GCD(int a, int b) //Greatest Common Divisor 최대 공약수 찾기
{
	while (b != 0)
	{
		int c = a % b;
		a = b;
		b = c;
	}

	return a;
}

void GetRelativePrime(int enterLine, int phi)
{
	int line = 0;
	for (int i = 1; i < phi; ++i)
	{
		if (GCD(i, phi) == 1)
		{
			line++;
			printf("%3d ", i);
			relativePrime[i] = true;
			
			if (line >= enterLine)
			{
				line = 0;
				printf("\n");
			}
		}
	}
}

void FindPrivateDKey(int e, int eulerPhi, int many)
{
	for (long long d = 1; dList.size() < many; ++d)
	{
		if (d * e % eulerPhi == 1)
		{
			dList.push_back(d);
			printf("[%d]번째 가능한 개인키 d = %lld [ %lld * %d %% %d = 1 ]\n", dList.size(), d, d, e, eulerPhi);
		}
	}
}

int Pow(int value, int e, int n)
{
	int v = value;
	for (int i = 1; i < e; ++i)
	{
		v = v * value % n;
	}
	return v;
}

void Encryption(int e, int n)
{
	char encryptForPrint[100] = { 0 };
	int length = strlen(input);

	for (int i = 0; i < length; ++i)
	{
		int value = Pow(input[i], e, n);

		//char는 1바이트로 8bit, 최대 2^8 (256) 까지밖에 표현이 불가능하여
		//값이 256을 넘으면 오버플로우 발생
		encryptToInt[i] = value; 
		encryptForPrint[i] = value;
	}

	printf("%s\n", encryptForPrint);
}

void Decryption(int d, int n)
{
	char decryptForPrint[100] = { 0 };
	int length = strlen(input);

	for (int i = 0; i < length; ++i)
	{
		decryptForPrint[i] = Pow(encryptToInt[i], d, n);
	}
	printf("%s\n", decryptForPrint);
}

int main()
{
	int p, q, n, e;
	long long d;

	InitPrime();
	PrintPrime(LineLength, Size);
	printf("\n\n두 개의 소수를 입력하세요.\n");
	
	while (true)
	{
		scanf("%d %d", &p, &q);
		if (notPrime[p] || notPrime[q])
		{
			printf("\n소수를 다시 입력하세요.\n");
			continue;
		}

		break;
	}

	n = p * q; //[중요] n보다 작은 값들에 대해서만 암호화가 가능하다!!! % n 으로 나누어주기 때문이다.

	int eulerPhi = (p - 1) * (q - 1);
	printf("\n오일러 피 함수 값 %d * %d = %d\n", (p - 1), (q - 1), eulerPhi);
	printf("====%d와 서로수인 수====\n", eulerPhi);
	GetRelativePrime(LineLength, eulerPhi);
	printf("\n\n");

	while (true)
	{
		scanf("%d", &e);
		if (relativePrime[e])
		{
			break;
		}
		else
		{
			printf("\n서로수인 수를 입력해야됩니다.\n");
		}
	}

	FindPrivateDKey(e, eulerPhi, 5); //5개를 구해보자
	printf("\n개인키를 입력하세요.\n");

	while (true)
	{
		scanf("%lld", &d);
		
		bool isContain = false;

		for (int i = 0; i < dList.size(); ++i)
		{
			if (dList[i] == d)
			{
				isContain = true;
				break;
			}
		}

		if (isContain)
		{
			break;
		}
		else
		{
			printf("\n올바른 개인키를 입력해야 됩니다.\n");
		}
	}

	printf("\n\n 공개키 [e = %d, n = %d], 개인키 [d = %lld, n = %d]\n\n", e, n, d, n);

	printf("100문자 이내로 평문을 작성해보세요.\n");
	printf("(단 n의 크기가 해당 문자를 나타내는 숫자보다 작다면 변환값을 잃게 됩니다.)\n");
	printf("ex) 'A' = 65, n = 42라면 65값을 잃게 됩니다.\n\n");

	getchar(); //버퍼에 엔터키 제거용
	gets_s(input);

	printf("\n평문을 암호화 합니다.\n");
	Encryption(e, n);

	printf("\n==============================================\n");

	printf("\n평문을 복호화 합니다.\n\n");
	Decryption(d, n);

	return 0;
}

 

https://ko.wikipedia.org/wiki/%EC%9C%A0%ED%81%B4%EB%A6%AC%EB%93%9C_%ED%98%B8%EC%A0%9C%EB%B2%95

 

유클리드 호제법 - 위키백과, 우리 모두의 백과사전

유클리드 호제법(-互除法, Euclidean algorithm) 또는 유클리드 알고리즘은 2개의 자연수 또는 정식(整式)의 최대공약수를 구하는 알고리즘의 하나이다. 호제법이란 말은 두 수가 서로(互) 상대방 수를

ko.wikipedia.org

 

유클리드 호제법으로도 불립니다.

GCD는 굉장히 간단한 코드라서 외워서 쓸 정도인데 막상 안보고 구현하려니 헷갈려서

유도 방식을 직접 써서 생각해보게 되었습니다.

 

GCD (21, 12)     (참고로 GCD(12, 21)을 해도 12 % 21 = 12로 21 % 12로 바뀜)

21 % 12 = 9        
    12 % 9 = 3    
        9 % 3 = 0

GCD (21, 12) = 3

 

위의 숫자들을 그대로 가져와서 써주면 됩니다.

#include <iostream>

using namespace std;

int GCD(int a, int b)
{
	while (b != 0)
	{
		int c = a % b;
		a = b;
		b = c;
	}

	return a;
}

int main()
{
	cout << GCD(21, 12);
}

 

추가적으로 a와 b의 최대 공배수를 구하는 방법은

a * b / GCD(a, b) 로 할 수 있습니다.

 

ex)

8 과 10의 최소 공배수 구하기

8 * 10 / GCD(8, 10)   ( GCD(8, 10) = 2 )

8 * 10 / 2 = 40

클록을 통해 현재 경과한 시간을 알 수 있습니다.

아래 코드에서 5초 동안 돌아가며 i가 증가되는 값을 볼 수 있습니다.

 

#include <iostream>
#include <ctime>

using namespace std;

int main()
{
	clock_t start = clock(); //ms 단위를 반환 합니다. 1s == 1000ms
	int i = 0;
	int second = 0;

	while (second < 5)
	{
		clock_t end = clock();
		i++;
		if (end - start >= 1000)
		{
			second++;
			start = end;
			cout << second << "초 경과 i 값은 " << i << endl;
		}
	}
}

 

실행 결과

 

부모 클래스 또는 인터페이스를 이용하여 하위 요소를 생성 및 사용할 때 이용되는 패턴입니다.

 

using System;

namespace ConsoleApp
{
    class Program
    {
        public static void Main(string[] args)
        {
            int size = 3;
            int player = 0;
            Unit[] unit = new Unit[size];

            while (player < size)
            {
                Console.WriteLine("{0}p 종족을 입력하세요: (Zerg, Protoss, Terran)", player + 1);
                string race = Console.ReadLine();

                switch (race)
                {
                    case "Zerg":
                        unit[player] = new Zerg();
                        player++;
                        break;
                    case "Protoss":
                        unit[player] = new Protoss();
                        player++;
                        break;
                    case "Terran":
                        unit[player] = new Terran();
                        player++;
                        break;
                    default:
                        break;
                }
            }

            Console.WriteLine();
            foreach (Unit u in unit)
            {
                u.ShowType();
            }
        }
    }

    abstract class Unit
    {
        public abstract void ShowType();
    }

    class Zerg : Unit
    {
        public override void ShowType()
        {
            Console.WriteLine("Zerg");
        }
    }

    class Protoss : Unit
    {
        public override void ShowType()
        {
            Console.WriteLine("Protoss");
        }
    }

    class Terran : Unit
    {
        public override void ShowType()
        {
            Console.WriteLine("Terran");
        }
    }
}

실행 결과

 

단 하나의 인스턴스를 통해 해당 클래스에 접근 및 사용할 수 있습니다.

다른 객체들간의 통신 등에도 유용하게 쓸 수 있는 방법!

 

using System;

namespace ConsoleApp
{
    class Program
    {
        public static void Main(string[] args)
        {
            GameManager.GetInstance().PrintHello();
        }
    }

    class GameManager
    {
        private static GameManager instance = new GameManager();
        public static GameManager GetInstance ()
        {
            return instance;
        }

        private GameManager()
        {
            //private로 외부에서 생성을 못하게 막아줍니다.
        }

        public void PrintHello()
        {
            Console.WriteLine("Hello");
        }
    }
}

등록 된 관측자들에게 메시지를 전달해주는 패턴. (EventListener 등과 같이 알게 모르게 많이 쓰이고 있습니다.)

인터페이스보다 델리게이트 사용이 더 간단한 듯합니다.

 

using System;

namespace ConsoleApp
{
    class Program
    {
        public static void Main (string[] args)
        {
            Teacher t = new Teacher();
            Observer_Student marine = new Observer_Student("마린");
            Observer_Student zealot = new Observer_Student("질럿");
            Observer_Student zergling = new Observer_Student("저글링");

            t.AddStudent(marine);
            t.AddStudent(zealot);
            t.AddStudent(zergling);

            Console.WriteLine();
            t.ClassStart("달리기");

            Console.WriteLine();
            t.RemoveStudent(marine);

            Console.WriteLine();
            t.ClassStart("근접 공격");
            
            Console.ReadKey();
        }
    }

    class Teacher
    {
        private delegate void Teach(string subject);
        private Teach teach;
        
        public void AddStudent (Observer_Student student)
        {
            Console.WriteLine("{0}이 등록됩니다.", student.name);
            teach += student.Learn;
        }

        public void RemoveStudent (Observer_Student student)
        {
            Console.WriteLine("{0}이 등록 해제됩니다.", student.name);
            teach -= student.Learn;
        }

        public void ClassStart (string subject)
        {
            teach(subject);
        }
    }

    class Observer_Student
    {
        public string name;
     
        public Observer_Student(string name)
        {
            this.name = name;
        }

        public void Learn (string subject)
        {
            Console.WriteLine("{0}은 {1} 수업을 받고 있습니다.", name, subject);
        }
    }
}

 

실행 결과

 

특정한 동작에 대해 클래스 내부에 대한 수정이 아니라 클래스 외부에서 수정하도록 설계 해둔 패턴!

인터페이스 또는 델리게이트를 사용하여 구현할 수 있겠습니다.

 

using System;

namespace ConsoleApp
{
    class Program
    {
        public static void Main (string[] args)
        {
            Unit marine = new Unit();
            Unit zerling = new Unit();
            Unit medic = new Unit();

            marine.SetAttack(new Marine());
            zerling.SetAttack(new Zergling());
            medic.SetHeal(new Medic());

            marine.Attack();
            marine.Heal();

            zerling.Attack();
            zerling.Heal();
            
            medic.Attack();
            medic.Heal();
        }
    }

    class Unit
    {
        private IAttack attack = null;
        private IHeal heal = null;

        public void Attack ()
        {
            if (attack != null)
            {
                attack.Attack();
            }
        }

        public void Heal ()
        {
            if (heal != null)
            {
                heal.Heal();
            }
        }

        public void SetAttack (IAttack attack)
        {
            this.attack = attack;
        }

        public void SetHeal (IHeal heal)
        {
            this.heal = heal;
        }
    }

    interface IAttack
    {
        void Attack();
    }

    interface IHeal
    {
        void Heal();
    }

    class Marine : IAttack
    {
        public void Attack ()
        {
            Console.WriteLine("가우스 라이플 공격");
        }
    }

    class Zergling : IAttack
    {
        public void Attack()
        {
            Console.WriteLine("발톱 공격");
        }
    }

    class Medic : IHeal
    {
        public void Heal ()
        {
            Console.WriteLine("치료");
        }
    }
}

 

실행 결과

 

https://www.acmicpc.net/problem/1271

 

1271번: 엄청난 부자2

첫째 줄에는 최백준 조교가 가진 돈 n과 돈을 받으러 온 생명체의 수 m이 주어진다. (1 ≤ m ≤ n ≤ 101000, m과 n은 10진수 정수)

www.acmicpc.net

n / m 의 몫과 나머지를 출력하면 되는 문제.

 

처음에 별거 아니잖아? 하고 덤벼들었는데 1 ~ 10^1000 범위의 숫자에 대한 연산이 필요한 문제였습니다.

입력 값이 1001 "자리" 가 나온다는 의미입니다.  ("천억" 의 자리는 0000,0000,0000 12자리밖에 되지 않네요.)

 

풀이에 떠올린 아이디어는 이렇습니다.

우선 입력은 문자열로 받고 계산하기 편하게 숫자 배열로 만들어줍니다.

그리고 뺄셈을 통해 몫과 나머지를 구해줄 겁니다.

 

먼저 우리가 나누기를 진행할 때를 기억해보면

483216 / 30

 

        1 

    ㅡㅡㅡㅡㅡㅡ 

30) 4 8 3 2 1 6

     3 0

    ㅡㅡㅡㅡㅡㅡ

     1 8 3

 

        1 6

    ㅡㅡㅡㅡㅡㅡ 

30) 4 8 3 2 1 6

     3 0

    ㅡㅡㅡㅡㅡㅡ

     1 8 3

     1 8 0

    ㅡㅡㅡㅡㅡㅡ

          3 2

          .....

 

이런식으로 진행이 됩니다.

이 과정을 컴퓨터에게 시키면 몫과 나머지를 구할 수 있습니다.

대신 앞에서부터 뺄셈을 진행할 것이기 때문에 뺄셈이 진행되는 도중 불가능한 것이 판명되면

뺀 숫자들을 다시 더해주고 복구시켜 주겠습니다.

 

ex)

  574 / 575 진행 시

  574

- 5

ㅡㅡㅡ

    74

-   7

ㅡㅡㅡ

      4

-     5

 (진행이 불가능 하므로 앞의 57을 복구시켜 줘야됩니다.)

 

#include <iostream>
#include <string>
#include <vector>

using namespace std;

vector<int> moneyArray;
vector<int> personsArray;

int moneyLength;
int personsLength;

void MakeIntArray(vector<int>& arr, string& str, int length)
{
	for (int i = 0; i < length; ++i)
	{
		arr[i] = str[i] - '0';
	}
}

void PrintQuotient(vector<int>& quotient)
{
	int size = quotient.size();

	if (size == 0) //몫이 없는 경우
	{
		cout << 0;
		return;
	}

	for (int i = 0; i < size; ++i)
	{
		cout << quotient[i];
	}
}

void PrintRemainder()
{
	int i = 0;

	while (i < moneyLength && moneyArray[i] == 0)
	{
		i++;
	}

	if (i < moneyLength) //나머지가 있는 경우
	{
		while (i < moneyLength)
		{
			cout << moneyArray[i];
			i++;
		}
	}
	else //나머지가 없는 경우
	{
		cout << 0;
	}

	cout << endl;
}

int Subtraction(int base)
{
	int index = base - personsLength + 1;
	//47664
	//46669
	//현재 base = 4, personsLength = 5로
	//index = 0 이 됩니다. 비교할 첫 시작점을 의미합니다.

	for (int i = 0; i < personsLength; ++i)
	{
		if (moneyArray[index + i] - personsArray[i] < 0) //앞에서 자리를 빌려와야됨
		{
			int j = 1;

			//47664
			//46669
			//0100 <4 - 9>
			//위 부분에서 앞자리에 빌려올 곳을 찾아야됩니다.
			while (index + i - j >= index && moneyArray[index + i - j] == 0)
			{
				j++;
			}

			if (index + i - j < index) //빌려올 곳이 시작지점을 넘어서면 못빌려옵니다.
			{
				return i; //뺄셈이 불가능하기에 빼준 앞 부분들까지 다시 더해주기 위해
						  //인덱스를 반환합니다.
			}

			moneyArray[index + i - j]--; //요기서 빌릴 수 있네요.
			j--;
			while (j > 0)
			{
				moneyArray[index + i - j] = 9; //빌려오면서 거친 부분들은 9로 만들어줍니다.
				j--;
			}
			//0100 -> 0099 가 됩니다.

			moneyArray[index + i] += 10 - personsArray[i]; //0099(14 - 9) = 00995
		}
		else //뺄셈이 가능하면 그냥 빼주기
		{
			moneyArray[index + i] -= personsArray[i];
		}
	}

	return -1; //뺄셈이 성공하면 다시 더해줄 필요가 없음
}

void Sum(int base, int limit) //뺄셈이 실패하기 - 1 지점까지 다시 더해서 복구해주기
{
	int index = base - personsLength + 1;

	for (int i = limit - 1; i >= 0; --i)
	{
		moneyArray[index + i] += personsArray[i];
	}
}

int main()
{
	string money, persons;
	vector<int> quotient;

	cin >> money >> persons;

	moneyLength = money.length();
	personsLength = persons.length();

	moneyArray.resize(moneyLength);
	personsArray.resize(personsLength);

	MakeIntArray(moneyArray, money, moneyLength);
	MakeIntArray(personsArray, persons, personsLength);

	for (int i = personsLength - 1; i < moneyLength; ++i)
	{
		//만약 1234 / 124의 경우
		//123 / 124 는 실패합니다.
		//이제 234 / 124 비교 차례인데
		//앞의 숫자(1)가 남아있는걸 갖고와주는 작업입니다.
		if (i - personsLength >= 0)
		{
			moneyArray[i - personsLength + 1] += moneyArray[i - personsLength] * 10;
			moneyArray[i - personsLength] = 0;
		}

		int div = 0; //몫

		while (true)
		{
			int failPos = Subtraction(i); //빼질때까지 계속 빼보기

			if (failPos > -1) //더이상 나눌수(뺄 수) 없으면 복구해주고 종료.
			{
				Sum(i, failPos);
				break;
			}

			div++;
		}

		if (quotient.size() == 0 && div == 0) //첫 몫이 0인지 확인
		{
			continue;
		}
		else
		{
			quotient.push_back(div);
		}
	}

	PrintQuotient(quotient);
	cout << " ";
	PrintRemainder();
}
using System;
using System.Net; //IPAddress, Dns
using System.Net.Sockets; //AddressFamily

namespace ConsoleServerTest
{
    class Program
    {
        public static void Main (string[] args)
        {
            PrintMyAddress();
        }

        private static void PrintMyAddress()
        {
            IPAddress[] host = Dns.GetHostAddresses(Dns.GetHostName());

            for (int i = 0; i < host.Length; ++i)
            {
                if (host[i].AddressFamily == AddressFamily.InterNetworkV6) //IPv6
                {
                    Console.WriteLine("IPv6 주소 [{0}]", host[i]);
                }

                if (host[i].AddressFamily == AddressFamily.InterNetwork) //IPv4
                {
                    Console.WriteLine("IPv4 주소 [{0}]", host[i]);
                }
            }
        }
    }
}

실행 결과

IP 주소는 고정 아이피를 신청하지 않는 이상 계속 바뀌게 됩니다.

다른 기기 (공유기, 스위칭 허브 등) 연결 없이 바로 연결했기 때문에

바로 제가 쓰고 있는 유동 아이피가 나온 모습입니다 ㅎㅎ

+ Recent posts