랑아
article thumbnail

01. 알고리즘과 코딩

01. 알고리즘(Algorithm)

1) 알고리즘의 정의

  • 주어진 문제를 해결하기 위하여 잘 정의된 동작의 유한 집합
  • 프로그램은 알고리즘과 데이터 구조가 결합된 것
  • 알고리즘은 수학, 컴퓨터 과학, 언어학 등의 관련 분야에서 어떠한 문제를 해결하기 위해 정해진 일련의 절차나 방법을 공식화한 형태로 표현한 것
  • 알고리즘은 넓은 의미에서 자료 구조와 함께 프로그램을 구성하는 요소를 의미함
  • 좁은 의미에서 어떤 문제에 대한 답을 찾는 해법을 의미함
  • 프로그래밍 언어가 아니더라도 알고리즘의 표현은 가능함

2) 알고리즘이 갖추어야 할 조건(알고리즘의 5가지 특성)

  • 입력(Input) : 외부에서 입력되는 자료가 0개 이상 존재함
  • 출력(Output) : 출력이 적어도 1개 이상의 결과가 있어야 함
  • 명확성(Definiteness) : 명령어들은 명확하고 모호하지 않아야 함
  • 유한성(Finiteness) : 알고리즘의 명령어들은 유한 번의 수행 후 종료되어야 함
  • 유효성(Effectiveness, 효과성, 실제성) : 모든 명령들은 명백하고 실행 가능한 연산들이어야 함

3) 알고리즘을 분석하는 판단 기준

  • 정확성(Correctness) : 알고리즘이 정확한지를 검사하여, 입력에 대해서 정확한 출력이 되는지를 나타내는 기준
  • 간결성(Simplicity) : 표현이 간단하고, 일기 쉽고, 이해가 용이한가를 나타내는 기준
  • 작업량(Amount of Work Done) : 알고리즘을 수행할 때 명령어의 실행 횟수로 평균과 최악의 경우는 나타내는 기준
  • 최적성(Optimality) : 알고리즘 수행 시간의 평균과 최악이 같을 때 최적이라고 하며 두 가지 경우의 시간 차이를 계산하여 분석함

4) 순서도

  • 알고리즘을 누구나 알아볼 수 있는 형식으로 표현해야 하는데 영문이나 한글로는 표현이 어렵고, 많기 때문에 약속된 기호인 순서도 기로를 사용하는 것
  • 순서도로 그려진 알고리즘은 프로그래머는 쉽게 알아볼 수 있기 때문에 문법이 다른 프로그래밍 언어를 사용하더라도 프로그램으로 변환이 쉬움

5) 코딩(Coding)

  • 알고리즘을 선정한 프로그래밍 언어로 변환하여 작성하는 것
  • 정확하고 간결한 좋은 프로그램을 작성하는 것은 프로그래밍 언어의 선택과 관계가 없음

6) 알고리즘 설계 기법

  1. 동적 계획법(Dynamic Programming)
    • 해결하고자 하는 문제의 최적해(Optimal Solution)가 부분 문제들의 최적해들로 구성되어 있을 경우 이를 이용하여 문제의 최적해를 구하는 기법
    • 부분적으로 해결된 문제들을 이용하여 최적해를 구함
    • Bottom-up 방식
  2. 탐욕적 알고리즘(Greedy Algorithm)
    • 최적해를 구하는 데에 사용되는 근사적인 알고리즘으로, 문제의 해법을 욕심 형태로 선택하면서 최적의 해법에 도달하기를 바라는 방법
    • 가장 좋아 보이는 해법을 선택하는 알고리즘으로 결국 최적 해법을 구할 수는 없을지라도 근사적인 해답을 얻을 수 있음
    • 대표적으로 배낭 채우기 알고리즘
  3. 재귀적 알고리즘(Recursion Algorithm)
    • 같은 알고리즘을 반복하여 수행하는 알고리즘
  4. 근사 알고리즘(Approximation Algorithm)
    • 회적화되는 답을 구할 수는 없어도 비교적 빠른 시간에 계산이 가능하도록 근사 해법을 수행하는 알고리즘
  5. 배낭 알고리즘(Knapsack Algorithm)
    • 어떤 도둑의 배낭에 훔친 물건을 채우는 방법을 찾는 알고리즘
  6. 분할 정복법(Divide and Conquer)
    • 전체 문제를 부분적으로 나누어 해결하고, 부분적으로 해결된 문제들을 결합하면 전체 문제를 해결할 수 있음
    • 대표적으로 병합 정렬 알고리즘
    • Top-Down 방식
  7. 퇴각 검색법(Backtracking)
    • 최적해를 구하기 위한 모든 가능성을 찾아가는 방법
    • 대표적으로 깊이 우선 탐색 알고리즘



