C언어 기초교육(4/10)

2024. 5. 17. 11:12코딩과 프로그래밍/C언어

728x90

[복습]

자, 이번엔 1장부터 3장까지 배웠던 내용을 복습하려고 한다. 내가 항상 복습을 강조하는 이유는 사람의 뇌는 여러 번 익혀야 기억이 오래가기 때문이다.

 

1. C언어는 시스템 프로그래밍 및 다양한 응용 프로그램을 개발하는 데 사용되는 범용 프로그래밍 언어이다.

 

2. 1970년대에 데니스 리치가 벨 연구소에서 개발하였다.

 

3. main 함수는 C프로그램의 시작점이자 진입점이다.

 

4. main 함수는 대부분의 프로그래밍 언어에선 두 개 이상 사용 할 수 없다.

 

5. 변수란 데이터를 저장하는 공간을 의미하며 변수는 특정 값을 메모리에 저장하고 필요할 때 이 값을 불러와 사용 할 수 있도록 한다.

 

6. 데이터에는 다양한 타입이 있는데. 대표적으로 정수형(int), 실수형(float), 문자형(char) 등이 있다.

 

7. 초기화란 변수를 선언할 때 처음으로 값을 할당하는 것을 의미한다.

ex)

int a = 10; 정수형 번수 a를 선언하고 변수 a에 10이라는 값을 초기화(할당)하였다.

 

8. printf는 출력 함수로 형식 지정자 등을 사용하여 값을 출력한다.

ex)

printf("정수: %d\n", a);

printf("실수: %f\n", b);

printf("문자: %c\n", c);

 

 

[출력과 입력받기]

우리가 프로그래밍에서 출력을 하기 위해선 printf문을 사용한다고 하였는데. 그렇다면 반대로 값을 입력받기 위해선 어떤 문을 사용해야할까? 반대로 scanf 함수이다.

 

scanf 함수는 C 언어에서 표준 입력으로부터 데이터를 읽어오는 데 사용된다. 이때 표준 입력이란 키보드 등을 얘기한다. scanf 함수는 입력 형식을 지정하고 그에 따라 변수를 채우는 역할을 한다. 이제 scanf 함수 사용법에 대한 예시를 보여주겠다.

ex)

scanf("형식 문자열(형식 지정자)", 변수의 주소);

 

여기서 추가로 설명을 하자면 형식 문자열과 형식 지정자의 차이점에 대해서 잠깐 알려주겠다. 둘은 비슷하지만, 약간의 차이가 있는데. 형식 문자열이란 scanf 함수에서 사용되는 문자열로 이 문자열은 사용자로부터 입력을 받을 때 어떤 형식의 데이터를 받을지를 지정한다. 예를 들어, %d, %f, %c, %s 등이 형식 문자열의 일부이다.

 

여기서 %d, %f, %c, %s 등은 지난 3장에서 형식 지정자라고 알려줬는데. 형식 지정자란 형식 문자열에 포함되는 특별한 문자열이다. 형식 지정자는 % 기호로 시작하며 어떤 형식의 데이터를 출력할지 또는 입력받을지를 지정한다.

 

예를들면 %d는 정수형 형식 지정자, %c는 문자형 형식 지정자이다. 이는 지난 번에 이미 배운 내용이기 때문에 복습 차원에서 한 번 더 알린다.

 

자, 그렇다면 이번엔 정수를 입력 받아보도록 하자. 비쥬얼 스튜디오를 실행하고 다음과 같이 작성해보자.

 

#include <stdio.h>

int main() {
    * num;

    printf("정수를 입력하세요: ");
    scanf_s("%d", &num);

    printf("입력된 정수: %d\n", num);
    printf("변수 num의 값: %d\n", num);

    return 0;
}

위에 num; 앞에 있는 *는 여러분들이 맞춰보자. 정수값을 입력 받기 위해선 *의 위치에 '이것'이 있어야 한다.

여기서 '이것'이란 무엇일까? 참고로 띄어쓰기 잊지 말자. * num; 처럼 '이것'과 num 사이는 붙어 있어야 하는 게 아니라 한 칸 띄어져 있어야 한다.

HTML button tag

 

