C2009.12.14 01:44


이번 강좌에서는
  • 함수의 필요성
  • 함수의 의미, 함수의 인자, 함수의 리턴값, 함수 내부에서 선언된 변수
  • main 함수

x + 4bc + 4d

  안녕하세요 여러분. 이 강좌를 읽고 있을 여러분은 포인터의 고지를 정복하고 온 위대한 전사(?) 들 입니다. 이제, 앞으로 다룰 내용은 C 언어에서 중요하면서도 쉬운 부분 이니 큰 부담 없이 편히 읽으시면 합니다. 또한, 앞에서 배운 포인터를 이제 본격적으로 활용하는 단계에 접어들기 때문에 혹여라도 잊은 것이 있는지 없는지 매일 한 번씩 다시 정독하시면 좋습니다. 또는, 다른 C 언어 강좌로 한 번 더 공부해 보세요. 다른 방식으로 공부하다 보면 이해가 더 잘될 수 도 있습니다.


  저는 제 강좌에서 여러분이 최소한 초등학교 4 학년 정도의 수학을 이수하셨다면 아래와 같은 문제를 본 기억이 어렴풋이나마 있을 것 입니다.
 
이 상자는 들어간 값에 4 를 더한 게 튀어나온다. 36 을 집어넣으면 뭐가 튀어나올까요!!
  음.. 아래 물음표에서 어떤 값이 출력될까요? 아마, 여러분 대부분은 '40' 이라고 짐작하실 것입니다. 맞습니다. 40 입니다. 위 마술 상자는 입력 받은 값에 4 를 더해서 출력하는 상자 입니다. 만일 우리가 36 이 아니라 10 을 집어넣었다면 14 가 나왔을 것이지요. 수학에서 함수는 마술 상자와 비슷합니다. 특정한 값을 입력 받아, 이 값을 가지고 상자 내부에서 지지고 볶고 해서 결과를 내보낸 마술 상자 처럼, 수학에서는 특별한 값 x 를 입력 받아 지지고 볶은 뒤(유식한 말로 연산을 취하여)에 결과를 출력하는 것을 함수 라고 합니다. (참고적으로, 수학에서 보통 입력값은 x, 출력값은 y 라고 하니, 아래에선 아무런 이야기 없이 사용하도록 하겠습니다.)

  수학에서 마술 상자를 글로 표현하기 조금 껄끄러우니 보통 다음의 표현을 사용합니다. (y = f(x) )



  이는, 'x 라는 값을 f 라는 마술 상자 (함수) 를 통과시켰더니 y 라는 값이 되었다' 라는 의미와 일맥 상통합니다. 위의 마술 상자의 경우 입력값에 4 를 더한 값을 반환하였습니다. 그렇다면, 위의 마술 상자는 아래와 같은 식으로 나타낼 수 있습니다.( f(x) = x + 4 )



  예를 들어 x 에 36 이 들어간다면 f(x) 의 값, 즉 y 의 값은 36 + 4 인 40 이 됩니다. 따라서, 40 이 출력된다는 사실을 볼 수 있습니다. 그렇다면, 아래의 예를 보고 어떠한 값이 출력되는지 맞추어 보세요. ( f(x) = x 의 3 승 + 2x 일 때 f (3) 은? 또한 g(x) = x 제곱 - 3x + 4 일 대 g(5) 는? )



(이례적으로 답을 올리자면 f(3) = 33, g(5) = 14. 참고로 g 가 나와서 당황하실 수 도 있는데, 단지 f 나 g 는 함수의 이름을 의미한 것입니다. 다시말해 f 나 g 말고도 다른 여러분의 원하시는 문자를 선택하시면 됩니다. 다만, f 가 function 의 앞글자 이기 때문에 f, g, h.. 순으로 함수의 이름을 정하는 경우가 대다수 입니다. )

  간혹 제 블로그를 방문하는 분들 중에는 초등학생인 분들이 있기에, 함수를 전혀 들어보지 못한 분들이 있을 까봐 짤막하게 함수에 대해 설명하였습니다. C 언어의 함수도 비슷한 개념으로 사용됩니다.

   함수의 시작
 

  우리가 프로그래밍을 하면서 여러가지 작업들을 반복적으로 해야되는 경우가 종종 있습니다. 예를 들어서 변수 a 와 b 중 최대값을 구하는 것을 생각해봅시다. 우리가 이를 프로그래밍 시에 필요로 하게 된다면 다음과 같이 해야 될 것입니다.

    int max;
    if(a >= b)
    {
        max = a;
    }
    else
    {
        max = b;
    }

  뭐, 위 코드는 아주 아주 쉬운 코드 이니 설명은 하지 않겠습니다. 그런데, 실제로 프로그래밍을 하다 보면 어떠한 두 변수의 최대값을 구하는 경우가 자주 생긴다는 것입니다. 현재 까지 배운 바로는 이러한 상황에서는 Ctrl + C, Ctrl + V 신공을 통해 소스를 채워나가면 된다고 생각했습니다. 자, 그렇다면 이러한 방법이 합리적인 것일까요? 만일 최대값을 구하는 것이 프로그램에서 100 번 정도 필요하다면 그 때 마다 위 코드를 복사해서 변수 이름만 살짝 바꿔주면 됩니다. 하지만, 소스가 얼마나 지저분해질까요? 소스가 수천줄이 넘어가면 위 코드가 무슨 작업을 하는지 눈에 팍 들어오기 힘듧니다.

  그렇다면 여러분은 이렇게 생각해 볼 수 있습니다.

  "최대값을 출력하는 함수를 만들어버리자!!"

  응? 도대체 위 말이 무슨뜻인감.. 아마도 여러분은 갈피를 잡기 힘들 것입니다. 하지만 이렇게 생각하면 편합니다. '아까 위에서 설명한 마술 상자 처럼 우리가 만들게 될 마술상자는 두 개의 값이 입력된다면 큰 놈을 출력하는 것이야'. 오오. 괜찮은 아이디어 아닌가요. 우리는 그 긴 코드(사실 그렇게 긴 것은 아니지만;;) 를 매번 쓰는 대신에 두 값을 입력받아서 큰 것을 출력하는 마술 상자 (함수) 를 제작하여, 최대값을 구하는 것이 필요할 때 마다 그 마술 상자에 두 변수를 넣어 버리면 되지 않습니까? 그러면 우리는 그 마술 상자가 뱉어내는 값을 받아 먹기만 하면 되는 것이니까요.

  자, 그럼 마술 상자를 만들어봅시다~

  일단, 최대값을 구하는 함수를 만들어 보기 전에 아주 아주 간단한 함수를 먼저 만들어보겠습니다.

#include <stdio.h>
/* 보통 C 언어에서, 좋은 함수의 이름은 그 함수가
무슨 작업을 하는지 명확히 하는 것이다. 수학에서는
f(x), g(x) 로 막 정하지만, C 언어에서는 그 함수가 하는
작업을 설명해주는 이름을 정하는 것이 좋다. */
int print_hello()
{
    printf("Hello!! \n");
    return 0;
}
int main()
{
    printf("함수를 불러보자 : ");
    print_hello();

    printf("또 부를까? ");
    print_hello();
    return 0;
}

  성공적으로 컴파일 하였다면


  음.. 일단 우리가 여태까지 보아왔던 것과 매우 다른 모습입니다. 하지만 걱정하지 마세요. 금세 이해하게 될 것이니까요.