02. 코드의 품질 향상

1) 리팩토링(Refactoring)

  • 코드의 외부 행위는 바꾸지 않고, 내부 구조를 개선하여 소프트웨어를 변경하는 프로세스로 버그 발생을 최소화하는 코드 정화(Clean Up) 방법
  • 리팩토링은 이미 존재하는 코드의 설계를 안전하게 향상하는 기술이라고 할 수 있음
  • 단순히 코딩 스타일만을 개선하는 것이 아니라 성능과 코드의 구조, 즉 좋은 설계가 되도록 개선하는 과정을 의미함
  • 리팩토링은 소프트웨어의 디자인을 개선함
  • 리팩토링은 소프트웨어를 이해하기 쉽게 만들어 줌
  • 버그를 빨리 찾을 수 있도록 도움을 줌
  • 리팩토링은 프로그램을 빨리 작성할 수 있도록 도와줌

2) 코드 품질 향상 기법

  1. 테스트(Test) : 코드의 품질을 높이는 방법 중 가장 일반적인 기법
  2. 코드 인스펙션(Code Inspection) : 코드에 존재하는 결함을 발견하기 위해 눈으로 확인하는 검사
  3. 정적 분석(Static Analysis) : 프로그램을 실행시키지 않고 분석하는 도구로, 사전에 결함을 발견하는 예방 기법으로 데드 코드(Dead Code)가 없는지, 선언이 되지 않고 사용한 변수가 없는지 등을 검사함
  4. 동적 분석(Dynamic Analysis) : 프로그램을 실행시키고 분석하는 도구로, 실행 과정에서 비효율적인 코드를 분석하는 도구
  5. 증명(Proof) : 가장 이상적인 방법으로 소프트웨어 품질이 아주 중요한 경우에 주로 활용됨

3) 코드 품질 분석 도구

1. 코드 품질 분석 도구의 개념

  • 코딩 스타일, 설정된 코딩 표준, 코드의 복잡도, 코드 내에 존재하는 메모리 누수 현상, 스레드의 결함 등을 발견하기 위해 사용하는 프로그램
  • 코드 품질 분석 도구는 정적 분석과 동적 분석 도구가 있음

2) 정적 분석 도구

  • pmd
    • Java 및 타 언어 소스 코드에 대한 버그, 데드 코드를 분석함
    • Eclipse에 내장되어 사용함
  • cppcheck
    • C/C++ 코드에 대한 메모리 누수, 오버플로우를 분석함
    • 배열 범위, 클래스, 메모리 누수, NULL 포인트 등을 체크함
  • SonarQube
    • 소스 코드의 품질을 체크하는 통합 플랫폼
  • checkstyle
    • Java 코드가 표준을 준수하였는지를 검사함

2. 동적 분석 도구

  • Avalanche
    • valgrind 프레임워크 및 STP 기반 소프트웨어로 오류 및 취약점을 동적으로 분석함
  • valgrind
    • 자동화된 메모리 및 스레드 결함을 검색하고 분석하는 도구
    • 메모리 오류를 검출함
    • Cache, Heap, 다중 스레드의 프로파일링을 지원함

4) 코드 최적화 기법

1. 코드 최적화 기법의 개념

  • 코드 최적화 기법, 아키텍처 조정 및 호출 순서 조정 등을 적용하여 성능을 개선할 수 있음
  • 프로그래밍 언어의 특성에 대한 이해를 기반으로 소스 코드 품질 분석 도구를 활용하여 성능을 개선할 수 있음
  • 코드 최적화 기법은 나쁜 코드를 찾아 읽기 쉽고 변경 및 추가가 쉬운 클린 코드를 작성하는 것
  • 소스 코드는 지속적으로 변경이 되기 때문에 실행 시간이나 자원 사용량 측면에서 비효율적일 수 있기 때문에, 소스 코드는 지속적으로 최적화 해야 함

