CodeUp 기초 100제/C

CodeUp[코드업] C언어 1038 ~ 1046 : [기초 - 산술 연산]

En_Geon 2019. 12. 8. 01:52

1038 : [기초 - 산술 연산] 정수 2개 입력받아 합 출력하기 1

문제 설명 : https://codeup.kr/problem.php?id=1038

 

정수 두 개를 합하는 문제다.

 

  • 정수 두 개를 입력받는다. 공백으로 구분된다.
  • 정수를 합하여 출력한다.
  • 합한 결과 값이 int 범위를 넘는지 생각해야 한다.

여기서는 연산자를 배운다.

1024 문제에서 연산자 우선순위를 배웠다. 연산자 우선순위는 매우 중요하기 때문에 보면서 실습해야 한다.

 

연산자의 첫 번째는 산술 연산자다.

산술 연산자는 기본적으로 알고 있는 수학에 대한 상식을 C언어로 그대로 옮긴 문법이다.

덧셈, 뺄셈 연산은 각각 '+'와 '-'로 표시하며 곱셈과 나눗셈은 각각 '*'와 '/'로 표시한다.

나머지 연산자는 '%'로 표시한다. 나머지 연산자는 헷갈리기 쉽다. 나중에 자세히 배울 것이다.

 

x = 3 + 4 - 5;로 초기화했을 때 코드의 순서는 이렇다.

 

  1. 우선순위가 같은 연산의 중첩. 따라서 결합성을 고려한다.
  2. 뺄셈 연산의 피연산자 중 하나가 임시결과다.
  3. 연산의 최종 결과를 x 변수에 저장(단순 대입 연산) 한다.

산술 연산자뿐만 아니라 앞으로 배울 모든 내용 전체에 적용되는 중요한 개념은 연산의 임시결과다.

여기서 피연산자가 임시결과이다.

3 + 4의 값은 7이다. 7은 덧셈 연산의 임시결과다. 임시결과 7에 뺄셈 연산을 수행한다.

임시결과에서 5를 뺌으로 얻은 결과 또한 임시결과다. 하지만 이후로 이어지는 연산이 더 없기 때문에 마지막 임시결과는 해당 구문의 최종 결과가 된다.

 

연산 과정에서 가장 중요한 것은 앞선 연산의 임시결과가 이어지는 다음 연산에 참여하여 또 다른 임시결과를 얻는 과정에서 유실된다는 점이다. 3 + 4로 얻는 임시결과 7에서 5를 뺌으로써 최종 결과 2를 얻는 동시에 3 + 4 결과인 7은 유실된다. 임시결과 7이 이후 연산에서 꼭 필요하다면 변수에 저장해두었다가 활용하거나 다시 계산해야 한다.

 

연산의 최종 결과 역시 임시결과다. 필요하다면 유실 전에 저장해야 한다.

 

본인은 여기서 멘붕이 왔다. 10번 이상 틀린 답을 제출했다.

어떤 두 수가 입력되는지 그 합의 결과 값이 int 범위가 넘는지 생각해야 한다. 본인은 이 부분을 생각하지 못했다.

넘어가지 않는다면 int형으로 써도 되지만 넘어간다면 다른 데이터형을 써야 한다. 이미 배운 것이다.

 

더보기

 

#include     <stdio.h>

 

int main()

{

    long long int x, y;

    scanf("%lld %lld", &x, &y);   

    printf("%lld", x+y);      

   

    return 0;
   

}

 

1039 : [기초 - 산술 연산] 정수 2개 입력받아 합 출력하기 2

문제 설명 : https://codeup.kr/problem.php?id=1039

 

정수 두 개를 합하는 문제다.

1038 문제와 같은 유형이다. 

 

  • 정수 두 개를 공백으로 구분되어 입력받는다.
  • 1038에서 배운 연산자를 사용한다.
  • 합한 결과 값이 int 범위를 넘는지 생각해야 한다. 
더보기

 

#include      <stdio.h>

int main ()
{
    long long int x, y;
    scanf("%lld %lld", &x, &y);
    printf("%lld", x+y);

 

    return 0;
}

 

1040 : [기초 - 산술 연산] 정수 1개 입력받아 부호 바꿔 출력하기

문제 설명 : https://codeup.kr/problem.php?id=1040

 

