함수의 이해 / 데이터 전달

언어로그/C/C++ 2010. 12. 10. 19:50

1. 함수가 필요한 이유?

  • 중복된 작업을 함수로 분리하면, 한번 작성으로 여러번 사용할 수 있어서 효율적인 프로그램이 된다.
  • 또한 큰 문제를 작은 문제들로 나누어 이해하기 쉬워지며, 수정사항이 발생하면 함수 부분만 수정하면 되기 때문에 유지보수도 용이해진다.


2. 함수의 원형(프로토타입)과 정의

  • C언어에서 함수는 원형(프로토타입)과 정의로 분리된다.
  • 함수의 원형(프로토타입)은 보통 헤더파일이나 메인함수 이전에 선언이 되며, 컴파일러에게 이러 이러한 함수를 아래에 정의했으니까 메인함수 또는 특정함수에서 이 함수를 사용해도 됨을 알려주는 것이다.
  • 함수의 정의는 실제적으로 함수가 하는 일을 기술하는 부분이다. C언어에서는 함수의 시그니처로 함수의 이름만을 사용하기 때문에, 파라미터의 타입과 반환값의 타입이 달라도 동일한 이름의 함수를 사용 할 수 없다.
#include <stdio.h>

void swap(int , int);// 함수원형(프로토타입)   

int main() {
...

return 0;

}
void swap(int a, int b) {   // 함수의 정의         
...

}  


3. Call By Value vs Call By Reference

  • 함수 호출시 파라미터를 넘기는 방식에 따라 Call By Value 또는 Call By Reference 라고 구분한다.
  • 함수 호출시 변수들의 데이터(값)가 복사되는데, 함수 내에서 이 복사된 변수에 대한 조작은 원본 변수에 아무런 영향을 미치지 못하는데 이러한 호출방식을 Call By Value라고 부른다.
  • 파라미터로 변수의 주소를 넘기면, 피호출자 쪽에서는 이 주소를 조작하여 원본 변수의 데이터를 변경할 수 있다. 이러한 호출방식을 Call By Pointer 또는 Call By Reference 라고 부른다.


Call By Value

main() {
    int a = 1, b = 5;

    swap(a, b);// 변수의 값을 전달함 

    }
    void swap(int a, int b)  {// main함수의 a, b는 변경되지 않음    
    int temp = a;

    a = b;

    b = temp      

}


Call By Reference

main()  {
   int a = 1, b = 5;
   swap(&a, &b);// 변수의 주소를 전달함    

}

void swap(int *a, int *b)  { // main함수의 a, b가 변경됨    
    int temp = *a;
    *a = *b;
    *b = temp;
}


'언어로그 > C/C++' 카테고리의 다른 글

C 프로그램 실행과정  (0) 2011.02.22
C 언어란?  (0) 2011.02.22
비트필드  (0) 2010.12.10
함수의 이해 / 데이터 전달  (0) 2010.12.10
과제 #3 함수, 포인터의 사용  (0) 2010.12.10
과제#4 배열과 문자열  (0) 2009.10.03

과제 #3 함수, 포인터의 사용

언어로그/C/C++ 2010. 12. 10. 14:25

1. 최대값과 최소값을 구하는 함수

  • 세 개의 정수를 입력받아서 그중 가장 큰 수를 반환하는 함수와 가장 작은 수를 반환하는 함수 작성.

입력

  • 세 개의 정수 입력 : 7 4 9

출력

  • 최대값 : 9
  • 최소값 : 4

코드

/*
    입력: 세 개의 정수 
    출력: 가장 큰수와 가장 작은 수 
    조건: 가장 큰수를 반환하는  함수 
        가장 작은수를 반환하는 함수 작성  
*/

#include <stdio.h>

int max_num(int a, int b, int c);
int min_num(int a, int b, int c);

int main (int argc, char const* argv[])
{
    int a, b, c, max, min;

    printf("세 개의 정수 입력 : ");
    scanf("%d %d %d", &a, &b, &c);

    max = max_num(a, b, c);
    min = min_num(a, b, c);

    printf("\n최대값 : %d\n", max);
    printf("\n최소값 : %d\n", min);

    return 0;
}