int print_hello()
{
// 잠시 생략
}

  일단, 함수의 정의(definition) 부분을 살펴 봅시다. 위와 같이 'int print_hello()' 라고 써 있는 부분을 함수의 '정의' 부분이라 부릅니다. 우리는 함수의 정의 부분에서 3 가지 사실을 알 수 있는데, 일단은 2 가지만 먼저 설명하고 나머지 하나는 아래에서 설명하겠습니다.

  먼저, 우리에게 친근한 키워드가 하나 있습니다. 바로 int ! 우리는 여태까지 int 를 변수나 배열을 정의하는데만 사용하였습니다. 그런데, int 가 놀랍게도 함수를 정의하는데도 사용되고 있습니다. 여기서의 int 는 다음과 같은 사실을 알려줍니다. '이 함수는 int 형의 정보를 반환한단다~'. 반환? 그렇다면 반환은 또 뭐야.

  우리가 앞서, 마술 상자를 이야기 하였을 때, 우리가 36 을 마술 상자에 넣는다면, 4 를 더해서 40 을 출력한다고 하였습니다. 이 때, 우리는 '출력된다' 라는 사실을 함수에서는 '반환한다' 라고 이야기 합니다. 영어로는 return 이라고 하지요.

int print_hello()
{
    printf("Hello!! \n");
    return 0;
}

  위 함수 정의 부분에서, 아래에서 두번째 줄에 return 0; 라고 써있는 부분을 볼 수 있습니다. 이 함수는 0 을 반환한다는 뜻이군요. 즉, 우리가 위와 같은 마술 상자를 이용한다면 언제나 0 이 출력됩니다. 이 때, 함수의 반환형이 int 이므로, 0 은 int 의 형태로 저장되어 나갑니다. 여기서 'int' 의 형태로 저장된다는 말의 의미는 0 이라는 데이터가 메모리 상의 4 바이트를 차지하여 반환된다는 뜻이지요. (* 통상적으로 정수를 반환하는 함수들은 모두 int 를 사용합니다. )

 함수의 정의 부분에서 알 수 있는 두 번째 사실은 바로 함수의 이름 입니다. 대충 짐작이 가듯이, 위 함수의 이름은 print_hello 입니다. 끝에 붙는 () 는 함수의 이름에 포함되는 것이 아닙니다. 끝에 붙는 괄호 두 개는 이것이 '함수' 라는 사실을 의미합니다. 만일 우리가 끝에 () 를 붙이지 않는다면 int print_hello 라는 문장은 단순히 끝에 ';' 를 제대로 붙이지 않았구나 라고 해석되어 오류를 출력하게 됩니다. 꼭 () 를 붙여주세요~

  주석에서도 잘 설명 하였듯이 좋은 함수 이름의 조건은 함수가 무슨 일을 하는지에 대해서 잘 설명하는 것 입니다. 만일 우리가 함수를 int asdfasd() 라고 만들었다면 우리가 asdfasd 라는 함수를 보고 무슨 일을 하는지 잘 알 수 없습니다. 하지만 우리의 예제 처럼 print_hello 라고 하게 된다면 이 함수가 대략 'hello 를 출력하는구나' 라는 사실을 알 수 있겠지요. 다만, 함수의 이름이 너무 길어지면 함수를 사용시 너무 불편하므로 20 자가 넘어가게 하지는 맙시다. 또한, 함수의 이름 역시 변수의 이름 조건과 동일하므로 기억나지 않는 분들은 3강 변수가 뭐지? 의 맨 마지막 부분을 보세요.

int print_hello()
{
    printf("Hello!! \n");
    return 0;
}

 함수의 정의부분은 그만 살펴보고, 이제 함수가 무슨 일을 하는지 알 수 있는 부분을 살펴 봅시다. 이 부분은 보통 함수의 몸체(body) 라고 부릅니다. 이번 예제 함수의 몸체는 설명을 안해도 잘 알 수 있습니다. 이 함수는 printf("Hello!! \n"); 을 실행한 후, 0 을 반환한다 이지요?

    printf("함수를 불러보자 : ");
   print_hello();

    printf("또 부를까? ");
   print_hello();

  마지막으로 실제로 함수를 호출하는 부분을 살펴 봅시다. 함수를 불러내는 방법(보통 '호출한다(call)' 라는 표현을 사용하므로 앞으로 호출한다고 표현하겠습니다) 은 단순히 함수의 이름을 써주시기만 하면 됩니다. 물론 그 뒤에 () 도 붙여주어야 겠지요. 다시 말하지만 () 는 함수의 이름에 포함되는 것이 아닙니다. 하지만, () 를 써줌으로써 컴파일러에게 '내가 지금 쓴 것이 함수 이니라~' 라는 사실을 말해주게 되는 것이지요. 만일 함수를 호출한답시고 print_hello; 라고 쓴다면 컴파일러는 '어딘가에 print_hello 라는 변수에 접근하였네' 라고 생각하는데, print_hello 라는 변수가 없으므로 오류를 출력하게 됩니다.

  함수를 호출하면 프로그램은 함수의 내용을 실행하게 됩니다. 그리고 다시, 원래 실행되려는 부분으로 돌아오게 되죠. 위의 경우, "함수를 불러보자" 가 출력된 후 print_hello() 를 통해 함수를 호출하였습니다. 그러면 프로그램은 print_hello() 라는 함수로 넘어가서, 이 함수의 내용을 다 실행한 뒤에 다시 원래 있던 곳으로 돌아와 넘어가게 됩니다.

  이와 같은 현상은 실생활에서도 볼 수 있습니다. 밥을 먹고 있다가 '엄마가 부르신다' 라는 함수가 호출되면 엄마한테로 달려갑니다. 그리고 '엄마가 부르신다' 라는 함수가 종료되면 다시 밥 먹던 식탁으로 와서 밥을 먹게 되지요. 이 때, 함수의 종료는 두 가지 형태로 있을 수 있습니다. 하나는 반환이 되어 종료를 하게 되는 것이고 다른 하나는 함수의 끝 부분 까지 실행하여 종료되는 것입니다. 함수는 반환을 하여 종료되는 것이 안전합니다. 한 가지 중요한 사실은 return 을 실행하면 함수는 무조건 종료되어 함수를 호출하였던 부분을 돌아간다는 점입니다.

/* 함수의 리턴 */
#include <stdio.h>
int return_func()
{
    printf("난 실행된다 \n");
    return 0;
    printf("난 안돼 ㅠㅠ \n");
}
int main()
{
    return_func();
    return 0;
}

  성공적으로 컴파일 한다면


  물론 앞에서 이야기 하였듯이 짐작은 하고 있으셨겠지만 확실히 보여드리기 위해 예제를 작성하였습니다.

int return_func()

  연습 삼아 위 부분이 무슨 의미인지 다시 한 번 살펴봅시다. 일단, int 를 보아 이 함수는 int 형을 리턴한다는 의미이고, return_func 을 보아서 이 함수의 이름이 return_func 라는 사실을 알 수 있습니다.