자, 완벽하게 작성했다면 컨트롤과 F5를 눌러보도록 하자.  

위와 같이 나오는 걸 확인 할 수 있다. 우리는 num에 할당해줄 값을 입력하였고. 필자는 그 값을 50이라 입력하였다. 그래서 현재 변수 num의 값은 50으로 변경된 걸 확인 할 수 있다. 참고로 필자랑은 출력되는 글자가 조금 다를 수 있는데. 그건 필자가 따로 설정해서 그런 것이니 당황하지 말자.

 

그리고 우리가 작성한 코드를 다시 한 번 훑어보자. scanf 부분에 _s를 붙였는데. scanf 함수를 사용하면 입력 크기에 제한이 없어 지정된 크기보다 더 많은 양을 입력받는 버퍼 오버플로(buffer overflow)라는 메모리 문제가 발생한다. 그래서 비쥬얼 스튜디오에선 이 같은 문제점을 보완해 새로 만든 명령어가 있는데, 그게 바로 scanf_s 이다. scanf_s는 함수가 입력값의 크기를 지정한다는 것 외엔 다른 점도 없고 사용법도 똑같으니 우리는 주로 scanf_s를 사용 할 것이다.

 

 

[문자형 변수와 문자열]

이번에는 문자형 변수를 출력해보자.

아래와 같은 코드를 작성해보자.

 

int main() {
    char hong = 'kill';
    printf("%c\n", hong);
    return 0;
}

 

다시 한 번 얘기하지만, 문자형 변수를 만들기 위해선 char를 사용해야하고. 문자형 변수를 출력할 땐 정수형 형식 지정자(%d)와 달리 문자형 형식 지정자(%c)를 사용해야한다. 모두 입력 했다면 컨트롤 + F5를 입력해보자.

hong이라는 문자형 변수를 출력하는데 문제가 생겼다. 우린 분명 hong에 kill이라는 문자열 값을 초기화 했는데. 출력되는 것은 l 뿐이다.

 

일단 문자형 변수 hong은 단일 문자를 저장할 수 있는 변수지만, 'kill'처럼 여러 개의 문자들로 이루어진 문자열을 저장 할 순 없다. 만약 다음과 같이 작성했다면 정상적으로 출력되었을 것이다. char hong = "k"; 이런 식으로 말이다. 그렇다면 여러 문자열을 출력하기 위해선 어떻게 해야할까? 문자형이 아닌 문자열을 저장 할 수 있는 형식으로 변수를 선언하면 된다. 또 문자열 리터럴을 사용해야한다. 코드를 아래와 같이 작성해보자.

 

int main() {
    char hong[] = "kill";
    printf("%s\n", hong);
    return 0;
}

위와 같이 작성하였다면 한 번 실행해보자. 정상적으로 kill이 입력되는 것을 확인 할 수 있다.

이해를 돕기 위해 먼저 작성했던 코드와 새로 작성했던 코드를 비교 해보도록 하자.

 

(전)

int main() {
    char hong = 'kill';
    printf("%c\n", hong);
    return 0;
}

 

(후)

int main() {
    char hong[] = "kill";
    printf("%s\n", hong);
    return 0;
}

먼저 printf문을 보면 %c가 아닌 %s를 사용하였는데. %c는 단일 문자만을 출력할 때 사용하며 반대로 문자열을 출력하기 위해선 %s를 사용해야한다.

 

%c = 단일 문자(character)

%s = 문자열(string)

 

그리고 위에 변수 선언 부분에 잘 보면 hong 오른쪽에 []를 붙였다. 이는 문자열을 저장하기 위한 문자 배열을 선언하고 초기화한 것을 의미한다. 간단하게 char hong[] = "kill"; 라는 코드를 설명하자면 char hong[] 은 hong이라는 이름의 문자 배열을 선언한 것이고. 이 배열은 "kill"이라는 문자열을 저장하는데 사용 될 것이다. 이때 배열의 크기는 따로 명시하지 않았으므로 문자열의 길이에 맞게 자동으로 결정된다.

 

