{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# C - Day 01" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# 변수 할당\n", "변수의 할당에는 몇 가지 다른 방법이 있지만, 원리는 똑같다. 항상 다음의 5가지 구성요소로 되어 있다. 다음 문자열을 보자.\n", "```int height = 180;```\n", "* 처음에 등장하는 ```int```는 자료형이라고 한다.\n", "* 두번째 등장하는 ```height```는 변수의 이름이다. \n", "* 세번째 등장하는 ```=```는 대입연산자이다.\n", "* 네번째 등장하는 ```180```는 변수에 저장될 값이다. \n", "* 다섯번째 등장하는 ```;```는 문장의 끝을 나타내는 마침표이다." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 문제 1\n", "다음의 변수 할당 예를 살펴 보자. 또 다른 방법은 없는지 찾아보자. 몇 개의 변수까지 한 번에 선언할 수 있을까? " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "#include \n", "\n", "int main()\n", "{\n", " // type 1 declaration & initialization\n", " int height = 180;\n", " \n", " // type 2 \n", " int length; // declaration\n", " length = 180; // initialization\n", " \n", " // type 3 multiples of type1 \n", " int height1 = 180, length1 = 180;\n", " \n", " // type 4 type2, 3 mixed\n", " int height2 = 180, length2;\n", " length2 = 180;\n", " \n", " printf(\"%d\\n\", height);\n", " \n", " return 0;\n", "}" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# 변수 자료형\n", "\n", "C언어는 자료형(type)을 매우 중요하고 엄격하게 지켜야한다. 화면에 문자/숫자를 출력하거나 입력을 받을 때에도 자료형이 사용되고 연산을 할 때도 문자형이 사용된다. 값을 저장하는 변수에도 문자형이 꼭 필요하다. 아래 중요한 문자형들이 나열되어 있다. \n", "\n", "* char : 문자형, ? byte\n", "* int : 정수형, ? byte\n", "* short : 정수형, ? byte\n", "* long : 정수형, ? byte\n", "* float : 실수형, ? byte\n", "* double : 실수형, ? byte" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 문제 2\n", "다음의 예제 코드는 자료형의 크기를 확인하는 코드이다. 자료형의 크기는 CPU 아키텍처의 종류에 따라 다를 수 있다. 아래 코드를 수정하여 다른 자료형들의 크기를 확인해보자. (```printf```는 쌍따옴표의 글자들을 출력하는 함수이다. ```%lu```는 뒤에 따라오는 인자의 값의 서식을 정하는 서식지정자이다. " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "#include \n", "\n", "int main()\n", "{\n", " printf(\"sizeof(double) = %lu \\n\", sizeof(double));\n", " return 0;\n", "}" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "앞에서 다양한 변수형에 대한 크기를 소개하였다. 변수 형의 크기를 확인하는 코드를 작성 한 후 **문제 1의 변수형에 있는 ?를 채워 넣어 보자.**" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# 산술 연산자의 종류\n", "\n", "다음 예를 살펴보고 연산자의 종류에 대해 이해해보자" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "#include \n", "\n", "int main()\n", "{\n", " int add, sub, mul, dev, modular;\n", " int num1 = 5, num2 = 7;\n", " \n", " add = num1 + num2;\n", " sub = num1 - num2;\n", " mul = num1 * num2;\n", " dev = num2 / num1;\n", " modular = num2 % num1;\n", " \n", " printf(\"num1 + num2; = %d\\n\", add);\n", " printf(\"num1 - num2; = %d\\n\", sub);\n", " printf(\"num1 * num2; = %d\\n\", mul);\n", " printf(\"num2 / num1; = %d\\n\", dev);\n", " printf(\"num1 %% num2; = %d\\n\", modular);\n", " return 0;\n", "}" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 문제 3\n", "위의 코드에서 나눗셈의 결과는 실수인데, 정수부의 값만 출력된다. 수정하여 소숫점까지 나오도록 해보자. " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "#include \n", "\n", "int main()\n", "{\n", " // your code here\n", " \n", " return 0;\n", "}" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# 변수 명 작성 규칙\n", "## 문제 4\n", "\n", "변수명으로 사용할 수 있는 문자 조합과 불가능한 조합이 있다. 그 조합을 찾아보자. 다음과 같은 변수명들은 사용가능한 조합인지 코드를 작성하여 가능한 변수 명인지 불가능한 변수명인지 확인해보자\n", "* times10 (가능/불가능)\n", "* _done (가능/불가능)\n", "* __done (가능/불가능)\n", "* 10times (가능/불가능)\n", "* get_next_char (가능/불가능)\n", "* get_next-char (가능/불가능)\n", "* get-next-char (가능/불가능)\n", "* job, joB, JoB (가능/불가능)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "#include \n", "\n", "int main()\n", "{\n", " // your code here\n", "}" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# define 문\n", "\n", "숫자는 사람이 기억하기 어렵기 때문에 숫자에 이름을 달아 쓰는 경우가 흔하다. 예를 들어 핸드폰 모델이 MQAF2KH이라는 조합일 때는 기억하지 못하지만, Galaxy S9이라고 하면 쉽게 기억하는 것과 같은 이치이다. 문자의 수는 더 많지만, 의미가 있기 때문에 더 쉽게 기억할 수 있다. 이와 같은 방식으로 C에서도 문자에 이름을 붙여 줄 수 있다. 다음의 예를 보자." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "#include \n", "#define PI 3.141592\n", "\n", "int main()\n", "{\n", " printf(\"radius of a circle with radius 5 = %f\", 2*PI*PI*5);\n", " return 0;\n", "}" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 문제 5\n", "다음의 코드에서 상수에 해당하는 값들에 이름을 부여해보자. 32.0은 FR, (5.0 / 9.0) 은 SF라고 이름을 붙여 보자. 여기서 scanf는 사용자로부터 값을 입력받는 합수이다. " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "/* Converts a Fahrenheit temperature to Celsius */\n", "\n", "#include \n", "\n", "//#define \n", "//#define \n", "\n", "int main(void)\n", "{\n", " float fahrenheit = 39.0, celsius;\n", "\n", " celsius = (fahrenheit - 32.0) * (5.0/9.0);\n", "\n", " printf(\"Celsius equivalent: %.1f\\n\", celsius);\n", "\n", " return 0;\n", "}\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# 관계 연산자\n", "\n", "## 문제 6\n", "수학에서 부등호의 연산과 같다고 생각하면 된다. 아래의 코드를 읽어보고 결과가 참인지 거짓인지 예상해보자. 이런 관계 연산자를 언제 어떻게 쓸 수 있을 지 생각해보고 친구들과 논의해보자.\n", "\n", "1. 참 / 거짓\n", "2. 참 / 거짓\n", "3. 참 / 거짓\n", "4. 참 / 거짓\n", "5. 참 / 거짓\n", "6. 참 / 거짓\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "#include \n", "\n", "int main(void)\n", "{\n", " int num1 = 5, num2 = 1, num3 = 10;\n", " int result1, result2, result3;\n", " \n", " result1 = num1 > num2;\n", " result2 = num2 == num3 > num1;\n", " result3 = num1 < num2 < num3;\n", " \n", " printf(\"1. result1 = %d\\n\", result1);\n", " printf(\"2. result2 = %d\\n\", result2);\n", " printf(\"3. result3 = %d\\n\", result3);\n", " printf(\"4. result1 >= result2 %d\\n\", result1 >= result2);\n", " printf(\"5. result1 != result3 %d\\n\", result1 != result3);\n", " printf(\"6. result1 == result1 %d\\n\", result1 == result1);\n", "\n", " return 0;\n", "}\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# 논리 연산자\n", "논리 연산자는 하나 이상의 관계 연산자의 조합을 평가할 때 유용하다. 예를 들어 아침에 버스를 타고 왔고, 정문부터는 자전거를 타고 이 건물까지 온 사람은 오른쪽으로 줄을 서고, 둘 중에 하나라도 참이 아닌 경우에는 왼쪽, 둘 다 아닌 경우는 집으로 돌아가라는 식의 표현을 생각해볼 수 있다. 둘 다 참인 경우를 AND 를 표현하는 &&으로 쓰고 둘 중에 하나만 참인 경우(OR)는 ||으로 쓰며, 부정을 표현하는 방법은 수식에 !를 붙이면된다. AND, OR 등의 논리 연산자가 한 번 이상 수식에서 사용된다면, 실행의 우선 순위에 맞게 괄호로 묶어 주어야 한다.\n", "\n", "## 문제 7\n", "아래의 코드에서 !num1의 출력 결과는 0이다. 어떤 경우에 1이 되는지 검사해보자.\n", "\n", "각 줄의 의미를 먼저 생각해보고 예상한 데로 결과가 나오는지 확인해보자." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "#include \n", "\n", "int main(void)\n", "{\n", " int num1 = 7, num2 = 2, num3 = 5;\n", " int result1, result2, result3, result4;\n", " \n", " result1 = !num1;\n", " result2 = !0;\n", " result3 = num1 < num2 || num2 != num3;\n", " result4 = ((num1 - 4) || (num1 != num2)) && (2 + 2 != num3);\n", " \n", " printf(\"result1 = %d\\n\", result1);\n", " printf(\"result2 = %d\\n\", result2);\n", " printf(\"result3 = %d\\n\", result3);\n", " printf(\"result4 = %d\\n\", result4);\n", " \n", " return 0;\n", "}" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# 비트 논리 연산자\n", "\n", "비트 연산자를 이해하려면 2진수를 이해해야 한다. 2진수는 0과 1로만 표현되는 수 체계를 말한다. 7은 111이고, 2는 10 이며 5는 101로 표현된다. \n", "\n", "논리 연산자에서는 &, | 두 번 연속으로 사용되었는데, 여기서는 한 번씩만 쓰이고 있기 때문에 혼돈하지 않기 위해 주의해야 한다. \n", "\n", "* & Bitwise AND : 두 비트가 1일 때만 1, 그 외는 0\n", "* | Bitwise OR : 두 비트 중 하나라도 1이면 1, 그 외는 0\n", "* \\* Bitwise Exclusive OR : 두 비트가 서로 다르면 1, 그 외는 0\n", "* << shift left : bit를 왼쪽으로 한 칸 이동 (<< 1 일 때는 x2 한 것과 같은 효과)\n", "* \\>\\> shift right : bit를 오른쪽으로 한 칸 이동 (>> 1 일 때는 /2 한 것과 같은 효과)\n", "\n", "## 문제 8\n", "\n", "아래의 코드를 읽어보고 결과를 예측 해보자." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "#include \n", "\n", "int main(void)\n", "{\n", " int num1 = 7, num2 = 2, num3 = 5;\n", " int result1, result2, result3;\n", " \n", " result1 = num2 & num3;\n", " result2 = num1 ^ num2;\n", " result3 = num1 | num3;\n", " \n", " printf(\"result1 = %d\\n\", result1);\n", " printf(\"result2 = %d\\n\", result2);\n", " printf(\"result3 = %d\\n\", result3);\n", " printf(\"result4 = %d\\n\", num3 << 1);\n", " printf(\"result5 = %d\\n\", (num3 *2) >> 2 );\n", " \n", " return 0;\n", "}" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# 증감 연산자\n", "\n", "가장 많이 쓰이는 연산자들로서 단순하고 강력하다. ++ 또는 -- 를 변수 앞에 쓰느냐 또는 뒤에 쓰느냐에 따라 동작 방식이 달라진다. ++를 변수 앞에 쓰면 변수의 현재 값을 1 증가 시킨 후 활용한다. ++를 변수 뒤에 쓰면 현재 값을 먼저 활용한 후 1을 증가시킨다. " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "#include \n", "\n", "int main(void)\n", "{\n", " int num1 = 5;\n", " printf(\"num1 = %d\\n\", num1);\n", " printf(\"num1++ = %d\\n\", num1++);\n", " printf(\"num1 = %d\\n\", num1);\n", " printf(\"++num1 = %d\\n\", ++num1);\n", " printf(\"num1 = %d\\n\", num1);\n", " \n", " return 0;\n", "}" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "아래의 코드를 읽어보고, 실행 결과를 예측 해보자." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "#include \n", "\n", "int main(void)\n", "{\n", " int num1 = 5, num2 = 7, num3 = 12;\n", " int result1, result2, result3;\n", " \n", " result1 = ++num1 + ++num2;\n", " result2 = num3++;\n", " result3 = num2-- - ++num1 + ++num1 + num2--;\n", " \n", " printf(\"result1 = %d\\n\", result1);\n", " printf(\"result2 = %d\\n\", result2);\n", " printf(\"result3 = %d\\n\", result3);\n", " \n", " printf(\"num1 = %d, num2 = %d, num3 = %d\\n\", num1, num2, num3);\n", " \n", " return 0;\n", "}" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# 조건 연산자\n", "\n", "3항 연산자로 알려진 조건 연산자는 앞으로 배우게 될 `if-else` 조건문의 대용으로 많이 활용된다. 구조가 생경하기 때문에 혼란스러울 수 있지만, 어려울 것은 없습니다. \n", "\n", "구조는 다음과 같습니다. \n", "* 비교문, 그리고 비교문에 의문형을 붙입니다.\n", "* 참일 때 실행될 문장, 그리고 구분을 : (콜론)으로 합니다. \n", "* 거짓일 때 실행될 문장\n", "\n", "다음의 코드의 실행 결과를 예상해 봅시다. \n", "\n", "그리고 두 문장으로 이루어진 조건 연산자를 한 문장으로 만들어 봅시다. " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "#include \n", "\n", "int main(void)\n", "{\n", " int num1 = 12, num2 = 8, num3 = 21, min;\n", " \n", " // 아래 두 문장을 한 문장으로 변경해봅시다. (힌트: 중첩)\n", " min = (num1 < num2) ? num1 : num2;\n", " min = (min < num3) ? min : num3; \n", " \n", " printf(\"Minimum number = %d\\n\", min);\n", " \n", " return 0;\n", "}" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# 대입 연산자\n", "\n", "수학에서 등호는 프로그래밍 언어에서 대입 입니다. 좌변의 값을 우변으로 복사하는 것이라 생각할 수 있습니다.\n", "대입 연산자는 등호와 또 다른 연산자로 구성할 수 있습니다. 예를 들어 y = y + x 는 **y += x** 로 표현할 수 있습니다. 좌변에서 사용된 변수와 다른 어떤 값을 합하여 다시 좌변의 변수에 저장하는 식에서 빈번히 사용됩니다. 나머지 패턴들도 유사합니다. \n", "\n", "아래의 코드의 실행 결과를 예측 해봅시다. " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "#include \n", "\n", "int main(void)\n", "{\n", " int x = 10, y = 5, z =25;\n", " \n", " x += y = z;\n", " printf(\"x = %d, y = %d, z = %d\\n\", x, y, z);\n", " \n", " x = y += z;\n", " printf(\"x = %d, y = %d, z = %d\\n\", x, y, z);\n", " \n", " x += y - z;\n", " printf(\"x = %d, y = %d, z = %d\\n\", x, y, z);\n", " \n", " x += y;\n", " printf(\"x = %d, y = %d, z = %d\\n\", x, y, z);\n", " \n", " x %= 3;\n", " printf(\"x = %d, y = %d, z = %d\\n\", x, y, z);\n", "\n", " x /= y + 2;\n", " printf(\"x = %d, y = %d, z = %d\\n\", x, y, z);\n", " \n", " return 0;\n", "}" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# 형 변환 연산자 (casting)\n", "\n", "`int`은 정수형 변수 타입이기 때문에 소숫점을 저장할 수 없습니다. 예를 들어 `int n = 5/7;`이라고 한다면 `n` 은 정수만 저장하기 때문에 정보의 손실이 생깁니다. 하지만, 변수는 정수형이지만 소수점을 계산해야 한다면, 일시적으로 형을 변환시킬 수가 있습니다. 아래의 코드의 예처럼 `(변수형)`수식의 형태를 갖고 있습니다. \n", "\n", "아래의 코드의 예의 실행 결과를 예상해보고 결과를 확인해봅시다. \n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "#include \n", "\n", "int main()\n", "{\n", " int num1 = 7, num2 = 17;\n", " printf(\"division = %d\\n\", num2/num1);\n", " printf(\"type conversion = %.2f\\n\", (float)(num2/num1);\n", " return 0;\n", "}" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "실수형 변수와 정수형 변수를 식에 섞어서 계산하면 어떻게 되는지 확인해봅시다. \n", "\n", "그리고, float 형 변수와 double 형 변수의 계산 결과를 int 형 변수에 저장해 봅시다. 정수에서 실수로, 실수에서 정수로 casting 할 때 부족한 정보는 어떻게 표현되는지 확인해봅시다. " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "#include \n", "\n", "int main()\n", "{\n", " // your code here\n", " return 0;\n", "}" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# 변수의 범위(scope)\n", "\n", "아래의 코드는 중괄호 안에 같은 이름의 변수들이 여러 번 사용되었다. 동작이 어떻게 되는지 예측해보자. 그리고 예상한 결과처럼 동작하는지 확인해보자. \n", "\n", "아래와 같이 같은 이름의 변수를 쓰는 것은 어떤 문제가 있는가?" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "// local variable\n", "\n", "#include \n", "\n", "int main()\n", "{\n", " int a = 7, b = 8;\n", " printf(\"a = %d, b = %d\\n\", a, b);\n", " {\n", " int b = 10;\n", " float c = 8.5;\n", " printf(\"a = %d, b = %d, c = %f\\n\", a, b, c);\n", " a = b;\n", " ++a;\n", " {\n", " int c;\n", " c = b;\n", " --c;\n", " printf(\"a = %d, b = %d, c = %d\\n\", a, b, c);\n", " }\n", " }\n", " printf(\"a = %d, b = %d\\n\", a, b);\n", "}" ] } ], "metadata": { "kernelspec": { "display_name": "C", "language": "c", "name": "c" }, "language_info": { "file_extension": ".c", "mimetype": "text/plain", "name": "c" } }, "nbformat": 4, "nbformat_minor": 2 }