C 프로그래밍을 하다보면,, 새로운 기능을 추가하기 위해서,, 기존의 함수를 변경해야 할 일이 발생한다.. 하지만,, 반드시 파라미터를 추가해야 하는 경우가 발생하면,, 조금 골치 아파 진다..

예를 들어 int foo (int a) 라는 함수가 있다고 하자,, 게다가 이 함수는 수도 없이 많은 곳에서 호출되어 사용된다고 가정하자.. 그러기에,, foo() 함수의 파라미터을 함부로 변경 하기에는 무리가 있다..

이런 상황에서 foo() 함수와 거의 유사한 기능을 하는 또 다른 함수를 작성해야 한다..

많은 초보들이 int foo (int a) 를 copy & paste 해서 int foo2 (int a) 를 만들어 쓴다는 것이다..

이거 무지무지 좋지 않은 코딩 방법이다..

첫번째로 소스코드가 그만큼 길어진다.. 새로운 기능이 늘어날때마다,, 새로운 함수가 추가되면,, 유사한 기능을 하는 코드가 복사된다.. 소스는 커질수록 관리가 안된다..

두번째로,, foo() 함수의 원 저자가 버그를 발견하고 foo() 함수를 수정해 놓을 수가 있다.. 이런 경우 foo2() 함수의 버그는 수정되지 않는다..

그렇다고 기존의 foo 함수를 int foo (int a, int option) 처럼,, 파라미터를 추가해 버리면,, 기존의 foo 를 호출하는 수많은 모듈에서 에러가 발생한다..

C++ 에서는 default parameter 라는 기능을 사용하면,, 에러가 발생하는 것은 피할수 있지만,, C 에서는 제공하지 않는다..

대신 이를 흉내내는 형태로 코딩할 수 있다..

int foo(int a)
{
    // foo function body;
    return 0;
}

원래는 이랬던 함수를

int foo_with_option(int a, int option);  /* declaration */

#define FOO_DEFAULT_OPTION 0

int foo(int a)
{
    return foo_with_option(a, FOO_DEFAULT_OPTION);
}

int foo_with_option(int a, int option)

{
    // foo function body;
   if (option == 1)
        // do something

    return 0;
}

위와 같이 바꾸어 버리면 된다.. 기존의 foo () 함수를 foo_with_option() 로 바꾸면서, 필요한 파라미터를 추가한다.. 그리고,, 원래의 foo() 함수와 같은 타입으로 함수를 선언한뒤 foo_with_option() 를 호출하게끔 한다.. 당연히 원래의 기능을 동일하게 동작하도록 추가된 파라미터 입력을 주면 된다..

즉, option 이 FOO_DEFAULT_OPTION( = 0 ) 인 경우는 원래의 foo() 함수와 동일하게 동작하고,, option 이 다른 값이면,, 다르게 동작하게 바디를 수정해 주면 된다.. 그리고 나서는 새 모듈에서 foo_with_option() 을 호출해서 사용하면 된다..

이렇게 작성할 경우, 위에서 언급했던 2가지 문제가 모두 해결된다.. 같은 코드를 재사용하기에,, 코드가 간결하고 이해하기 쉽게 된다.. 기존의 foo() 만 알고 있던 사람도 foo() 가 변경되었음을 명확히 알게 되며,, option 에 추가된 경우를 고려해서 버그를 수정할 수 있게 된다.. 게다가,, 아무런 컴파일 문제를 야기하지 않는다..

#ifdef __FOO_WITH_OPTION_FEATURE__
int foo_with_option(int a, int option);  /* declaration */

#define FOO_DEFAULT_OPTION 0

int foo(int a)
{
    return foo_with_option(a, FOO_DEFAULT_OPTION);
}

int foo_with_option(int a, int option)
#else
int foo(int a)
#endif

{
    // foo function body;
#ifdef __FOO_WITH_OPTION_FEATURE__
    if (option == 1)
        // do something

#endif
    return 0;
}

추가적으로 이걸 #ifdef 으로 막아줄 수 있다면,, 금상첨화 되겠다..

- 이쁜왕자 -
- Valken the SEXy THief~~ ^_* -
 

Posted by 이쁜왕자

modulo

모듈로 ( modulo ) 연산자

C 언어에서 % 는 모듈로 연산이며,, 일반적으로 자연수 나눗셈의 나머지 값을 구하는 목적으로 사용된다.. 문제는 이게 음수에 적용되면 아주 골때린 문제를 야기한다..

int a = 12;
printf ("a = %d , a/10 = %d , a%10 = %d\n", a, a/10, a%10);

위와 같은 코드가 있다고 하자.. 이는 별 문제 없이.. 다음과 같은 결과를 낸다..

a = 12, a/10 = 1, a%10 = 2

만약 a = 12 가 아니라 음수인 -12 이면 어떤 출력을 내는지 추측해 보자..

결과는 다음과 같다..

int a = -12;
printf ("a = %d , a/10 = %d , a%10 = %d\n", a, a/10, a%10);
a = -12 , a/10 = -1 , a%10 = -2

음수에 대해서 모듈로 연산을 하면 그 결과 음수가 나온다.. 이에 대한 이유는 사실 간단하다..