"kill"은 큰따옴표(")로 둘러싸인 문자열 리터럴인데, 문자열 리터럴이란 큰 따옴표(" ")로 감싸져 있는 문자들을 말한다, 따라서 "kill"이라는 문자열 리터럴은 hong이라는 이름의 char 배열에 저장되며 각 문자는 배열의 개별 요소에 저장된다. 여기서 시퀀스 라는 표현이 사용되는데, 시퀀스는 여러 개의 데이터가 일정한 순서로 나열되어 있는 것을 의미한다.

 

문자열 시퀀스 외에도 정수 배열 시퀀스도 있다.

 

int numbers[] = {10, 20, 30, 40};

위의 코드는 numbers라는 이름의 정수형 배열에 10, 20, 30, 40이 순서대로 나열된 정수형 시퀀스이다. 이를 정수 배열 시퀀스 혹은 배열 시퀀스라고 부른다.

 

다시 본론으로 돌아가 "kill"이라는 문자열 리터럴은 'k', 'i', 'l', 'l'이라는 문자들이 정해진 순서대로 배열되어 있는 시퀀스이다.

 

hong[0] = 'k' 

hong[1] = 'i' 

hong[2] = 'l' 

hong[3] = 'l' 

hong[4] = '\0' // 문자열의 끝을 나타내는 널 문자

따라서 배열의 크기는 널 문자를 포함하여 5가 된다. 이것은 문자열의 길이가 4인 문자열에 널 종료 문자(\0)가 추가된 결과이다. 이 널 문자라는 것은 문자열 리터럴의 끝에 자동으로 널 문자가 추가된다. 

 

배열의 크기를 알고 싶다면 아래 printf문을 아래와 같이 수정해주면 된다.

 

int main() {
    char hong[] = "kill";
    printf("%d\n", sizeof(hong));
    return 0;
}

우리는 printf문에 hong에 초기화된 kill이라는 문자열을 띄우려는 것이 아닌 hong에 배치된 배열의 크기를 알고 싶은 것이기 때문에 먼저 문자열 형식지정자인 %s를 지운뒤 정수형 값을 출력하기 위해 정수형 형식지정자인 %d로 수정하였고 그 뒤에 hong이라고 적혀 있는 데이터 부분을 sizeof(hong)이라고 수정해주었다. 한 번 컨트롤 + F5를 입력해 실행해보자.

앞서 말했듯이 널 문자를 포함한 5라는 숫자가 출력된다.

 

만약 배열의 크기를 지정해주고 싶다면 char hong[] = "kill"; 이라는 부분에서 []부분 안에 숫자를 넣어주면 된다. 한 번 []부분 안에 원하는 임의의 숫자를 넣어보고 컨트롤 + F5로 실행해보자. 필자는 10이라는 숫자를 넣고 실행하니 아래와 같이 실행된다.

참고로 배열의 크기를 조회할 때 널 문자가 포함되지 않는 이유는 배열의 크기와 문자열의 길이는 다르기 때문이다. 아까는 배열의 크기를 지정해주지 않았기 때문에 널 문자가 포함된 "KILL"이라는 문자열을 따라가 배열의 크기 출력시 '5'라는 숫자가 출력되었지만, 지금은 배열의 크기를 따로 지정해줬기 때문에 문자열을 따라가지 않아 '10'이란 숫자만 출력된 것이다.

 

[이번 장의 주요 복습]

1. printf는 출력함수

2. scanf는 표준 입력 함수

3. scanf 함수는 오버 플로우 문제가 있으니 scanf_s를 사용

4. 배열의 크기를 명시하지 않을 시 문자열의 길이에 맞게 자동으로 결정된다.

5. 형식지정자 %c는 단일 문자, 형식지정자 %s는 문자열

6. 배열의 크기를 지정해주지 않으면 널 문자가 포함된 문자열의 길이를 따라간다. 

7. 배열의 크기와 문자열의 길이는 다른 것이다.

 

728x90

'코딩과 프로그래밍 > C언어' 카테고리의 다른 글

C언어 기초 퀴즈  (0) 2024.05.24
C언어 기초교육(5/10)  (0) 2024.05.18
C언어 기초교육(3/10)  (0) 2024.05.16
C언어 기초교육(2/10)  (0) 2024.05.16
C언어 기초교육(1/10)  (0) 2024.05.15