{
    printf("난 실행된다 \n");
    return 0;
    printf("난 안돼 ㅠㅠ \n");
}

  다음은 함수의 몸체 입니다. 앞에서 이야기 하였듯이 return 이 실행되면 프로그램은 바로 함수를 호출하였던 부분으로 넘어가 버려 그 다음에 오는 모든 것들(위 예제에선 printf("난 안돼 ㅠㅠ \n"); ) 이 실행되지 않게 됩니다.

  이와 같은 현상도 실생활에서 찾아 볼 수 있습니다(웃음). 늘 컴퓨터 게임만 하는 아이가 있습니다. 그는 24 시간 컴퓨터 게임만 합니다. 이를 도저히 참지 못한 엄마는 '공부하기' 라는 함수를 만들었습니다. 엄마가 '공부하기' 함수를 호출하였더니 (놀랍게도) 이 아이는 공부하기 함수의 내용을 실행합니다. 공부하기 함수에는 'C 언어 공부하기', '숙제하기' 등등의 작업들이 있었는데, 공교롭게도 엄마가 실수로 'C 언어 공부하기' 와 '숙제하기' 사이에 '공부 끝' 이라는 return 문장을 집어 넣은 것입니다! 결과적으로 이 아이는 C 언어 공부하기를 다 실행하자 마자, '공부 끝' 이 실행되어 (함수의 return) 결국 원 상태로 돌아가 다시 컴퓨터 게임을 하기 시작하였습니다.

/* 반환값 */
#include <stdio.h>
int ret()
{
    return 1000;
}
int main()
{
    int a = ret();
    printf("ret() 함수의 반환값 : %d \n", a);

    return 0;
}

  성공적으로 컴파일 한다면


  마지막으로 한 번더, 함수의 정의 부분을 분석해봅시다.

int ret()

  아마 이쯤 되면 여러분은 위 것만 보고도 이 함수는 이름이 ret 이고, int 형을 반환한다 라는 사실을 알 수 있을 것 입니다.
그리고 ret 함수의 몸체를 살펴 보자면 상당히 간단하다라는 것을 알 수 있습니다.

{
    return 1000;
}

  그리고 위 코드는 "이 함수를 호출하면 1000 을 리턴한다" 정도 되겠지요.

int main()
{
    int a = ret();
    printf("ret() 함수의 반환값 : %d \n", a);

    return 0;
}

  위는 ret() 함수를 호출하여 그 값을 a 에 대입하는 문장 입니다. 그런데 ret() 가 가지는 값이 있나요? 물론, ret() 는 함수이기 때문에 위와 같이 이용하면 안될것 같습니다만, ret() 를 코드에 쓰게 된다면 이 말은 "ret() 함수의 반환값" 라는 의미를 가집게 됩니다. 즉, 컴퓨터가 위 코드를 실행한다면 a 에는 ret 함수의 반환값인 1000 이라는 값이 들어가게 됩니다.

  아무튼 아래의 유명한 격언을 기억하시기 바랍니다.

  "호랑이는 죽어서 가죽을 남기고, 함수는 죽어서 리턴값을 남긴다"

   메인(main) 함수
 

  아마 꼼꼼하신 여러분들은 이미 int main() 이란 부분도 main 이라는 함수를 정의하고 있다는 사실을 눈치 채고 있을 것입니다. 맞습니다. 여러분은 main 이라는 이름의 함수를 정의하고 있는 것이였습니다. 그런데 왜 하필이면 main 일까요?

  왜냐하면 프로그램을 실행할 때 컴퓨터가 main 함수 부터 찾기 때문입니다 (물론 모든 경우가 그런 것은 아니고 적어도 우리가 앞으로 만들게 될 C 프로그램들의 경우). 즉, 컴퓨터는 프로그램을 실행할 때 프로그램의 main 함수를 호출함으로써 시작합니다. 만일 main 함수가 없다면 컴퓨터는 프로그램의 어디서 부터 실행할 지 모르게 되어 오류가 나게 되죠.

  보통 메인 함수를 아래와 같은 형태로 정의합니다.

int main()

  위에서 배운 내용을 살짝 활용하면 "이 함수는 리턴형이 int 이고 이름은 main 이네!" 정도 알 수 있겠지요. 그런데, 메인 함수가 리턴을 하면 누가 받을까요? 메인 함수가 프로그램 맨 처음에 실행되는 함수라면, 맨 마지막으로 종료되는 함수도 메인 함수 이기 때문에 리턴값을 받을 수 있는 함수가 없을 듯 합니다.

  사실, 그렇지 않습니다. 메인 함수가 리턴하는 데이터는 바로 운영체제가 받아들입니다. 운영체제. 즉 여러분이 아마도 쓰고 계실 Windows XP 나 Linux 에서 받는 다는 이야기 이지요. 보통 메인 함수가 정상적으로 종료되면 0 을 리턴하고, 비정상적으로 종료되면 1 을 리턴한다고 규정되어 있습니다. 우리가 여태까지 만들어왔던 모든 메인 함수들은 정상적으로 종료되므로 마지막에 0 을 리턴하였죠. 사실, 1 을 리턴한다고 해서 큰 문제는 없습니다. 이 정보를 활용하는 경우는 매우 드물기 때문이죠.

  아무튼, 여기서 알아야 할 사실은 "main 도 함수다!" 정도만 알아 두셨으면 합니다.

  이번에는 맨 위에서 구상하였던 마술 상자 ( 4 를 더한값을 출력하는..) 를 제작해보기로 하였습니다. 일단 여러분은 아래와 같이 구현할 수 있지 않을까 라는 것을 머리속에 떠올릴 것입니다.

/* 마술 상자 */
#include <stdio.h>
int magicbox()
{
    i+=4;
    return 0;
}
int main()
{
    int i;
    printf("마술 상자에 집어넣을 값 : ");
    scanf("%d", &i);

    magicbox();
    printf("마술 상자를 지나면 : %d \n", i);
    return 0;

}

  컴파일 하면 아래와 같이 달콤한 오류를 볼 수 있습니다.

error C2065: 'i' : 선언되지 않은 식별자입니다.

  아니, 왜? 이런 오류가 뜨는 것이지.. 분명히 우리는 main 함수 내에서 i 라는 이름의 int 형 변수를 선언하였고 다른 함수(magicbox) 에서 사용할 수 있어야 되는 것 아닌가요? 하지만 안타깝게도 아닙니다. 사실, 이 마술상자는 우리가 생각했던 것 보다도 훨씬 멋진 개념입니다.

  어떠한 함수를 호출할 때, 호출된 함수는 함수를 호출한 놈에 대해서 어떠한 것도 알고 있지 않습니다. 즉, 내가 magicbox 라는 함수를 호출하였을 때, 이 magicbox 는 내가 얘를 호출하였는지, 다른 애가(즉, 다른 코드를 말하는 것이겠죠;;) 얘를 호출하였는지 '전혀 알 수 없다' 라는 것입니다.

int magicbox()
{
    i+=4;
    return 0;
}

  따라서 이 함수는 i 라는 변수에 대해서 아무런 정보도 가지지 않고 있습니다. 왜냐하면 이 함수를 호출한 것이 무엇인지에 대한 정보가 하나도 없기 때문이죠. 결과적으로 main 함수에서 정의된 i 라는 변수는 magicbox 의 입장에서 본다면 듣도 보도 못한 것이 되는 것입니다. 결과적으로 위에서 보았던 오류와 같이 i 라는 변수가 선언되어있지 않다는 오류를 내게 됩니다.

  아직도 위 코드가 왜 작동이 되지 않는지 이해가 되지 않으신 분들은 아래의 옛날 이야기(?) 를 보시면 됩니다.

  옛날 옛날 이집트 시대에 어떤 부유한 귀족이 있었습니다. 이 귀족은 하루에 10000 달러[각주:1]씩 장사를 해서 벌었습니다. 그런데 공교롭게도 수학을 매우매우 못했죠. 따라서, 이 귀족은 노예를 한 명 사서, 이 노예에게 자신의 현재 재산에 10000 을 더해서 알려 달라고 하였습니다. 그리고 시간이 흘러 10 시간 뒤, 귀족의 일과가 끝났습니다. 이제, 그는 오늘 자신의 재산 현황을 파악하기 위해서 노예를 호출했습니다.