단항 연산자를 사용하여 부호를 바꿔 출력하는 문제다.

단항 연산자를 배운다.

 

  • 단항 연산자를 사용해 부호를 바꾼다.
  • 단항 연사자의 부호 연산자를 사용한다.

단항 연산자에는 증감 연산자 '++', '--'가 있고, 부호 연산자 '+', '-'가 있다.

 

부호 연산자 '-'는 피연산자의 부호를 반대로 변경한 결과를 저장한다.

피연산자가 음수면 양수, 양수면 음수가 연산의 결과가 된다.

부호 연산자 '+'는 하는 일이 없으며 쓰이는 경우도 거의 없다.

부호 연산자 '+'는 부호 연산자 '-'가 있으니까 형식적으로 추가해 놓은 것뿐이다.

 

증감 연산자에서는 증가 연산자 '++', 감소 연산자 '--'가 있다.

증감 연산자는 ++x 전위형, x-- 후위형이 있다. 

전위형 연산자는 값이 참조되기 전에 증가시킨다. 후위형 연산자는 값이 참조된 후에 증가시킨다. 

 

증감 연산자가 포함된 식을 이해하기 어려울 때는 증감 연산자를 따로 떼어내면 이해하기 쉽다.

 

전위형인 경우

j = ++i;   // 전위형

 

전위형을 떼어 표현한 경우

++i;     // 증가 후에

j = i;     // 참조하여 대입

후위형인 경우

j = i++;     // 후위형

 

후위형을 떼어 표현한 경우

j = i;      // 참조하여 대입 후에

i++;      // 증가

 

단항 증감 연산이 문법적으로 조금 어려운 부분은 전위식 표기일 경우엔 연산자 우선순위가 높지만 후위식 표기면 우선순위가 사실상 최하위가 된다. 연산자 우선순위가 낮은 편에 속하는 대입 연산자보다도 나중이 된다. 그러므로 단항 증감 연산을 후위식으로 표기했다면 해당 구문에서 그 단항 연산이 없는 것처럼 생각하는 것이 맞다.

그리고 그 구문이 다 끝나야지만 비로소 단항 증감 연산이 수행된다고 보면 된다. 

 

더보기

 

#include      <stdio.h>

int main()
{
    int x;
    scanf("%d", &x);
    printf("%d", -x);
   

    return 0;
}

 

1041 : [기초 - 산술 연산] 문자 1개 입력받아 다음 문자 출력하기

문제 설명 : https://codeup.kr/problem.php?id=1041

 

영문자를 입력받아 다음 문자를 출력하는 문제다.

 

  • 아스키 문자 표에서 'A'는 10진수 65로 저장한다.
  • 아스키 문자 표에서 'B'는 10진수 66으로 저장한다.
  • 문자를 입력받고 입력받은 문자를 연산하여 출력한다.
더보기

 

#include      <stdio.h>

int main()
{
    char x;
    scanf("%c", &x);
    printf("%c", x + 1);
   

    return 0;
}

 

1042 : [기초 - 산술 연산] 정수 2개 입력받아 나눈 몫 출력하기

문제 설명 : https://codeup.kr/problem.php?id=1042

 

정수를 입력받아 나눈 몫을 출력하는 문제다.

 

  • 1038에서 배운 산술 연산자 중 나눗셈 연산자를 사용한다.
  • 정수를 정수로 나눈 결과는 정수다.
  • 절대 0으로 나눌 수 없다.

정수 5를 정수 2로 나누면 연산 결과는 정수다.

소수점 이하 정보가 전부 절사 된다. 따라서 심각한 정보 왜곡이 발생한다.

 

더보기

 

#include      <stdio.h>

int main()
{
    int a, b;
    scanf("%d %d", &a, &b);
    printf("%d", a / b);

 

    return 0;
}

 

1043 : [기초 - 산술 연산] 정수 2개 입력받아 나눈 나머지 출력하기

문제 설명 : https://codeup.kr/problem.php?id=1043

 

정수를 입력받아 나눈 나머지를 출력하는 문제다.

 

  • 음(-)이 아닌 정수에 대해서만 연산된다.
  • 나머지 연산자도 나누기 연산자와 마찬가지로 0으로 나눈 나머지를 구할 수 없다.
  • 나머지 연산자의 피연산자로 실수가 사용될 수 없다.
  • 나머지 연산은 제수만큼 경우의 수를 갖는다.