int max_num(int a, int b, int c) {
    int temp = a > b ? a : b;
    return temp > c ? temp : c;
}


int min_num(int a, int b, int c) {
    int temp = a < b ? a : b;
    return temp < c ? temp : c;
}  



2. 온도변환 : 화씨와 섭씨 변환 함수

  • Fahrenheit 함수 : 섭씨온도를 입력하면 화씨 온도로 변환
  • Celsius 함수 : 화씨 온도를 섭씨 온도로 변환
  • 공식 : F = 1.8 * C + 32
## 온도 변환 ##  
1) 섭씨 입력  
2) 화씨 입력

## 메뉴선택: 1
입력:
섭씨 입력:  32

출력:
변환된 화씨 : 89.60

코드

/*
    입력: 섭씨온도 또는 화씨온도 
    출력: 섭씨온도 또는 화씨온도 
    조건: 섭씨온도는 화씨온도 / 화씨온도는 섭씨온도로 변환하는 함수 작성 
*/

#include <stdio.h>

double fahrenheit_to_celsius(double f);
double celsius_to_fahrenheit(double c);

int main (int argc, char const* argv[])
{
    double input, output;
    int select;

    printf(" ### 온도 변환 ### \n\n");
    printf("1) 섭씨 입력 \n");
    printf("2) 화씨 입력 \n");
    printf("\n메뉴 선택 : ");

    scanf("%d", &select);

    if (select == 1) {
        printf("\n섭씨입력 : ");
        scanf("%lf", &input);
        output = celsius_to_fahrenheit(input);
        printf("변환된 화씨 : %.2lf \n", output);
    } else if (select == 2) {
        printf("\n화씨입력 : ");
        scanf("%lf", &input);
        output = fahrenheit_to_celsius(input);
        printf("변환된 섭씨 : %.2lf \n", output);
    }

    return 0;
}

double fahrenheit_to_celsius(double f) {
    double c = (f - 32) / 1.8;
    return c;
}

double celsius_to_fahrenheit(double c) {
    double f = 1.8 * c + 32;
    return f;
}  