"야 말해"

  그런데 노예는 아무 말도 하지 못했습니다.

"야 말하라고, 내 재산에 10000 을 더해서 말하라니까"

  역시 아무말도 없었습니다. 왜일까요? 그야, 당연히 노예는 귀족의 재산에 대한 정보가 없었기 때문입니다. 귀족이 방금 노예를 호출함으로써 한 일은, "자신의 재산 += 10000" 이였습니다. 그런데, '자신의 재산' 이란 변수는 노예의 머리에서 정의된 것이 아니므로 알 노릇이 없습니다.
 
 그렇다면, 이제 아무 쓸모 없게된 불쌍한 노예를 악랄한 귀족이 죽이게 내버려 두어야 하나요? 물론, 그리하면 안되겠죠. 일단, 여기서 문제점을 해결하기 위해선 노예가 "현재 귀족의 재산" 이라는 데이터만 머리에 넣고 있으면 됩니다. (노예가 계산을 충분히 잘한다는 가정 하에..) 이 말을, C 언어 적으로 이야기 하면 노예라는 함수에 "주인의 현재 재산" 이라는 변수를 정의하고 이 변수에 "자신(주인)의 재산" 의 값을 넣은 뒤에, "주인의 현재 재산+=10000" 을 계산한 후, "주인의 현재 재산" 을 반환(입으로 말함) 하면 되는 것입니다.

  이제, 문제는 노예 머리속에 "주인의 현재 재산" 이라는 변수에 "자신(주인) 의 재산" 값을 어떻게 넣느냐가 문제 입니다. 바로 아래에서 보도록 하죠.

   함수의 인자 
 

#include <stdio.h>
int slave(int master_money)
{
    master_money += 10000;
    return master_money;
}
int main()
{
    int my_money = 100000;
    printf("2009.12.12 재산 : $%d \n", slave(my_money));

    return 0;
}

  성공적으로 컴파일 하면


  일단, 함수의 정의 부분이 바뀐 것을 볼 수 있습니다.

int slave(int master_money)

  slave 가 함수 임을 알려주는 소괄호 안에 'int master_money' 가 써 있군요. 이는 다음과 같은 의미를 가집니다.

"나를 호출하는 코드로 부터 어떤 값을 "mater_money" 라는 int 형 변수에 인자(혹은 매개변수라고도 부름)로 받아들이겠다!"

  허걱.. 정말 뭔소린지 알 수 없군요. 먼저 '인자' 가 무엇인지 살펴 보도록 합시다. 아까 전에 우리는 노예의 머리속에 '현재 주인이 가지고 있는 재산' 이라는 값을 어떻게 입력해야 할지가 문제라고 하였습니다. 그런데, slave 함수와 main 함수는 전혀 별개의 함수 이기 때문에 slave 함수는 main 함수 안의 변수를 사용할 수 없을 뿐더러 main 함수에서도 slave 함수의 변수들이 무엇인지 전혀 알 길이 없습니다.

  하지만, 인자(argument, 하지만 대다수의 경우 매개변수(parameter) 라고 부른다. 하지만 여기서에서는 인자라고 부르겠다. 왜냐하면 타이핑 하기 더 짧기 때문) 를 이용하면 이러한 일을 가능하게 합니다. 일단, 인자는 직관적으로 봐도 알 수 있듯이 slave 함수 내에 선언이 되어 있는 변수 입니다. 이 때, 인자는 함수 정의할 때의 소괄호 안에 나타나게 되죠. 위의 경우 slave 함수는 int 형의 master_money 라는 변수를 인자로 가지고 있습니다. 이제, 이 함수를 어떠한 함수에서 호출을 한다고 합시다. 그렇다면, 이 함수를 호출 할 때, 인자에 적당한 값을 넣어 주어야 합니다. 마치 아래와 같이요.

  slave(500);

  이 말은 "slave 함수를 호출할 때, slave 함수 안에서 정의된 master_money 라는 변수에 500 이라는 을 전달하겠다!" 라는 의미가 되겠지요.따라서, slave 함수 내부에 정의된 master_money 라는 변수에는 500 이라는 값이 들어가게 됩니다. 그렇다면 아래는 어떨까요?

  slave(my_money);

 이 것도 마찬가지 입니다. 이렇게 이용한다면 "slave 함수를 호출할 때, slave 함수 안에서 정의된 master_money 라는 변수에 my_money 의 을 전달하겠다!" 가 되겠지요. 만일 my_money 에 10000 이 있었더라면 slave 함수를 호출 시에 master_money 에는 10000 이 들어가게 됩니다. 결론적으로 말하자면 함수의 인자는 '함수를 호출한 것과, 함수를 서로 연결해 주는 통신 수단' 이라고 말할 수 있습니다. 이러한 연유에서 수학적인 용어로 틀린 표현 이지만 C 에선 '매개 변수' 라고 부릅니다.

  그렇다면, 위의 예제를 한 번 살펴볼까요?

int main()
{
    int my_money = 100000;
    printf("2009.12.12 재산 : $%d \n", slave(my_money));

    return 0;
}

  일단, slave 함수를 호출하는 호출자(caller) 의 코드를 살펴봅시다. printf 에서, 맨 뒤에 %d 에 들어갈 값으로 slave(my_money) 가 반환 하는 값을 넣었습니다. slave(my_money) 가 반환하는 값을 먼저 넣기 위해선 slave 함수를 호출해야 하는데 이 때 my_money 의 값이 slave 함수의 인자로 전달이 됩니다. 그러면 slave 함수는 아래의 코드를 실행하겠지요.

{
    master_money += 10000;
    return master_money;
}

  즉, master_money 에 10000 을 더한 후, 그 값을 반환하게 됩니다. 따라서, 100000 에 10000 이 더해진 110000 이 출력되겠지요.

  참고적으로, 많은 책에서 C 언어의 인자들을 '매개 변수' 라는 이름으로 부르는데 이것이 왜 수학적으로 틀렸는지 궁금하신 분들은 아래의 접혀진 글을 보시면 됩니다. 다만, 고등학교 이상의 수학 과정을 밟지 못한 분들은 안보시는 것을 추천합니다. 괜히 머리만 아파질 뿐이지요.

왜 수학적으로 틀렸는가?


이번에는 과연 성공적으로 컴파일 될지 의문이 드는 예제를 한 번 만들어 보았습니다.

/* 될까용 */
#include <stdio.h>
int slave(int my_money)
{
    my_money += 10000;
    return my_money;
}
int main()
{
    int my_money = 100000;
    printf("2009.12.12 재산 : $%d \n", slave(my_money));
    printf("my_money : %d", my_money);

    return 0;
}

  성공적으로 컴파일 하면


  아마도, 앞의 내용을 열심히 배우신 분들은 위 코드가 정상적으로 실행될 것이라는 것을 알고 계셨겠죠? 하지만, 그렇지 못한 분들을 위해 설명 하자면

int slave(int my_money)
{
    my_money += 10000;
    return my_money;
}

위 slave 함수는 my_money 를 인자로 받고 있습니다. 여기서 중요한 점은 my_money 가 slave 의 변수라는 것입니다. 그렇다면 slave 함수를 호출하는 부분을 볼까요.

int main()
{
    int my_money = 100000;
    printf("2009.12.12 재산 : $%d \n", slave(my_money));
    printf("my_money : %d", my_money);

    return 0;
}