1038에서 배운 나머지 연산자다.

어떤 수를 3으로 나눈 나머지를 구했다면 출력될 수 있는 숫자는 0, 1, 2 세 가지뿐이다. 

10이든 100이든 어떤 숫자든지 상관없이 나머지 연산 결과는 제수보다 클 수 없기 때문이다. 

이를 이용하면 일정 범위로 경우의 수를 강제할 수 있기 때문에 중요한 의미가 있다.

 

printf("%d", 8 % 5)의 의미는 8/5의 나머지를 출력하라는 것이다.

즉, 5로 8을 나눈 나머지 3을 출력한다.

그래서 본인은 나머지 연산자는 한 번 더 생각하게 되어서 헷갈린다고 했다.

 

더보기

 

#include      <stdio.h>

int main()
{
    int x, y;
    scanf("%d %d", &x, &y);
    printf("%d", x % y);

   

    return 0;
}

 

1044 : [기초 - 산술 연산] 정수 1개 입력받아 1 더해 출력하기

문제 설명 : https://codeup.kr/problem.php?id=1044

 

1040에서 배운 증감 연산자를 사용하여 출력하는 문제다.

 

  • 계산 후 값의 범위를 생각해야 한다.

증감 연산자를 사용하지 않고, 단순히 덧셈 연산자를 사용해도 같은 결과를 얻을 수 있다.

그러나 덧셈 연산자는 많이 사용해봤으므로 여기서는 증감 연산자를 사용해 출력하는 것을 추천한다.

 

더보기

 

#include      <stdio.h>

int main()
{
    long long int x;
    scanf("%lld", &x);
    printf("%lld", ++x);

 

    return 0;
}

 

1045 : [기초 - 산술 연산] 정수 2개 입력받아 자동 계산하기

문제 설명 : https://codeup.kr/problem.php?id=1045

 

정수를 입력받아 합, 차, 곱, 몫, 나머지, 나눈 값을 출력하는 종합문제다.

 

  • 줄 바꿈(개행)을 해야 한다.
  • 정수 / 정수는 정수다. 

정수 / 정수는 정수다. 그러나 마지막 값은 실수를 출력해야 한다. 이것은 형 변환이 필요하다는 것이다.

 

형 변환이란 변수 또는 상수의 타입을 다른 타입으로 변환하는 것이다.

형 변환 방법은 아주 간단하다. '(타입) 피연산자'이다.

 

형 변환의 예

 

double d = 85.4;

int score = (int)d;

// double 타입의 변수 d를 int타입으로 형 변환

두 번째 줄의 연산과정을 단계벌로 살펴보면 이렇다.

int score = (int)d;

int score = (int)85.4; 

//변수 d의 값을 읽어 와서 형 변환한다.

 

int score = 85; 

// 형 변환의 결과인 85를 변수 score에 저장한다.

 

형 변환에는 자동 형 변환(묵시적 형 변환), 강제 형 변환(명시적 형 변환)이 있다.

 

자동 형 변환(묵시적 형 변환)

  1. 대입 연산자의 전달 과정에서 발생하는 자동 형 변환
  2. 정수의 승격에 의한 자동 형 변환
  3. 피연산자의 자료형 불일치로 발생하는 자동 형 변환
더보기

1. 대입 연산자의 왼편과 오른편에 존재하는 두 피연산자의 자료형이 일치하지 않으면, 왼편에 있는 피연산자를 대상으로 형 변환이 자동으로 일어난다. (저장소의 자료형에 맞춰 형 변환이 일어나야 값이 저장이 가능)

 

double x = 189;  → double x = 189.0;

 

이 경우는 대입 연산자의 왼편에 있는 x는 double형이지만, 189는 int형이다. 따라서 int형 정수인 189가 double형 실수 189.0으로 형 변환되어서 x에 저장된다.

 

int y = 5.1896; → int y = 5;

 

이 경우는 double형 상수 5.1896가 int형으로 변환되어 변수 y에 저장된다.

 

int형은 정수형이라 소수점 이하의 값을 절사 한다.

형 변환의 과정에서 5.1896이 정수 5로 변환되어서 결괏값이 y에 저장된다.

실수형 데이터를 정수형 데이터로 변환하는 과정에서 실수 부분의 손실이 발생한다.

 

