728x90
함수 선언과 호출

강의 링크 : https://www.edwith.org/boostcourse-mo-kotlin-basic1/joinLectures/28611

함수 선언과 호출

fun sum(a:Int, b:Int): Int{ var sum = a+b return sum }
  • fun 키워드로 함수 선언
    • 매개변수 (이름 : type) 선언
    • 함수의 반환 타입 결정 (fun _ : type)
    • 반환 필요 시 return
  • 함수의 간략화된 선언 - 바로 return하는 경우
fun sum(a:Int, b:Int) : Int = a+b //매개변수를 통해 return 추론이 가능한 경우 return 자료형도 생략 가능 fun sum(a:Int, b:Int) = a+b
  • 매개변수의 기본값 : 인자가 전달되지 않을 때 기본으로 사용할 값 설정 가능
fun email(ID : String, domain : String = "naver.com") { println("your email is ${ID}@${domain}") } fun main(){ email("Kildong") //your email is Kildong@naver.com email("Kildong", "Gmail.com") //your email is Kildong@Gmail.com }
  • 반환값이 없는 함수 : Unit return
fun out(name : String) : Unit { println("name : ${name}") return Unit //return Unit은 아무것도 반환하지 않음(생략 가능) } fun outp(name : String) : Unit = println("name : ${name}") //위 함수와 동일하게 동작
  • 함수 매개변수 지정
    • 기본값이 있는 매개변수의 경우 지정하여 대입 가능
fun sum(a : Int = 1, b : Int = 2) = a+b fun main() { println("1+2 = ${sum()}") //1+2 = 3 println("1+4 = ${sum(b = 4)}") //1+4 = 5 println("3+2 = ${sum(a = 3)}") //3+2 = 5 }
  • 가변인자 : vararg 키워드로 여러 개의 인수를 받을 수 있음
    • for문을 이용하여 함수에서 처리 가능
fun varprint(vararg a : Int) { for (n in a) { println("number is ${n}") } println("===========================") } fun main() { varprint(1) varprint(1,2) varprint(1,2,3,4,5,6,7,8,9) } /*출력결과 number is 1 =========================== number is 1 number is 2 =========================== number is 1 number is 2 number is 3 number is 4 number is 5 number is 6 number is 7 number is 8 number is 9 =========================== */

함수형 프로그래밍 패러다임 (1)

  • 코틀린은 멀티 패러다임 언어 : 함수형 / 객체지향
  • 함수형 프로그래밍
    • 단순한 코드 지향
    • 코드의 테스트나 재사용성 증가
    • 람다식, 고차함수 활용 : 함수의 인자에 함수를 대입 가능
    • 순수 함수 제공
  • 순수 함수
    • 부작용이 없는 함수 : 동일 입력 - 동일 출력
    • 값의 예측이 가능
    • 함수 외부의 상태를 바꾸지 않음 : 함수에 없는 외부 객체가 사용되는 경우(함수 리턴값을 대입하는 등)
    • 람다식, 고차함수 사용을 위해 필요한 개념
    • 입력 - 내용을 분리하여 재사용성이 높음
    • 병행 작업 시 안전
    • 테스트, 디버깅 시 유리
  • 람다식
    • 익명 함수의 일종으로 이름 선언 없이 사용 가능
    • {x, y -> x+y}
    • 고차 함수에 인자로 넘기거나 결과값으로 사용할 수 있음
  • 일급 객체(First Class Citizen)
    • 함수의 인자, 반환값으로 쓰일 수 있음
    • 변수에 대입할 수 있음
    • 코틀린의 함수는 일급 객체로 다룸
  • 고차 함수
    • 함수 인자가 함수가 되는 것
fun highFunc(sum : (Int, Int) -> Int, a : Int, b : Int) : Int { //첫 번째 매개변수 : sum이라는 람다식 변수는 Int 2개를 받아 Int를 반환 return sum(a, b) } fun main() { println(highFunc({x, y -> x + y}, 10, 20)) }

함수형 프로그래밍 패러다임 (2)

  • 고차함수의 호출 방법 : 값에 의한 호출, 이름에 의한 호출, 참조에 의한 호출
  • 값에 의한 호출 : 함수 인자는 값으로 처리되어 수행된 값을 전달
fun main() { val result = callByValue(lambda()) // 람다식 함수를 호출 println(result) } fun callByValue(b: Boolean): Boolean { // 일반 변수 자료형으로 선언된 매개변수 println("callByValue function") return b } val lambda: () -> Boolean = { // 람다 표현식이 두 줄이다 println("lambda function") true // 마지막 표현식 문장의 결과가 반환 }
  • 이름에 의한 호출 : 함수 이름을 매개변수로 전달하여, 함수가 사용될 때 실행
fun main() { val result = callByName(otherLambda) // 람다식 이름으로 호출 println(result) } fun callByName(b: () -> Boolean): Boolean { // 람다식 함수 자료형으로 선언된 매개변수 println("callByName function") return b() } val otherLambda: () -> Boolean = { println("otherLambda function") true }
  • 참조에 의한 호출 : 콜론 기호(::)를 이용한 호출
fun main() { // 1. 인자와 반환값이 있는 함수 val res1 = funcParam(3, 2, ::sum) println(res1) // 2. 인자가 없는 함수 hello(::text) // 반환값이 없음 // 3. 일반 변수에 값처럼 할당 val likeLambda = ::sum println(likeLambda(6,6)) } fun sum(a: Int, b: Int) = a + b fun text(a: String, b: String) = "Hi! $a $b" fun funcParam(a: Int, b: Int, c: (Int, Int) -> Int): Int { return c(a, b) } fun hello(body: (String, String) -> String): Unit { println(body("Hello", "World")) }

익명함수, 인라인 함수

  • 익명 함수 : 이름이 없는 함수
    • 람다식 함수를 위한 임시 함수로 사용
    • 람다식에서 쓰기 어려운 return, break continue 등을 사용하기 위함
fun (x:Int, y:Int) : Int = x+y val add : (Int, Int) -> Int = fun(x,y) = x+y val add = fun(x : Int, y:Int) = x+y // 람다식과 유사한 형태
  • 인라인 함수 : 함수가 호출되는 곳에 함수 내용을 복사
    • 함수 호출 시 코드가 분기하는데, 이 부분이 없어지므로 성능이 증가
    • 과도한 호출 시 main 함수 자체의 크기가 커질 수 있음
inline fun foo(...) { ... } fun main(){ foo() // foo 내용이 복사 }

인라인 함수의 제한

  • 코드가 복사되므로 내용이 많은 인라인 함수는 파일 크기를 증가시킬 수 있음
  • noinline : 람다식 함수는 인라인 되지 않도록 할 수 있음
inline fun foo(bar1 : () -> Unit, noinline bar2 : () -> Unit) { ... //bar1 람다식은 인라인 복사되지만, bar2는 인라인 x }
  • 확장 함수
    • 클래스의 멤버 함수를 외부에서 추가할 수 있음
    • 동일한 멤버나 메소드 존재 시 기존의 함수가 우선하여 호출됨

중위 함수, 재귀 함수

  • 중위 함수
    • 클래스 멤버 호출 시 점을 생략하고, 함수 이름 뒤의 소괄호를 생략
    • 조건
      • 멤버의 메소드 혹은 확장 함수
      • 매개변수가 존재
      • infix 키워드로 정의
infix fun Int.multiply(x:Int) : Int { return this * x } fun main { // 기존 표현법 : val multi = 3.multiply(10) val multi = 3 multiply 10 // 30 }
  • 재귀 함수
    • 자기 자신을 다시 호출
    • 필수 조건
      • 탈출 조건을 만들어야 함(무한루프 방지)
      • 호출 회수에 제한(함수 호출은 스택을 이용하므로)
    • 꼬리 재쉬 함수
      • 함수 분기 없이 재귀 호출 시 함수 영역을덮어씌우면서 호출 (스택 영역을 사용하지 않음)
      • 무한히 호출하더라도 stack overflow가 없음
      • tailrec 키워드로 선언
// 팩토리얼 함수 fun factorial(n:Int): Long { return if(n == 1) n.toLong() else n*factorial(n-1) } //꼬리재귀 팩토리얼 tailrec fun factorial(n : Int, run : Int = 1) : Long { return if(n ==1) run.toLong() else factorial(n-1, run * n) }
pn
728x90
728x90
코틀린의 특징

강의 링크 : https://www.edwith.org/boostcourse-mo-kotlin-basic1/joinLectures/28611

코틀린의 특징

  • 안드로이드의 주 개발 언어인 JAVA가 갖는 한계성을 보완 (애플이 Obj-C에서 Swift로 넘어간 것과 같은 맥락)
  • 목표
    • 웹, 어플(Android/IOS), 임베디드, IoT 등 모든 개발을 다양한 플랫폼에서 개발하고자 함
  • 특징
    • Jetbrain에서 개발 / 보급
    • 간결한 코드, 높은 호환성
    • 세미콜론은 선택
    • 안드로이드 공식 언어
    • 변후는 Nullable (?로 선언) / Not Null로 구분 가능 : Java의 NullpointerException을 방지
  • 플랫폼
    • JVM : 자바 가상 머신에서 동작하는 어플 (JAVA와 호환 가능)
    • JS : 자바스크립트에 의해 동작하는 웹앱
    • Native : LLVM 기반(ARM, x86 등) 컴파일을 지원
      • IOS / Mac / Android / Windows / Linux / WebAssembly 등등
  • 장점
    • 자료형 오류를 미리 잡을 수 있는 정적 언어(statically typed) : 컴파일러가 변수 타입을 미리 검증
    • 널 포인터로 인한 중단 예방 - NullpointerException(NPE)에서 자유로움
    • 자바와 100% 호환 : JVM 상에서 동작 가능
    • 함수형 / 객체지향 모두 가능
    • 세미콜론 생략 가능

기본 자료형과 변수 선언 (1) 불변형, 기본형

  • 자료형
    • 정수형 Int (1)
    • 문자열 String ("1")
    • 실수형 Float (1.00)
    • 그 외 (Double 등)
  • 변수
    • 불변형 val : 선언 후 값 수정 불가
    • 가변형 var : 수정 가능
    • 변수명은 숫자로 시작할 수 없고, 코틀린 키워드(while, if 등)으로는 선언 불가
val username : String = "kildong" //키워드 불변 / 이름 username : 자료형 문자열 / 값 "kildong" // 자료형은 대문자로 시작함에 유의
  • 변수 타입 지정을 해주지 않아도 컴파일러가 타입을 추론해줌
    • Ctrl+Shift+P를 누르면 추론된 타입 확인 가능
    • 자료형 추론을 하고자 하는 경우 초기값을 반드시 선언해주어야 함
var number = 10 //자료형 추론을 위해서는 초기값을 주거나 var number : Int //초기값이 없는 경우 자료형을 줘야 함
  • 카멜 표기법
    • 긴 이름의 변수를 선언하는 규칙 중 하나
    • 일반 변수, 함수명은 단어가 변경될 때 대문자로 시작 (카멜 표기법)
    • 클래스의 경우 대문자로 시작 (파스칼 표기법)
val camelCase var numberOfBooks //변수 선언 - Camel Expr Class AnimalCategory (){} Class CarEngine (){} //클래스 선언 - Pascal Expr

기본 자료형과 변수 선언방법 (2) 정수형과 실수형

  • 정수형 변수
    • Long : 8바이트
    • Int : 4바이트
    • Short : 2바이트 (-32768 ~ 32767)
    • Byte : 1바이트 (-128 ~ 127)
    • 부호 없는 정수형 : 앞에 U를 붙임 (0부터 2n2^n값까지)
  • 정수형 추론
    • 자료형 생략 시 Long 외에는 Int로 추론됨
    • 접미사 L : Long으로 추론 (ex. 123L)
    • 접두사 0x : 16진법 Int (ex.0x0F)
    • 접두사 0b : 2진 Int (ex.0b001100)
    • 접미사 u(uL) : unsigned int(Long) (ex. 123u, 123uL)
    • 가독성 : 언더스코어로 큰 수를 읽기 쉽게 표현 (ex. 123_456_789)
  • 실수형 변수
    • Double : 8바이트
    • Float : 4바이트
  • 실수형 추론
    • 기본은 Double로 추론
    • 접미사 F : Float로 추론됨 (ex. 3.14F)
  • 실수형 변수는 부동 소수점 표현
    • bit 일부는 기수를 일부는 지수 표현에 사용됨
    • 이로 인해 정확한 숫자 표현은 불가능 / 약간의 오차 존재

기본 자료형과 변수 선언방법 (3) 크기 범위와 기타 자료형

  • 자료형의 음수 표현 (2의 보수)
    • 2의 보수 : 이진수 값을 뒤집고 +1
      • ex. -6 : 0000 0110(2) >> 1111 1001(2) (뒤집기)>> 1111 1010(2) (+1)
    • 제일 왼쪽 비트(가장 큰 자리수)가 부호 비트 역할
  • 기타 자료형
    • 논리형 Boolean : 1bit로 true / false로 구분
    • 문자형 Char : 2바이트 유니코드 표현(\u0000 ~ \uffff)
  • String Pool
var str1 : String = "hello" var str2 = "hello" //str1 == str2는 true 반환 //문자열은 string pool에 저장되어 처리
  • $ 표현식
    • 문자열 내에 $기호 사용 시 변수 출력 가능
var a = 1 val s1 = "a is $a" // a is 1 val s2 = "a+1 is ${a+1}" //a+1 is 2

Null 타입

  • 코틀린 변수는 기본적으로 Null 허용 x
    • 선언한 변수는 반드시 값이 할당되어야 함
  • Nullable 선언 : ? 사용
val a : Int? = null val b : String? = null
  • null 변수를 연산시 오류 발생
    • null 연산 시도 시 컴파일 오류 발생
    • 메소드(.) 자리에 safe call(?. - null이면 연산 x)
    • assert call(!!.) : null이 아니라고 가정(컴파일러의 오류처리 무시) - null 접근시 NPE(NullPointException) 발생
    • 엘비스(elvis) 연산자 (?:) : 연산 오류 발생시 대입할 값 지정
val str1 : String? ... //str1의 대입 여부는 모른다고 가정 val len = str1?.length ?: -1 //val len = if(st1!=null) str1.length else -1

비교와 캐스팅

  • 자료형 변환 시 메소드 이용
val a : Int = 1 val b : Double = a.toDouble()
  • 변환 메소드의 종류
    • toByte
    • toLong
    • toShort
    • toFloat
    • toInt
    • toDouble
    • toChar
  • 이중 / 삼중 등호
    • 이중 등호(==) : 값 비교
    • 삼중 등호(===) : 참조 주소 비교 (nullable / not nullable 변수는 같은 값이어도 다른 주소로 할당)
  • 스마트 캐스트
    • 명시되지 않은 자료형을 자동변환
    • Number형 : 대입되는 숫자에 맞는 자료형으로 자동 캐스팅
    • Any형 : 자료형이 정해지지 않은 경우
      • 모든 자료형 클래스의 root 역할
      • 필요한 자료형으로 자동 변환
var test : Number = 12.2 //float test = 12 //int로 smartcast tset = 12L //long으로 smartcast test += 12.0 //다시 float로 smartcast

비트 연산자

  • 비트 메소드
    • shl(bits) : bits만큼 왼쪽으로 shift
    • shr(bits) : bits만큼 오른쪽으로 shift
    • ushr(bits) : bits만큼 오른쪽 shift(부호 변화 x)
    • and(bits) : bits와 and연산
    • or(bits) : bits와 or연산
    • xor(bits) : bits와 xor연산
    • inv() : bit 뒤집기
728x90
728x90
VSCode에 C언어 개발 환경 설정하기

VSCode에 C언어 개발 환경 설정하기

  • VSCode에 C/C++ 개발 환경 설정한다고 한참을 해멨는데, 결국 공식 가이드가 답이었다...
  • MINGW 말고, MINGW-W64를 설치하는게 답이었다. 하나씩 진행해보자!

VSCode 설치하기

  • 이 링크로 들어가서 설치한다. https://code.visualstudio.com/download
  • C/C++ Extension을 설치한다.
    • 위 검색창에 C를 누르면 이미지에 보이는 C/C++을 설치하면 된다.

MINGW 설치하기

  • 해당 링크로 들어가 MINGW를 설치한다 - https://sourceforge.net/projects/mingw-w64/files/Toolchains targetting Win32/Personal Builds/mingw-builds/installer/mingw-w64-install.exe/download
  • 설치 중간에 설정 부분에서 Architecturex86_64를 선택하고, 그 외에는 계속 진행한다.
  • 설치 후, 설치된 폴더를 환경 변수에 추가한다.
    • 파일 관리자에서 내 PC 우클릭 - 속성 - 고급 시스템 설정 - 환경 변수를 클릭한다.
    • 시스템 변수에서 Path를 찾아 편집을 누른다.
    • (mingw 설치 경로)\x86_64-8.1.0-posix-seh-rt_v6-rev0\mingw64\bin까지 복사한 후, 환경 변수에 추가해 준다.
  • cmd를 켜서 g++ --version, gcc --version의 결과가 다음과 같으면 성공이다.

빌드 환경 만들기

  • 일단 코드를 작성한다.
// hello.c #include <stdio.h> int main(void) { printf("hello, world!\n"); return 0; }
  • VScode에서 Terminal > Configure Default Build Task로 이동한다. 이때 C파일의 경우 gcc.exe를, Cpp는 g++.exe 를 선택한다.
{ "version": "2.0.0", "tasks": [ { "type": "shell", "label": "C/C++: g++.exe build active file", "command": "C:\\Program Files\\mingw-w64\\x86_64-8.1.0-posix-seh-rt_v6-rev0\\mingw64\\bin\\g++.exe", "args": ["-g", "${file}", "-o", "${fileDirname}\\${fileBasenameNoExtension}.exe"], "options": { "cwd": "${workspaceFolder}" }, "problemMatcher": ["$gcc"], "group": { "kind": "build", "isDefault": true } } ] }
  • 만약 mingw의 설치 폴더가 다르다면 위 command를 설치 폴더로 수정한다.
  • 이제 ctrl+shift+B를 누르면 C/Cpp 파일이 exe로 빌드된다.

디버깅 설정하기

  • 이번엔 디버깅이다. Run > Add Configuration...을 눌러 GDB를 선택한다.
  • 이후 F5를 누르면 디버깅이 가능하다.
728x90

+ Recent posts