(참고적으로 편의를 위해 main 함수 내부에서 선언된 my_money 는 파란색으로, slave 함수 내부에서 선언된 my_money 는 붉은색으로 표기하였습니다)

   음, slave 함수를 호출할 때 main 함수 내부에서 선언된 my_money 의 값을 slave 함수의 변수인 my_money 로 전달하고 있습니다. 즉, 각 함수 내부에서 선언된 my_money 들은 "
서로 다른 변수" 이고, 메모리 상의 "다른 위치"를 점유하고 있습니다. 즉, 우리가 보기에 두 변수는 똑같은 것으로 보여도 적어도 컴퓨터가 보기에는 두 변수는 서로 다른 것이라는 것이지요. 두 번째로 주목할 점은 "값" 이 전달된다는 것입니다. 이는 아까 제가 위에서 부터 누누히 강조해 온 점이기도 한데, slave 함수를 호출할 때 slave 함수의 my_money 인자에는 '값' 이 전달됩니다. 즉, main 함수의 my_money 의 100000 이라는 값이 slave 함수의 my_money 라는 인자에 저장되어 들어갑니다.

  따라서, slave 함수에서 my_money 의 값을 아무리 지지고 볶아도 main 함수의 my_money 변수에는 전혀 영향을 주지 않는다는 것이지요. 왜냐하면 slave 함수의 my_money 변수는 단지 "main 함수의 my_money 와 같은 값을 가진 채로 초기화된 메모리 상의 또다른 변수" 이기 때문이지요. 이건 마치

int a = b;
b++;

  이라고 했는데 a 의 값이 b 와 같이 1 증가함을 바라는 것과 같습니다. 아무튼, 결과적으로 main 함수에서 두 번째 printf 문에서 main 함수의 my_money 의 값을 출력했을 때 에는 전혀 변하지 않은 100000 이 출력됩니다.

  그렇다면 우리가 다른 함수의 변수의 값을 수정하고자 하는 함수를 만들고 싶다면 어떻게 해야 될까요? 우리가 앞에서 배운 내용을 생각해보면 "각 함수의 세계는 너무나 배타적이여서 각 함수는 서로에 무슨 변수가 있는지 모른다. 사실 (정확히 말하자면 각 함수의 형태(리턴형, 함수의 이름, 인자들의 형(type))  빼고는) 서로에 대해 아는 것이 완전히 없다."

  그럼, 정말로 우리는 다른 함수에서 정의된 변수의 값을 수정하는 함수는 결코 작성할 수 없는 것일까요?

  답은 아니오 입니다. 놀랍게도 포인터를 이용하면 됩니다(드디어 포인터가 쓸모 있어지나요?). 일단, 이것까지 이야기 하면 강좌가 너무 길어지므로 오늘은 이쯤에서 끝내도록 하고 '어떻게 포인터로 가능할까' 에 대해서 다음 강좌가 나올 때 까지 생각해봅세요.

생각해보기

이 강좌 최상단에서 이야기 했던 마술 상자를 함수로 제작해보세요 (난이도 : 못한다면 강좌를 다시 읽어보아야 할 것입니다)

어느날 귀족이 돈벌이가 시원치 않아져서 이전에는 일정하게 10000 달러씩 챙겼지만 이제 일정치 않은 수입을 얻게 되었습니다. 여러분은 slave 함수를 인자를 2 개를 가져서, 하나는 현재 귀족의 재산, 다른 하나는 오늘 귀족의 수입을 인자로 전달받는 새로운 함수를 만들어 보세요 (난이도 : 下)

1 부터 n 까지의 합을 구하는 함수를 작성해보세요. 수학적인 공식을 써도 되지만 for 문으로 작성하는 것이 연습 하는데에는 도움이 될듯 합니다. (난이도 : 下)

N 값을 입력 받아서 1 부터 N 까지의 소수의 개수를 출력하는 함수를 제작해보세요. (난이도 : 下)

특정한 수 N 을 입력받아서 N 을 소인수분해한 결과가 출력되게 해보세요 (난이도 : 中)
예) factorize(10); --> 출력결과 : 2 × 5
     factorize(180); --> 출력결과  : 2 × 2 × 3 × 3 × 5

int function(int *arg) 와 같은 함수가 무엇을 뜻하는지 생각해보세요

강좌를 보다가 조금이라도 궁금한 것이나 이상한 점이 있다면 꼭 댓글을 남겨주시기 바랍니다. 그 외에도 강좌에 관련된 것이라면 어떠한 것도 질문해 주셔도 상관 없습니다. 생각해 볼 문제도 정 모르겠다면 댓글을 달아주세요.

현재 여러분이 보신 강좌는 <<씹어먹는 C 언어 - <13 - 1. 마술 상자 함수(function)>>> 입니다. 이번 강좌의 모든 예제들의 코드를 보지 않고 짤 수준까지 강좌를 읽어 보시기 전까지 다음 강좌로 넘어가지 말아주세요



Posted by Psi