2. 나쁜 코드(Bad Code)

  • 로직(Logic)을 이해하기 어렵게 작성된 코드
  • 로직의 제어가 정제되지 않고 서로 얽혀 있는 스파게티 코드
  • 변수나 메소드에 대한 이름 정의를 알 수 없는 코드
  • 동일한 처리 로직이 종복되게 작성된 코드
  • 소스 코드가 이해가 안 되면 유지보수 비용이 높아질 수밖에 없음
  • 스파게티 코드의 경우 잦은 오류가 발생할 가능성이 있음
  • 코드의 이해가 어려워 덧붙이기가 계속되고 코드 복잡도가 증가함

3. 클린 코드(Clean Code)

  • 판독성이 높고, 단순하며, 의존성을 줄이고, 중복을 최소화하여 깔끔하게 잘 정리된 코드
  • 클린 코드가 높을수록 가독성이 좋아져서 유지보수 비용이 낮아지고, 수정 속도가 빨라짐
  • 판독성이 높으므로 기능을 쉽게 이해할 수 있음
  • 오류를 찾기 용이함
  • 프로그래밍 속도가 빨라짐

5) 클린 코드의 작성 원칙

  1. 가독성
    • 이해하기 쉬운 명령어를 사용함
    • 코드 작성 시 들여쓰기 기능을 사용함
  2. 단순성
    • 한 번에 한 가지만 처리가 되도록 코딩함
    • 클래스, 메소드, 함수 등을 최소 단위로 분리함
  3. 의존성
    • 영향도, 결합도를 최소화함
    • 코드의 변경이 다른 부분에 영향이 없게 작성함
  4. 중복성
    • 중복된 코드를 제거함
    • 공통된 코드를 사용함
  5. 추상화
    • 클래스, 메소드, 함수에 동일한 수준의 추상화를 함
    • 상세 내용은 하위 클래스에서 함

6) 표준화된 코딩 형식

  • 하나의 명령을 하나의 라인을 코딩함
  • 명령어를 구분할 수 있는 줄 바꿈을 적절히 사용함
  • 호출하는 함수는 먼저 배치하고, 호출되는 함수는 나중에 배치함
  • 변수 선언 시 지역 변수는 함수 시작 부분에서 선언함
  • 함수 간의 매개 변수는 변수명만 보아도 쉽게 파악할 수 있도록 부여함
  • 변수명은 기억하기 쉬운 명칭, 발음하기 쉬운 용어, 접두어 등을 사용함
  • 주석문을 사용하여 다른 개발자가 소스 코드를 쉽게 이해하도록 함
  • 공백을 이용하여 실행문 그룹과 주석을 명확히 구분함
  • 복잡한 논리식과 산술식은 괄호와 들여쓰기를 통해 명확히 표현함
  • 빈 줄을 사용하여 선언부와 구현부를 구별함



03. C언어의 기초

1) C언어의 특징

  1. 고급 언어이면서 저급 언어
    • 쉽게 배울 수 있는 언어(고급 언어)이면서 하드웨어는 제어할 수 있는 시스템 프로그래밍 언어(저급 언어)
  2. 구고적을 프로그램을 작성할 수 있음
    • 프로그램을 기능별로 분리하여 부품처럼 만들어 조립하듯이 프로그래밍할 수 있음
  3. 이식성이 뛰어남
    • C언어로 작성된 프로그램은 컴퓨터의 기종이나 운영체제가 다르더라도 전혀 문제 없이 실행됨
  4. 효율적
    • C언어는 메모리를 직접 관리하면서 실행에 필요한 많은 자원을 낭비 없이 운영할 수 있음
  5. 다양한 연산자를 가지고 있음
    • 기본 연산자 외에도 비트 관련 연산자는 물론 다양한 연산 기능을 가지고 있어 프로그램 개발에 제한이 없음
    • 다양한 연산자로 인해 개발자는 물론 소스 분석자도 이해하기 어려울 수 있음

2) C언어의 작성 규칙

  1. 반드시 main() 함수로 시작함
  2. 영문자는 대소문자를 구분함
  3. 모든 함수는 블록 구조로 만들어야 함
  4. 모든 명령문은 세미콜론으로 종료를 알려야 함
  5. 프로그램 내에 설명이 필요하면 주석을 사용함
  6. 1열에 #include를 사용하여 <stdio.h> 파일을 포함해야 표준 입출력 함수를 사용할 수 있음

3) C언어 변수명 작성 규칙

1. C언어 변수명의 개념

  • C언어에서 제공하는 예약어가 아닌 프로그래머가 임의로 선언해야 하는 문자열의 작성 규칙
  • 변수명이나 함수명이 프로그래머가 임의로 작성해야 하는 문자열

