CS

[모두의 컴퓨터과학] 배열

KSWKSW 2021. 11. 14. 21:30

컴파일링

  • stdio.h: 헤더파일, C언어로 작성되어 있으며 파일명이 .h로 끝나는 파일
  • 컴파일을 하면 벌어지는 일은?
  • preprocessing -> compiling - > assembling -> linking

preprocessing

  • # 기호로 시작하는 줄을 실제 파일의 코드로 대체한다.

compiling

  • 소스코드를 머신코드로 바꾸는 단계
  • 소스코드를 어셈블리 코드로 바꾼다.
  • 어셈블리 코드: CPU가 이해할 수 있는 코드

assembling

  • 어셈블리 코드를 받아 0과 1로 이루어진 머신코드로 바꾼다.
  • clang이 해주는 일

linking

  • 라이브러리와 코드의 0과 1을 모아 하나의 파일로 만들어준다.

디버깅

  • 버그: 의도하지 않은 프로그램 내 실수
  • 문법적으로 나타나는 오류
  • 논리적인 오류: printf 활용

IDE

  • 통합 개발 환경

  • 디버깅에 대한 추가기능을 제공한다.

  • ex) 코드 중간에서 멈추기, 한줄씩 실행하기

코드의 디자인

  • 코드 작성시에는 다른 사람이 읽기 쉽도록, 유지보수가 쉽도록 작성해야 한다.
  • 코드의 정확성과는 관련이 없다.
  • 스타일 가이드를 따라야 한다.
  • 소프트웨어로 평가할 영역이 아님

배열

  • char를 입력할 때는 작은 따옴표가 필요하다. (문자열은 쌍따옴표)

형변환

#include <stdio.h>

int main(void)
{
    char c1 = 'H';
    char c2 = 'I';
    char c3 = '!';
    printf("%i %i %i", (int) c1, (int) c2, (int) c3);
}
  • (int)를 이용해서 char를 int로 형변환한다.
  • 컴퓨터 메모리는 c1, c2, c3를 각각 숫자로 한 칸에 저장해놓는다.

평균 내기

#include <cs50.h>
#include <stdio.h>

int main(void)
{
    int score1 = 72;
    int score2 = 73;
    int score3 = 33;
    printf("Average : %i", (score1 + score2 + score3) / 3);
}
  • 변수 하나하나를 각각 선언하여 3으로 나누는 것은 과목이 추가될 때 수정하기 어렵다 -> 배열 사용

  • 배열: 같은 자료형의 값들이 같은 이름의 변수에 리스트로 저장된다.

  • 3개의 값이 담긴 배열을 만들고 싶다면 대괄호 안에 3을 넣어 int scores[3];과 같이 선언한다.

  • 그 후 scores[0] = 72; 와 같은 식으로 배열에 값을 넣어준다.

배열을 사용한 코드

#include <cs50.h>
#include <stdio.h>

int main(void)
{
    int scores[3];
    scores[0] = 72;
    scores[1] = 73;
    scores[2] = 33;
    printf("Average : %i", (scores[0] + scores[1] + scores[2]) / 3);
}
  • 여전히 코드를 복사 붙여넣기 하고 있고, 항상 3으로만 나눌 수 있다는 단점이 있다.
  • 프로그램 내부에서 변수가 바뀌지 않도록 선언하고 싶다면 코드 상단에 const int N = 3; 과 같은 식으로 선언할 수 있다. 변수명은 대문자로 적는다.(상수)
#include <cs50.h>
#include <stdio.h>

float average(int length, int array[]);

int main(void)
{
    int n = get_int("Number of scores: ");
    int scores[n];
    for (int i = 0; i <n; i++)
    {
        scores[i] = get_int("score %i: ", i + 1);
    }
    printf("Average : %.1f", average(n, scores));
}

float average(int length, int array[])
{
    int sum = 0;
    for (int i = 0; i < length; i++)
    {
        sum += array[i]
    }
    return (float) sum / (float) length;
}
  • C에선 정수를 정수로 나누면 정수가 나온다. 소수점 뒤 숫자들은 버려진다.
  • 형변환을 이용해 해결한다.
  • C는 자바나 파이썬과 달리 배열의 길이를 저장하지 않는다. 따로 선언해줘야 한다.

문자열과 배열

  • 문자열(string): char의 배열
  • 램에서 글자 수 만큼의 바이트를 차지한다.
  • 문자열이 끝나는 메모리를 널문자(\0)로 나타낸다. 글자별로 저장할 때보다 1바이트가 추가된다.
  • 문자열은 char의 배열이므로 대괄호를 두번 사용하면 글자별로 출력할 수 있다.
  • 컴퓨터는 문자열을 출력할 때 앞 인덱스부터 메모리를 검사하면서 널 문자가 아니면 출력하고 널 문자이면 출력을 멈추는 식으로 출력한다.

문자열의 활용

입력받은 문자를 한 글자씩 출력하기

  • 널 문자 사용
#include <stdio.h>
#include <cs50.h>

int main(void)
{
    string s = get_string("Input: ");
    printf("Output: ");
    for (i = 0; s[i] != '\0'; i++)
    {
        printf("%c", s[i]);
    }
    printf('\n');
}
  • 문자열의 길이 사용
#include <stdio.h>
#include <cs50.h>
#include <string.h> // strlen 함수가 있는 라이브러리

int main(void)
{
    string s = get_string("Input: ");
    printf("Output: ");
    for (i = 0, n = strlen(s); i < n; i++)
    {
        printf("%c", s[i]);
    }
    printf('\n');
}

소문자를 대문자로 만들기

#include <stdio.h>
#include <cs50.h>
#include <string.h>
#include <ctype.h> // toupper 함수가 있는 헤더파일

int main(void)
{
    string s = get_string("Before: ");
    printf("After: ");
    for (int i = 0, int n = strlen(s); i < n; i++)
    {
        printf("%c", toupper(s[i]));
    }
    printf("\n")
}

명령행 인자

  • clang은 기본적으로 a.out이라는 프로그램을 출력하지만 "-o" 명령행 인자를 이용하며 프로그램의 이름을 바꿀 수 있다.
  • int main(void)에 void 대신 int main(int argc, string argv[]) 라고 입력하면 명령 프롬프트에서 문자열을 바로 입력받을 수 있고 argc는 입력받은 인자의 갯수가 들어간다.
  • 왜 main함수는 int 반환값이 있을까? -> main은 0을 반환한다. 0은 문제 없다는 의미
  • 가끔 에러메시지에서 -42같이 숫자를 반환하는 것은 main함수가 특정 상황에 리턴하도록 설계된 숫자다.
  • argv[0]에는 처음 입력하는 프로그램 이름이 저장됨

출처: 부스트코스 모두의 컴퓨터과학