댓글을 달아 주세요

  1. 이전 댓글 더보기
  2. YD

    #include <stdio.h>
    void Factorize(int num);
    void main() {
    int n;
    printf("n의 소인수 분해를 구하려고 합니다. n을 적어주세요 : ");
    scanf("%d", &n);
    Factorize(n);
    }

    void Factorize(int num) {

    printf("Factorize(%d) = 1", num);
    while(1){
    if(num%2 == 0){
    num=num/2;
    printf(" * 2");
    }
    else if (num%3 == 0) {
    num=num/3;
    printf(" * 3");
    }
    else if (num%5 == 0) {
    num=num/5;
    printf(" * 5");
    }
    else if (num%7 == 0) {
    num=num/7;
    printf(" * 7");
    }
    else if (num == 1)
    break;
    }
    }

    항상 강좌 잘 보고 감탄하고 있습니다!!

    제가 짜본 소인수 분해 소스인데
    어떠신가요
    Factorize(%d) = 1에서 1을 표현 안하고도 * 표현 하는방법 좀 알려주시면 감사하겠습니다...

    2015.04.28 22:21 신고 [ ADDR : EDIT/ DEL : REPLY ]
  3. 비밀댓글입니다

    2015.10.09 19:02 [ ADDR : EDIT/ DEL : REPLY ]
  4. ...

    직접만든 소인수 분해 프로그램

    #include<stdio.h>
    int so_in_su(n)
    {
    int a,b;
    printf("1");
    for (a=2;a<=n;a++)
    {
    for(;;)
    {
    if(n%a==0)
    {
    n/=a;
    printf(" * %d",a);
    }
    else
    {
    break;
    }
    }
    }
    return 0;
    }
    void main()
    {
    int n;
    clrscr();
    scanf("%d",&n);
    so_in_su(n);
    }

    2016.01.05 14:30 신고 [ ADDR : EDIT/ DEL : REPLY ]
  5. 1번 문제

    #include <stdio.h>

    int slave(int master_money)
    {
    int today_money = 0;
    printf("오늘의 귀족 수입은? ");
    scanf_s("%d", &today_money);
    master_money += today_money;
    return master_money;
    }

    int main()
    {
    int my_money = 100000;
    printf("2009.12.12 재산 : $%d \n", slave(my_money));

    return 0;
    }

    2번 문제

    #include <stdio.h>

    int OneToN()
    {
    int i = 0;
    int n = 0;
    int sum = 0;
    printf("n의 값 : ");
    scanf_s("%d", &n);

    for (i = 1;i <= n;i++)
    {
    sum = sum + i;
    }
    return sum;
    }

    int main()
    {
    int a = OneToN();
    printf("1부터 입력한 n 까지의 합은 %d 입니다. \n", a);
    return 0;
    }

    3번, 4번은 제가 수학을 잘 못해서 어떻게 구해야 하는지도 아이디어가 안 떠오르네요... ㅠㅠ
    혹시 알려주신다면 정말로 감사 드리겠습니다!

    2016.01.14 20:57 신고 [ ADDR : EDIT/ DEL : REPLY ]
  6. 감사합니다

    안녕하세요. 올려주신 강좌는 잘 보고 있습니다. 진짜 본 강의중에 최강입니다 ㅋㅋ

    마지막 문제 해결방법 보여드리고 피드백 받고 싶어서 댓글 올립니다.

    1 #include<stdio.h>
    2
    3 int main(void)
    4 {
    5 int i,j,k;
    6 int m = 0;
    7 int prime_number[200]={0};
    8
    9 printf("Please input your number: ");
    10 scanf("%d", &i);
    11 int num2 = 2;
    12 int l = i;
    13
    14 for(k=0;k<l;k++)
    15 {
    16 prime_number[m]=factorize(i,num2);
    17 if(prime_number[m] != 0)
    18 {
    19 m++;
    20 i = i/num2;
    21 }
    22 else if(prime_number[m] == 0)
    23 {
    24 num2++;
    25 }
    26 }
    27
    28 printf("Result is: ");
    29
    30 for(j=0;j<m+1;j++)
    31 {
    32 if(prime_number[j] != 0)
    33 printf("%d ",prime_number[j]);
    34 }
    35 printf("\n");
    36
    37 }
    38
    39 int factorize(int i, int num2)
    40 {
    41 if((i%num2) == 0)
    42 return num2;
    43 else
    44 return 0;
    45 }

    끝까지 읽어주셔서 감사합니다~

    2016.02.01 14:26 신고 [ ADDR : EDIT/ DEL : REPLY ]
  7. <1번 문제>

    #include <stdio.h> // 표준 입출력 헤더 (STandard Input Output header) 를 포함 (include)

    int magicbox(int gap)
    {
    gap = gap + 4;
    }

    int main(void) // 정수 형을 반환하는 메인 함수 (int : 정수 - integer)
    {
    int gap = 0;
    printf("마술 상자에 넣을 값 : ");
    scanf_s("%d", &gap);
    printf("마술 상자 지나기 전 : %d, 마술 상자 지난 후 : %d \n", gap, magicbox(gap));

    return 0; // 0을 반환 (return) 한다. -> 프로그램이 무사히 종료되었음 (return 값이 1 : 프로그램이 무사히 종료되지 않았다. 즉, 오류가 발생했다)
    }

    <2번 문제>

    #include <stdio.h> // 표준 입출력 헤더 (STandard Input Output header) 를 포함 (include)

    int slave(int master_money, int today_money)
    {
    master_money = master_money + today_money;
    printf("현재 재산 : $%d, 오늘 수익 : $%d \n", master_money, today_money);
    }

    int main(void) // 정수 형을 반환하는 메인 함수 (int : 정수 - integer)
    {
    int my_money = 100000;
    int today_money = 0;
    printf("오늘의 수익 : $");
    scanf_s("%d", &today_money);

    slave(my_money, today_money);

    return 0; // 0을 반환 (return) 한다. -> 프로그램이 무사히 종료되었음 (return 값이 1 : 프로그램이 무사히 종료되지 않았다. 즉, 오류가 발생했다)
    }

    <3번 문제>

    #include <stdio.h> // 표준 입출력 헤더 (STandard Input Output header) 를 포함 (include)

    int oneton(int N)
    {
    int i = 0;
    int sum = 0;
    for (i = 1;i <= N;i++)
    {
    sum = sum + i;
    }

    return sum;
    }

    int main(void) // 정수 형을 반환하는 메인 함수 (int : 정수 - integer)
    {
    int N = 0;
    printf("1 부터 몇 까지 더하시겠습니까? ");
    scanf_s("%d", &N);

    printf("1부터 %d 까지의 합은 %d 입니다. \n", N, oneton(N));

    return 0; // 0을 반환 (return) 한다. -> 프로그램이 무사히 종료되었음 (return 값이 1 : 프로그램이 무사히 종료되지 않았다. 즉, 오류가 발생했다)
    }

    <4, 5번 문제>
    소수 구하는 프로그램의 알고리즘을 생각해 낼 수가 없네요... ㅠㅠㅠ

    <6번 문제>

    인자를 포인터로 받는 함수를 의미합니다.

    2016.02.18 17:17 신고 [ ADDR : EDIT/ DEL : REPLY ]
  8. C 열공중

    C언어를 배우고 싶어서 홀로 독학하고 있는데 정말 많이 배우고 있습니다. 감사합니다.

    문제 4번

    int n_sum(int x)
    {
    int i = 2;

    for (i; i <= x; i++)
    {
    while (1)
    {
    if (x%i == 0)
    {
    printf("%d\n", i);
    x /= i;
    }
    else
    break;
    }
    }
    return i;
    }

    int main()
    {
    int num;

    printf("숫자를 입력하시오 : ");
    scanf_s("%d", &num);

    n_sum(num);

    system("pause");
    return 0;
    }

    2016.06.12 21:35 신고 [ ADDR : EDIT/ DEL : REPLY ]
  9. sea9016

    //문제 5
    #include <stdio.h>

    void primenum(int num)
    {
    int i;
    for (i = 2; i <= num; i++)
    {
    while(num%i == 0)
    {
    num =num / i;
    if (num != 1)
    {
    printf("%d x", i);
    }
    else if (num == 1)
    {
    printf("%d", i);
    }


    }

    }
    }

    int main()
    {
    int input;
    printf("소인수 분해 할 수를 입력하시오 :\n");
    scanf_s("%d", &input);
    primenum(input);
    }

    강의 잘 보고 있습니다~

    2016.11.20 23:15 신고 [ ADDR : EDIT/ DEL : REPLY ]
  10. 궁금


    /*어느날 귀족이 돈벌이가 시원치 않아져서 이전에는 일정하게 10000 달러씩 챙겼지만 이제 일정치 않은 수입을 얻게 되었습니다.
    여러분은 slave 함수를 인자를 2 개를 가져서, 하나는 현재 귀족의 재산, 다른 하나는 오늘 귀족의 수입을 인자로 전달받는
    새로운 함수를 만들어 보세요 (난이도 : 下)
    */
    #include <stdio.h>

    int slave(int current_money, int today_input) {

    int result_value;

    result_value = current_money + today_input;


    return result_value;
    }

    int main(void)
    {
    int current_money;
    int today_input;

    printf("현재 귀족 주인의 재산은? : ");
    scanf("%d", &current_money);

    while(true) {

    printf("귀족의 오늘 수입은? : ");
    scanf("%d", &today_input);

    current_money = slave(current_money, today_input);
    printf("현재 귀족의 재산은 %d 달러입니다.\n\n",current_money);

    }
    return 0;
    }

    2017.07.13 17:15 신고 [ ADDR : EDIT/ DEL : REPLY ]
  11. 궁금

    /*
    1 부터 n 까지의 합을 구하는 함수를 작성해보세요.
    수학적인 공식을 써도 되지만 for 문으로 작성하는 것이 연습 하는데에는 도움이 될듯 합니다. (난이도 : 下)
    */

    #include <stdio.h>

    int main(void) {

    int sum = 0, n, i;

    printf("얼마 까지의 합을 구할 것인가? (n=?) : ");
    scanf("%d",&n);

    for(i = 1; i < n+1; i++) {

    sum += i;

    }

    printf("1부터 n까지의 합은 %d입니다.", sum);

    return 0;
    }

    2017.07.13 17:19 신고 [ ADDR : EDIT/ DEL : REPLY ]
  12. 궁금

    /*
    N 값을 입력 받아서 1 부터 N 까지의 소수의 개수를 출력하는 함수를 제작해보세요. (난이도 : 下)
    */

    #include <stdio.h>

    int main(void)
    {
    int cursor = 0, flag = 0;
    unsigned int n, i, j;
    int prime_number[1000];

    prime_number[0] = 2;

    printf("N이하의 숫자 중 소수의 수를 구하는 함수. (단, N은 양수) N = ");
    scanf("%d", &n);

    for(i = 3; i < n+1; i+=2) {
    for(j = 0; j < cursor; j++) {
    if (i % prime_number[j] == 0)
    flag = 1;
    }
    if( flag == 0) {
    cursor++;
    prime_time[cursor] = i;
    }
    }

    printf("N이하의 수 중에서 소수는 총 %d개 있습니다.", cursor + 1);

    return 0;
    }

    2017.07.13 17:42 신고 [ ADDR : EDIT/ DEL : REPLY ]
  13. 궁금

    /*
    특정한 수 N 을 입력받아서 N 을 소인수분해한 결과가 출력되게 해보세요 (난이도 : 中)
    예) factorize(10); --> 출력결과 : 2 × 5
    factorize(180); --> 출력결과 : 2 × 2 × 3 × 3 × 5
    */

    #include <stdio.h>

    void factorize(int n) {

    int cursor = 0, flag = 0;
    unsigned i, j;
    int prime_number[1000];
    int factor[100];
    int temp_value = n;

    for(i = 3; i < n+1; i+=2) {
    for(j = 0; j < cursor; j++) {
    if (i % prime_number[j] == 0)
    flag = 1;
    }
    if( flag == 0) {
    cursor++;
    prime_time[cursor] = i;
    }
    }

    for(i = 0; i < cursor; i++) {
    j = 0;
    if (temp_value % prime_number[i] == 0) {
    factor[j] = prime_number[i];
    temp_value = temp_value/prime_number[i];
    i = 0;
    j++;
    }
    }

    printf("출력결과 : ");

    for(i = 0; i < j; i++) {

    printf("%d", factor[0]);

    if(i < j) {
    printf(" X %d",factor[i+1]);
    }
    }

    int main(void)
    {
    int n;

    printf("소인수 분해 할 수를 입력하시오. : ");
    scanf("%d", &n);

    factorize(n);

    return 0;
    }

    2017.07.13 17:58 신고 [ ADDR : EDIT/ DEL : REPLY ]
  14. 펠릭스

    문제 풀려고 코딩했는데 컴파일오류가 났어요

    제코드>>>>>
    #include<stdio.h>
    int prime(n)
    {
    int i,j,answer;
    answer=0;

    for(i=0;i<=n;i++)
    {
    for(j=2;j<=i;j++)
    {
    if(i%j==0)
    {
    answer++;
    break;
    }
    }
    return answer;
    }

    int main()
    {
    int N;
    printf("insert N\n");
    scanf("%d",&N);
    printf("answer:%d",prime(N));

    return 0;
    }//28번째줄
    컴파일 에러28.1 error: expected declaration or statement at end of input }
    라고 뜨는데 마지막줄의 }가 왜 문제라는지 전혀 모르겠어요;; ㅠㅠㅠ 함수니깐 넣은건데 대체 왜 컴파일이 안되는지 모르겠네요 ㅠㅠㅠ

    /그림문자 입력하기 너무 어렵네요

    2017.08.04 03:07 신고 [ ADDR : EDIT/ DEL : REPLY ]
    • 펠릭스

      +다시 코드 짰어요
      근데 그전에 왜 오류가 난건지 모르겠네요

      소수개수:
      #include<stdio.h>

      int Prime(int n)
      {
      int i,j,a;
      a=n-1;//1의 처리가 귀찮아서 미리함

      for(i=2;i<=n;++i)
      {
      for(j=2;j<i;j++)
      {
      if(i%j==0)
      {
      a=a-1;
      break;
      }
      }
      }
      return a;
      }

      int main(void)
      {
      int N;
      printf("ENTER N\n");
      scanf("%d",&N);
      printf("NUMBER OF THE PRIME NUMBERS:%d\n",Prime(N));

      return 0;
      }

      2017.08.05 01:23 신고 [ ADDR : EDIT/ DEL ]
  15. 컴맹

    //오늘 번돈을 재산에 더해 총재산을 구하기

    #include <stdio.h>
    int properties(int sum,int today)
    {
    sum+=today;

    }
    int main()
    {
    int sum,today;
    printf("재산총계와 오늘 번돈을 입력하시오!");
    printf("재산은:");
    scanf_s("%d", &sum);
    printf("오늘 번돈은:");
    scanf_s("%d", &today);

    printf("오늘까지 당신이 벌어들인 재산총액은: %d 입니다 \n", properties(sum,today));

    return 0;

    }



    //1부터 n까지의 합을 구하기
    #include<stdio.h>
    int Nsum(int n)
    {
    int i,sum = 0;
    for (i=1; i <= n; i++)
    {
    sum += i;
    }
    return sum;
    }

    int main()
    {
    int n;
    printf("1부터 몇까지의 합을 구하고 싶은지 입력하시오:");
    scanf_s("%d", &n);
    printf("1부터 %d까지의 합은:%d입니다.\n", n, Nsum(n));

    return 0;

    }


    //머리는 쥐가 나지만, 그래도 어찌어찌 따라가야지 하는 마음으로 좋은강의 자꾸 곱씹고 되내이며 따라가봅니다.

    2017.10.06 19:04 신고 [ ADDR : EDIT/ DEL : REPLY ]
  16. 컴맹

    /* 10명 학생들의 국영수 성적구하기*/
    #include <stdio.h>
    int main()
    {
    int i=0,kor[10], eng[10], math[10], total[10];
    float ave[10];
    char grade[10];
    for (i = 0; i < 10; i++)
    {
    printf("%d번째학생의 국어,영어,수학 점수를 입력하세요.\n", i + 1);
    scanf_s("%d %d %d", &kor[i], &eng[i], &math[i]);
    confirm: if ( kor[i] > 100||kor[i]<0||eng[i]>100||eng[i]<0||math[i]>100||math[i]<0)
    {
    printf("문자를 입력했거나 범위를 벗어난 숫자인듯합니다. 양수를 다시 입력하세요.\n");
    scanf_s("%d %d %d", &kor[i], &eng[i], &math[i]);
    goto confirm;
    }


    total[i] = kor[i] + eng[i] + math[i];
    ave[i] = total[i] / 3.0f;
    if (ave[i] >= 90)
    grade[i] = 'A';
    else if (ave[i] >= 80)
    grade[i] = 'B';
    else if (ave[i] >= 70)
    grade[i] = 'C';
    else if (ave[i] >= 60)
    grade[i] = 'D';
    else
    grade[i] = 'F';
    }
    printf("\n\n----------------------------------------------------\n");
    printf("번호\t국어\t영어\t수학\t총점\t평균\t학점\n====================================================\n");
    for (i = 0; i < 10; i++)
    {
    printf("%d\t%d\t%d\t%d\t%d\t%.2f\t%c\n", i + 1, kor[i], eng[i], math[i], total[i], ave[i], grade[i]);
    }
    printf("----------------------------------------------------\n");
    return 0;

    }
    /*여기서 질문입니다. 위코드에서 성적을 입력받을때 실수로 음수나 문자를 입력했을경우 확인후 재입력하기위한 코드를 짜고싶은건데요. 음수를 입력받으면 취지대로 재대로 입력할때까지 재입력을 요구하는게됩니다. 반면, 문자를 입력받으면 '확인후 양수를 다시 입력하세요'란 메세지가 끊임없이 화면을 가득채우는데 어떻하면 취지대로 해결할수 있을까요? 누구든 가르침을 주시면 감사하겠습니다.*/

    2017.10.10 01:41 신고 [ ADDR : EDIT/ DEL : REPLY ]
  17. 컴맹

    /* 10명 학생들의 국영수 성적구하기*/
    #include <stdio.h>
    #include <stdlib.h>
    int main()
    {
    int i=0,kor[10], eng[10], math[10], total[10];
    float ave[10];
    char grade[10];
    for (i = 0; i < 10; i++)
    {
    printf("%d번째학생의 국어점수를 입력하세요.\n", i + 1);
    scanf_s("%d", &kor[i]);
    while ( getchar() != '\n'||kor[i]>100||kor[i]<0)
    {
    printf("문자를 입력했거나 범위를 벗어난 숫자인듯합니다. 양수를 다시 입력하세요.\n");
    scanf_s("%d", &kor[i]);
    }
    printf("%d번째학생의 영어점수를 입력하세요.\n", i + 1);
    scanf_s("%d", &eng[i]);
    while (getchar() != '\n'||eng[i] > 100 || eng[i] < 0)
    {
    printf("문자를 입력했거나 범위를 벗어난 숫자인듯합니다. 양수를 다시 입력하세요.\n");
    scanf_s("%d",&eng[i]);
    }
    printf("%d번째학생의 수학점수를 입력하세요.\n", i + 1);
    scanf_s("%d", &math[i]);
    while (getchar() != '\n'||math[i] > 100 || math[i] < 0)
    {
    printf("문자를 입력했거나 범위를 벗어난 숫자인듯합니다. 양수를 다시 입력하세요.\n");
    scanf_s("%d", &math[i]);
    }

    total[i] = kor[i] + eng[i] + math[i];
    ave[i] = total[i] / 3.0f;
    if (ave[i] >= 90)
    grade[i] = 'A';
    else if (ave[i] >= 80)
    grade[i] = 'B';
    else if (ave[i] >= 70)
    grade[i] = 'C';
    else if (ave[i] >= 60)
    grade[i] = 'D';
    else
    grade[i] = 'F';
    }
    printf("\n\n----------------------------------------------------\n");
    printf("번호\t국어\t영어\t수학\t총점\t평균\t학점\n====================================================\n");
    for (i = 0; i < 10; i++)
    {
    printf("%d\t%d\t%d\t%d\t%d\t%.2f\t%c\n", i + 1, kor[i], eng[i], math[i], total[i], ave[i], grade[i]);
    }
    printf("----------------------------------------------------\n");
    return 0;

    }

    /*어찌어찌해서 원래 취지대로 구사해서 해결할수 있게 되었는데요. 그래도 여기서 다시금 의문이 드는건 "while ( getchar() != '\n'||kor[i]>100||kor[i]<0)"처럼 하면 되는데, while문안의 3가지 조건중 첫번째인 숫자인지확인하는조건을 맨마지막으로 위치시키면 계속 문제가되던데, 왜그런건지 설명좀 부탁 드려도 될까요? */

    2017.10.10 13:40 신고 [ ADDR : EDIT/ DEL : REPLY ]
  18. mk

    N 값을 입력 받아서 1부터 N 까지의 소수의 개수를 출력하는 함수를 제작해보세요.

    #include <stdio.h>

    int count_prime_number(int number)
    {
    int i,j;

    int prime_number_or_not = 0;

    int prime_number_counts = 0;

    for(i=2;i<=number;i++)
    {
    for(j=2;j<i;j++)
    {
    if(i % j == 0)
    {
    prime_number_or_not = 1;
    break;
    }
    else
    {
    prime_number_or_not = 0;
    }
    }

    if(prime_number_or_not == 0)
    {
    prime_number_counts++;
    }
    }

    return prime_number_counts;
    }

    int main()
    {
    int N;

    int total_count_prime;

    printf("N 값을 입력하세요 : ");

    scanf("%d", &N);

    total_count_prime = count_prime_number(N);

    printf("총 소수의 개수는 : %d", total_count_prime);

    return 0;
    }

    2018.06.15 11:04 신고 [ ADDR : EDIT/ DEL : REPLY ]
  19. mk

    특정한 수 N을 입력받아서 N을 소인수분해한 결과가 출력되게 해보세요

    int factorize(int number)
    {
    int i,j;

    int prime_number_or_not = 0;

    int first_item = 0;

    for(i=2;i<=number;i++)
    {
    for(j=2;j<i;j++)
    {
    if(i % j == 0)
    {
    prime_number_or_not = 1;
    break;
    }
    else
    {
    prime_number_or_not = 0;
    }
    }

    if(prime_number_or_not == 0)
    {
    for(;;)
    {
    if(number % i == 0)
    {
    if(first_item == 0)
    {
    printf("%d", i);
    first_item = 1;
    }
    else
    {
    printf(" X %d", i);
    }
    number = number / i;
    if(number == 1)
    {
    break;
    }
    }
    else
    {
    break;
    }
    }
    }
    }
    return 0;
    }

    int main()
    {
    int N;

    int total_count_prime;

    printf("N 값을 입력하세요 : ");

    scanf("%d", &N);

    factorize(N);

    return 0;
    }

    2018.06.15 12:19 신고 [ ADDR : EDIT/ DEL : REPLY ]
  20. 잘보고갑니다~

    2018.08.01 14:05 신고 [ ADDR : EDIT/ DEL : REPLY ]
  21. pikachu

    소인수분해 함수 프로그램입니다.
    중간에 continue, break도 헷갈리고 ㅜㅜㅜ
    factorize함수를 main함수 안에서 printf처리해버리고 아주 난리부르스를 쳤네요...
    항상 감사합니다~

    #include <stdio.h>

    int factorize(int N)
    {
    int i;

    for(i=2; i<=N; i++)
    {
    if(!(N%i==0))
    continue;

    printf("%d", i); // N=27, i=2인 경우, 앞의 것이 continue됐으니 for문이 스킵되고 바로 i=3으로 넘어간다.

    if(N==i)
    continue; //이 continue를 맞이할 경우, for문에서 진행되던 계산이 스킵되고 바로 i에 1이 더해져서 새로 for문이 시작된다.

    printf("*");
    N = N/i;
    i = 1;
    /* i가 i=2로 시작하면 안 되는 이유: for문이 또 시작할 때 i++된다.
    그러면 결과적으로 i=2부터 다시 시작하는 꼴.
    만약 i=2라고 하면 for문이 또다시 시작될 때 i++가 되어 i=3부터 시작하게 된다. */
    }
    return;
    }

    int main()
    {
    int N;
    printf("N값은? : ");
    scanf("%d", &N);
    printf("%d를 소인수분해하면: ", N);
    factorize(N);
    printf("\n");
    return 0;
    }




    2018.08.30 18:43 신고 [ ADDR : EDIT/ DEL : REPLY ]