2. 변수명이나 함수명의 작성 규칙

  • 영문자, 숫자, 밑줄 문자를 사용함
  • 첫 글자는 반드시 영문자로 시작해야 하며, 밑줄 문자는 영문자로 취급되기 때문에 첫 글자로 사용할 수 있음
  • 영문자는 대소문자를 다른 문자로 취급함
  • 공백을 포함하거나 다른 특수 문자를 포함해서는 안 됨
  • 예약어를 변수명으로 사용할 수 없음

4) C언어 변수 선언의 예약어

  • 문자형
    • char(대형 기종 : 1byte / 소형 기종 : 1byte)
  • 정수형
    • short(대형 기종 : 2byte / 소형 기종 : 2byte)
    • int(대형 기종 : 4byte / 소형 기종 : 2byte)
    • long(대형 기종 : 4byte / 소형 기종 : 4byte)
    • unsigned(대형 기종 : 4byte / 소형 기종 : 4byte)
  • 실수형
    • float(대형 기종 : 4byte / 소형 기종 : 4byte)
    • double(대형 기종 : 8byte / 소형 기종 : 8byte)

5) C언어 상수

  1. 정수형 상수
    • 10진 상수
      • 일반적으로 사용하는 방식으로 사용
      • 예시 : 10, 235, 56, -456
    • 8진 상수
      • 0으로 시작
      • 예시 : 043, 023
    • 16진 상수
      • 0x로 시작
      • 예시 : 0x43, 0x5E0, 0xFFFF
  2. 실수형 상수
    • 소수점형
      • 일반적으로 사용하는 방식으로 사용
      • 예시 : 1.4, -4.56, -0.001
    • 지수형
      • 문자 e나 E를 중간에 포함하여 사용
      • 예시 : 1e4, 2E-3, 1.2e4

6) 이스케이스 시퀀스(Escape Sequence)

  종류     설명  
  \n     줄 바꿈, 개방 문자로 Enter 키와 같은 역할  
  \t     일정한 크기의 열을 띄우는 것으로 Tab 키와 같은 역할  
  \b     한 칸 앞으로 이동하는 것  
  \f     프린터에서 다음 페이지를 출력할 수 있도록 이동함  
  \r     현재 행의 처음으로 이동함, home 키와 같은 역할  
  \0     NULL 문자, 1바이트 안에 모두 0이 채워짐  
  \\     \ 자체, printf("\\"); 은 \가 출력됨  
  \'     ' 자체, 단일 인용 부호(') 자체를 의미함  
  \"     " 자체, 이중 인용 부호(") 자체를 의미함  

7) 변환 문자

  종류     설명  
  %d     10진 정수로 변환하여 출력함  
  %o     8진 정수로 변환하여 출력함  
  %x     16진 정수로 변환하여 출력함  
  %u     부호 없는 정수로 변환하여 출력함  
  %f     소수점이 있는 실수로 변환하여 출력함  
  %e     지수 형태의 실수로 변환하여 출력함  
  %g     %f, %e 중에 출력 길이가 짧은 쪽을 선택하여 출력함  
  %c     한 문자로 변환해서 출력함  
  %s     문자열을 출력하며, 시작 번지로부터 "\0" 이전까지 출력함  
  • 변환 문자의 옵션
      • : 좌측에 맞춰 출력함
      • : 숫자 앞에 부호를 붙임
    • 0 : 숫자 앞 공백은 모두 0으로 채움



05. C언어의 표준 입출력 함수

1) 한 문자를 입력하거나 출력하는 함수

  • getchar() : 한 문자를 키보드에서 입력 받는 함수로 () 안에 인수를 사용하지 않음
  • putchar(char) : 한 문자를 모니터로 출력하는 함수

2) 문자열을 입력하거나 출력하는 함수

  • gets(string) : 문자열을 키보드로부터 입력 받는 함수
  • puts(string) : 문자열을 모니터로 출력하는 함수

3) 포맷을 갖춘 문자열을 입력하거나 출력하는 함수

  • scanf(format) : 포맷 문자열을 키보드로부터 입력 받는 함수
  • printf(format) : 포맷 문자열을 모니터로 출력하는 함수



06. C언어의 문자열 함수

  • strcpy() : 문자열을 복사함
  • strncpy() : 문자열에서 지정한 부분만큼 복사함
  • strcat() : 두 개의 문자열을 합침
  • strncat() : 두 개의 문자열을 지정한 부분만큼 합침
  • strlen() : 문자열의 길이를 구함
profile

랑아

@RangA

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!