int z = 129;

char ch = z;

 

129가 저장된 변수 z의 비트 열은 다음과 같다.

 

00000000 00000000 00000000 10000001

 

이 데이터를 변수 ch에 저장하기 위해서는 1바이트 크기로 줄여야 한다.

이때 상위 바이트의 손실이 발생한 결과는 10000001이다.

정수로는 -127이다. 상위 바이트의 손실로 부호가 바뀐 경우다.

 

2. 일반적으로 CPU가 처리하기에 가장 적합한 크기의 정수 자료형을 int로 정의한다. 따라서 int형 연산의 속도가 다른 자료형의 연산속도에 비해 동일하거나 더 빠르다.

 

그래서 int보다 작은 크기의 정수형 데이터는 int형 데이터로 형 변환이 되어 연산된다.

 

short x = 15, y = 25;

short z = x + y;

 

여기서 x와 y가 int형으로 형 변환이 발생한다. 그런데 위의 코드에서 정수의 승격만 일어난 게 아니다.

x + y의 계산 결과는 4바이트 크기의 int형 정수다. 따라서 이 값을 변수 z에 저장하기 위해, 대입 연산 과정에서의 형 변환(상위 바이트의 손실)이 다시 일어나게 된다.

 

3. 사칙연산과 같은 기본적인 산술 연산에는 두 개의 피연산자가 필요하다. 이 둘의 자료형은 일치해야 하며, 만약 일치하지 않을 시에는 자료형의 일치를 목적으로 자동 형 변화이 일어난다.

 

double x = 8.48 + 48;

 

실수형 데이터와 정수형 데이터의 합을 요구하고 있다. 정수와 실수는 표현방식이 다르므로 사실상 덧셈이 불가능하다. CPU는 같은 자료형의 두 피연산자를 대상으로만 연산이 가능하도록 설계되어 있기 때문이다.

 

8.48을 정수형으로 형 변환하거나 48를 실수형으로 형 변환해야 한다. 그러나 8.48을 정수형으로 변환하면 실수 부분의 손실로 8이 된다. 48를 실수형으로 변환하면 48.0이 되어 데이터의 손실이 최소화된다.

 

피연산자의 자료형이 일치하지 않아서 발생하는 자동 형 변환은 데이터의 손실을 최소화하는 방향으로 진행된다. 

 

산술 연산에서 형 변환(형 변환의 기준은 '데이터 손실의 최소화'다.)

char → int → long → long long → float → double → long double

 

두 피연산자가 다를 경우 상위 우선순위를 가진 연산자로 하위 우선순위를 가진 연산자가 형 변환된다.

int형과 double형이 있다면 int형이 double형 실수로 형 변환되어 연산된다.

 

char형 정수와 short형 정수는 정수의 승격에 의해 둘 다 int형 정수로 변환된다. 

 

강제 형 변환(명시적 형 변환)

강제 형 변환이란 형 변환 연산자를 이용해 강제로 형 변환을 명령하는 것이다.

위 형 변환의 예가 바로 강제 형 변환의 예다. 위 예의 (int) 즉, (타입)을 형 변환 연산자라 한다.

 

더보기

 

#include      <stdio.h>

 

int main()

{

    int x, y;

    scanf("%d %d", &x, &y);

    printf("%d\n", x+y);

    printf("%d\n", x-y);

    printf("%d\n", x*y);

    printf("%d\n", x/y);

    printf("%d\n", x%y);

    printf("%.2f", (float)x/y);
   

    return 0;
}

 

1046 : [기초 - 산술 연산] 정수 3개 입력받아 합과 평균 출력하기

문제 설명 : https://codeup.kr/problem.php?id=1046

 

정수를 입력받아 합과 평균을 출력하는 문제다.

 

  • 소수점 자릿수를 확인하고 출력한다.
  • 어떻게 형 변환이 이루어져야 되는지 생각한다.

정수를 입력받아 합을 출력하고 평균은 소수점이 나와야 하므로 실수형으로 형 변환해야 한다.

 

더보기

 

#include      <stdio.h>

int main()
{
    int x, y, z;
    scanf("%d %d %d", &x, &y, &z);
    printf("%d\n", x + y + z);
    printf("%.1f", (x + y + z)/3.0);

 

    return 0;
}