피젯수 = 몫 * 젯수 + 나머지

이라는 아주 당연한 식 때문이다.. 12 = 1 * 10 + 2  이기 때문에 12 / 10 = 1 이고, 12 % 10 = 2 이다.. a= -12 인 경우를 생각하면,, -12 = (-1) * 10 + (-2) 이기 때문에 -12 / 10 = -1 이고, -12 % 10 = -2 가 된다..

문제는 어찌보면 당연한 이것 때문에 여러곳에서 문제가 생긴다.. 예를 들면.. 다음과 같은 것이 있다..

변수 b 는 백분률의 x10 한 값을 저장하는 변수 이다.. 34.5% 는 변수 b 에 345 라는 int 값으로 저장된다.. 이처럼 실제로는 실수 이지만,, n 배한 값을 정수 변수에 저장하는 경우도 있다.. 이 b 를 백분률로 출력해주는 함수는 보통 이렇게 만들어 진다..

int b = 345;
printf ("b = %d.%1d%%\n", b/10, b%10);
b = 34.5%

b 가 0 보다 큰 양수값을 가지는 동안에는 아무런 문제가 없지만,, b 가 음수가 되면 바로 문제가 발생한다.. 만약 b = -345 라고 하면,, 다음과 같이 출력된다..

int b = -345;
printf ("b = %d.%1d%%\n", b/10, b%10);
b = -34.-5%

이를 보정하기 위해서 다음과 같이 바꿀 수 있다..

int b = -345;
printf ("b = %d.%1d%%\n", b/10, (b>=0)? b%10:(-b)%10);
b = -34.5%

일단은 제대로 동작하도록 수정한듯 싶지만,, 여전히 문제가 남아 있다.. b = -5 인 경우는 이렇게 된다..

int b = -5;
printf ("b = %d.%1d%%\n", b/10, (b>=0)? b%10:(-b)%10);
b = 0.5%

정상적이라면 -0.5% 여야 하지만,, -5 / 10 = 0 이기에, 음수 부호가 찍히지 않고,, 그로 인해서 음수가 양수로 바뀌어 찍혀 버린다..  이걸 바꾸는 건 그리 만만치가 않다.. 결국 if 문으로 음수 양수 구분해서 해결해야 한다..

int b = -5;

if (b>=0)
  printf ("b = %d.%1d%%\n", b/10, b%10);
else
  printf ("b = -%d.%1d%%\n", (-b)/10, (-b)%10);
b = -0.5%

이제 거진 문제가 해결된 듯 싶다.. 하지만,, 아직도 넘어야 할 산이 있다.. 출력되는 숫자의 자리수의 위치를 맞추고 싶다.. 양수인 경우는 %5d 등을 이용하면 쉽게 해결된다.. 부호 포함 정수부 5자리, 소수점 이하 1자리를 출력하고프면 다음과 같이 하면 된다.. 양수의 경우는 쉽게 해결되지만,, 음수인 경우는 점점 산으로 가게 된다..

int b = -5;

if (b>=0)
  printf ("b = %5d.%1d%%\n", b/10, b%10);
else
{
  char temp_buf[20];
  sprintf(buf, "-%d.%1d", (-b)/10, (-b)%10);
  printf ("b = %7.7s%%\n", buf);
}


b =    -0.5%

아무래도 왠만하면 double 이나 float 를 쓰는 방향으로 다시 고려해야 아닌가 싶어 진다..
저런 골치아픈 문제가,, 이렇게 간단하게 해결되니 말이다..

int b = -5;
printf ("b = %7.1lf%%\n", (double)b/10.0);

b =    -0.5%

- 이쁜왕자 -
- Valken the SEXy THief~~ ^_* -
Posted by 이쁜왕자

다음과 같은 조건을 만족하는 printf format 을 만드시오.

1. 출력하고자 하는 데이터는 string 이다.
2. string 이 10자 보다 길면, 앞에서 10자까지 짜른다.
3. string 이 10자 보다 짧으면, 오른쪽에 공백을 채워 10자를 만든다.
4. 별다른 string 연산 없이 printf format 만으로 해결하라.

입력 "abcde"
출력 [abcde_____]    (괄호는 공백를 표현하기 위함, 언더바는 공백)

입력 "abcdefghijklmn"
출력 [abcdefghij]

이거 정답은 찾긴 찾았는데, 이런식으로 printf 포맷팅을 해보긴 처음이군요. 한번 맞춰 보세요.

- 이쁜왕자 -
- Valken the SEXy THief~~ ^_* -

Posted by 이쁜왕자

BLOG main image
이쁜왕자 만쉐~~
이쁜왕자 만쉐이~~ 만쉐이~~ 만만쉐이~~ by 이쁜왕자

공지사항

카테고리

분류 전체보기 (438)
사진첩 (5)
낙서장 (179)
게임판 (113)
퍼즐판 (39)
지름신 (30)
캐슬라이프 (47)
퍼온것들 (24)

글 보관함

달력

«   2012/02   »
      1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29      
Total : 472,675
Today : 202 Yesterday : 272