3. 최대값과 최소값의 주소를 반환하는 함수

  • 세 개의 정수를 입력 받아서 그 중 가장 큰 수의 주소를 반환하는 함수와 가장 작은수의 주소를 반환하는 함수를 작성 (입출력은 #1과 동일)
int *MAX(int *, int *, int *);  
int *MIN(int *, int *,  int *);

코드

/*
    입력: 세 개의 정수 
    출력: 가장 큰수, 가장 작은수 
    조건: 가장 큰수의 주소를 반환하는 함수 
       가장 작은수의 주수를 반환하는 함수 작성 
*/

#include <stdio.h>

int* max_num_addr(int *a, int *b, int *c);
int* min_num_addr(int *a, int *b, int *c);

int main (int argc, char const* argv[])
{
    int a, b, c, *max, *min;

    printf("세 개의 정수 입력 : ");
    scanf("%d %d %d", &a, &b, &c);

    max = max_num_addr(&a, &b, &c);
    min = min_num_addr(&a, &b, &c);

    printf("\n최대값 : %d\n", *max);
    printf("최소값 : %d\n", *min);

    return 0;
}

int* max_num_addr(int *a, int *b, int *c) {
    int *temp = *a > *b ? a : b;
    return *temp > *c ? temp : c;
}


int* min_num_addr(int *a, int *b, int *c) {
    int *temp = *a < *b ? a : b;
    return *temp < *c ? temp : c;
}



4. 반올림 계산 함수

  • 양의 부동소수점 수를 받아서 소수점 셋째 자리에서 반올림 하는 함수 작성

입력

  • 양의 부동소수점을 입력 하시오 : 123.456789

출력

  • 반올림 결과 : 123.460000

문제해결

  • 소수점 셋째자리 반올림을 위해, 1000을 곱한다. 그리고 1의 자리 수가 5이상이면 10을 더하고, 1의 자리 수를 버린다. 이 수를 다시 1000으로 나누면 소수점 셋째 자리에서 반올림한 결과를 얻을 수 있다.

코드

/*
    입력: 양의 부동소수 점 
    출력: 소수 셋째 자리까지 반올림 된 수 (소수 6째 자리까지 출력) 
    조건: 
*/

#include <stdio.h>

#define SPACE 1000.0

double roundTwo(double x);

int main (int argc, char const* argv[])
{
    double input, output;

    printf("양의 부동소수점을 입력하시오 : ");
    scanf("%lf", &input);

    output = roundTwo(input);

    printf("\n반올림 결과 : %.6lf \n", output);

    return 0;
}

// 소수 3째 자리에서 반올림  
double roundTwo(double x) {
    int temp  = (int)(x * SPACE);

    if (temp % 10 >= 5) {
        temp += 10;
    }
    temp -= (temp%10); 

    return temp / SPACE;
} 



5. 이진수를 십진수로 변환하는 함수

  • 사용자로 부터 이진수를 입력 받아서 십진수로 변환하는 프로그램을 작성.
  • 사용자로부터 이진수를 입력받는 함수 (입력값이 0과 1로만 이루어져 있는지 판별)
  • 이진수를 십진수로 변환하는 함수

입/출력

이진수를 입력하시오 (0 또는 1) : 123
이진수가 아닙니다. 0 또는 1만 입력하시오.

이진수를 입력하시오 (0 또는 1) : 1010

입력한 이진수 : 1010
변환된 십진수: 10  

문제해결

  • 이진수 여부를 판별하기 위해서는 입력된 수의 각 자리수가 0 또는 1이어야 한다. 각 자리 수 확인을 위해 입력된 수를 10으로 나눈 나머지를 통해 각 자리수를 확인할 수 있다. 이진수를 십진수로 변경은 이진수 각 자리수에 대해서 2를 자리수만큼 곱한 것들의 합으로 구할 수 있다. 이 때 2의 자리수만큼의 곱은 시프트 연산으로 대신해 코드를 간결하게 할 수 있다.

코드

/*
    입력: 이진수
    출력: 십진수 
    조건: 이진수를 입력받는 함수 
        이진수를 십진수로 변환하는 함수 작성 
*/

#include <stdio.h>

#define TRUE 1
#define FALSE 0

int input_binary(int *input);
int binary_to_decimal(int binary);

int main (int argc, char const* argv[])
{   
    int input, output;

    while (input_binary(&input) == FALSE) {
        printf("이진수가 아닙니다. 0 또는 1만 입력하시오. \n\n");
    }
    output = binary_to_decimal(input);

    printf("입력된 이진수: %d \n", input);
    printf("변환된 십진 수 : %d \n", output);

    return 0;
}

// 이진수를 입력받고, 검사 
int input_binary(int *input) {  
    int temp;

    printf("이진수를 입력하시오 (0 또는 1) : ");
    scanf("%d", input);

    temp = *input;  
    while (temp != 0) {
        if (temp % 10 > 1) {
            return FALSE;
        }
        temp /= 10;
    }
    return TRUE;
}

// 이진수를 십진수로 변환 
int binary_to_decimal(int binary) {
    int decimal = 0, b = binary; 
    int i, rem;

    for (i = 0; b != 0; i++) {
        rem = b % 10;
        rem = rem << i;
        decimal += rem;
        b /= 10;
    }

    return decimal;
} 


'언어로그 > C/C++' 카테고리의 다른 글

C 프로그램 실행과정  (0) 2011.02.22
C 언어란?  (0) 2011.02.22
비트필드  (0) 2010.12.10
함수의 이해 / 데이터 전달  (0) 2010.12.10
과제 #3 함수, 포인터의 사용  (0) 2010.12.10
과제#4 배열과 문자열  (0) 2009.10.03

과제#4 배열과 문자열

언어로그/C/C++ 2009. 10. 3. 21:50

1. 윤년계산

  • 해당년도의 1월 1일부터 몇 번째 날인지를 계산하고 그 결과를 출력하는 프로그램
  • 입력은 년월일 형태로 형태로 처리 (예: 2009 10 15)
  • 2월의 경우 윤달여부를 판별하여 일수를 계산한다.
  • 윤년은 4로 나누어 떨어지는 해이며, 그중 100으로 나누어 떨어지는 해는 평년. 하지만 400으로 나누어 떨어지는 해는 다시 윤년임
입력

오늘 날짜는? (예: 2009.10.15 -> 2009 10 15) : 2008 3 1

출력

현재 61째 되는 날입니다.

문제해결
  • 매년 매월의 날수는 동일하지만, 윤년의 2월은 1일이 더 많다는 것에 주의!

코드
/*
    입력 : 년 월 일 (2009 10 15) 
    출력 : 해당년도 1월 1일 부터 몇번 째 날인지를 출력  
    조건 : 윤년 고려 
*/

#include <stdio.h>

// 1~12월까지 날수를 담는 배열 , 인덱스 0 는 무시. 
int month_days[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

int IsEmptyYear(int year);
int HowManyDays(int year, int month, int day);

int main (int argc, char const* argv[])
{
    int year, month, day, days;

    printf("오늘 날짜는 ? (예: 2009.10.15 -> 2009.10.15) : ");
    scanf("%d %d %d", &year, &month, &day);

    days = HowManyDays(year, month, day);

    printf("\n 현재 %d째 되는 날입니다. \n", days);

    return 0;
}

// 윤년인지 여부 반환 
int IsEmptyYear(int year) {
    if ( (year % 4 == 0) && ((year % 100) || (year % 400 == 0)) ) {
        return 1;
    } else {
        return 0;
    }
}


int HowManyDays(int year, int month, int day) {
    int i, days;

    days = 0;
    for (i = 1; i <= month - 1; i++) {
        days += month_days[i];
    }
    days += day;
    // 윤년이면 1 을 더함 
    if (IsEmptyYear(year)) {
        days += 1;
    }
    return days;
}  


2. 진법 변환

  • 임의의 정수와 변환될 진법을 입력 받아 출력하는 프로그램 작성.
입력

변환될 수(decimal)는 ? 12345
변환할 진법( base)은 ? 16

출력

변환된 수 = 1E240

문제해결
  • 십진수를 진법수로 나눈 나머지들의 역순이 해당 진법으로 변경된 수이다. 이 때 9진법 이상에서는 10부터는 알파벳 문자 A로 표기된다

코드
/*
    입력 : 십진수, 변환할 진법 
    출력 : 변환된 수 
    조건 : 8진수, 16진수 변환문자 사용금지, 배열 사용 
*/

#include <stdio.h>
#include <string.h>

#define MAX_SIZE 100

void base_conversion(char *num, int decimal, int base);
void reverse_str(char *s);

int main (int argc, char const* argv[])
{
    int decimal, base;
    char num[MAX_SIZE]; 

    printf("변환할 수(decimal) 는? ");
    scanf("%d", &decimal);

    printf("변환할 진법(base)은 ? ");
    scanf("%d", &base);

    base_conversion(num, decimal, base);

    printf("변환된 수 =  %s \n", num);

    return 0;
}

// 십진수 decimal을 base진수로 변환하여 문자배열 num에 담는 함수  
void base_conversion(char *num, int decimal, int base) {
    int i, share;
    char *p = num;

    i = 0;
    while (decimal > 0) {
        share = decimal % base;
        if (share > 9) {
            p[i++] = 'A' + share - 10;
        } else {
            p[i++] = '0' + share;
        }
        decimal /= base;
    }
    p[i] = '\0';

    reverse_str(num);
}

// 문자열을 거꾸로 뒤집는 함수 
void reverse_str(char *s) {
    char ch, *pre, *rear;
    pre = s;
    rear = s + strlen(s) - 1;

    while (pre < rear) {
        ch = *pre;
        *pre++ = *rear;
        *rear-- = ch;
    }
}


3. 배열에서 최대값과 최소값 구하기

  • 정수 값을 갖는 배열에서 최대값과 최소값을 찾는 프로그램을 작성
  • 배열의 초기값: 45, -12, 67, 30, 81, -3, 13, 74, 3, 20
  • 최소값과 최대값의 위치, 최소값과 최소값의 위치 구하기.
입력

array[] = { 45, -12, 67, -30, 81, -3, 13, 74, 3, 20}

최대값 : 81, 위치 : 5
최소값: -30, 위치 : 4

출력

변환된 수 = 1E240

문제해결
  • 배열에서 최대값, 최소값이 있는 인덱스를 알면 최대값과 최소값을 알수 있다.

코드
/*
    입력 : 배열 초기값 
    출력 : 최소값과 최대값의 위치, 최소값과 최대값의 위치 
*/

#include <stdio.h>

#define BUF_SIZE 10

void array_printf(int *arr, int size);
void max_min_finder(int *arr, int size, int *idx_max, int *idx_min);

int main (int argc, char const* argv[])
{
    int array[BUF_SIZE] = { 45, -12, 67, -30, 81, -3, 13, 74, 3, 20 };
    int max_index, min_index;

    array_printf(array, BUF_SIZE);

    max_min_finder(array, BUF_SIZE, &max_index, &min_index);

    printf(" 최대값 : %d , 위치 : %d \n", array[max_index], max_index+1);
    printf(" 최소값 : %d , 위치 : %d \n", array[min_index], min_index+1);

    return 0;
}

void array_printf(int *arr, int size) {
    int i;

    printf("array[] = { ");
    for (i = 0; i < size; i++) {
        printf("%d ", arr[i]);
    }
    printf("} \n\n");
}


void max_min_finder(int *arr, int size, int *idx_max, int *idx_min) {
    int i, max, min;
    min = max = arr[0]; 

    for (i = 0; i < size; i++) {
        if (arr[i] > max) {
            max = arr[i];
            *idx_max = i;
        }
        if (arr[i] < min) {
            min = arr[i];
            *idx_min = i;
        }
    }
}


4. 대소문자 변환

  • 임의의 문자열을 입력받아, 소문자는 대문자로, 대문자는 소문자로 변환하는 함수 작성 (제어문, 포인터 사용)
void change(char *to_str, const char *from_str);
문제해결
  • 대문자 -> 소문자 / 소문자 -> 대문자로 변경하고, 이외의 문자의 그대로 복사가 되어야 한다.

코드
/*
    입력 : 임의의 문자열 
    출력 : 소문자는 대문자로, 대문자는 소문자로 변환된 문자열 
    조건 : 제어문과 포인터 사용 
*/

#include <stdio.h>

#define MAX_SIZE 100

void change(char *to_str, const char *from_str);

int main (int argc, char const* argv[])
{
    char to_str[MAX_SIZE], from_str[MAX_SIZE];

    printf("문자열 입력 : ");
    fgets(from_str, MAX_SIZE, stdin);

    change(to_str, from_str);

    printf("변환된 문자열 : %s", to_str);

    return 0;
}

// 대소문자 상호 변환 
void change(char *to_str, const char *from_str) {
     while (*from_str != '\0') {
        if (*from_str >= 'a' && *from_str <= 'z') {
            *to_str++ = *from_str++ - ('a' - 'A');
        } else if (*from_str >= 'A' && *from_str <= 'Z') {
            *to_str++ = *from_str++ + ('a' - 'A');
        } else {
            *to_str++ = *from_str++;
        } 
    }
}  




'언어로그 > C/C++' 카테고리의 다른 글

C 프로그램 실행과정  (0) 2011.02.22
C 언어란?  (0) 2011.02.22
비트필드  (0) 2010.12.10
함수의 이해 / 데이터 전달  (0) 2010.12.10
과제 #3 함수, 포인터의 사용  (0) 2010.12.10
과제#4 배열과 문자열  (0) 2009.10.03