본문으로 건너뛰기

입출력과 전처리

표준 입출력 함수

scanf()를 이용한 표준 입력

scanf() 함수는 키보드로부터 데이터를 입력받기 위한 표준 입력 함수이다. 이 함수를 사용하기 위해서는 stdio.h 헤더 파일이 필요하다.

scanf()는 변환 명세(Conversion Specification)를 포함하는 제어 문자열과 입력받을 값을 저장할 변수의 주소를 인자로 받는다. 변수의 주소를 전달하기 위해 변수 이름 앞에 주소 연산자 &를 붙여야 한다.

int age;
scanf("%d", &age); // 키보드로 입력한 정수를 age 변수에 저장한다.

scanf()에서 사용하는 주요 변환 명세는 다음과 같다.

  • %d: 10진수 정수 (int)
  • %o, %x: 8진수, 16진수 정수 (int)
  • %u: 부호 없는 10진수 정수 (unsigned int)
  • %f: 단정밀도 실수 (float)
  • %lf: 배정밀도 실수 (double)
  • %c: 단일 문자 (char)
  • %s: 문자열 (string)

문자 입력 시 주의사항: scanf()로 여러 데이터를 연속으로 입력받을 때, 숫자 등을 입력한 후 누른 Enter키(\n)가 입력 버퍼에 남아 다음 문자 입력(%c)에 영향을 줄 수 있다. 이를 방지하려면 %c 앞에 공백을 추가하여 scanf(" %c", &variable); 형태로 사용해야 한다. 이 공백은 버퍼에 남아있는 공백 문자(스페이스, 탭, 개행 등)를 무시하는 역할을 한다.

printf()를 이용한 표준 출력

printf() 함수는 화면에 데이터를 출력하기 위한 표준 출력 함수이다. scanf()와 마찬가지로 제어 문자열과 출력할 값(표현식)들을 인자로 받는다.

출력 형식 지정

printf()의 변환 명세에 추가적인 정보를 결합하여 출력 형식을 제어할 수 있다.

  • 필드 폭(Field Width): 출력할 전체 자릿수를 지정한다.
    • %5d: 5칸을 확보하고 오른쪽 정렬로 정수를 출력한다.
    • %-5d: 5칸을 확보하고 왼쪽 정렬로 정수를 출력한다.
    • %+5d: 부호를 항상 표시하며 5칸에 오른쪽 정렬로 출력한다.
  • 정밀도(Precision): 실수를 출력할 때 소수점 이하 자릿수를 지정한다.
    • %5.2f: 전체 5칸 중 소수점 이하 2자리까지 출력한다.
    • %10.4e: 전체 10칸을 확보하고 지수 형태로 소수점 이하 4자리까지 출력한다.

출력 제어 문자 (Escape Sequence)

printf()의 제어 문자열 안에서는 특수한 기능을 하는 출력 제어 문자를 사용할 수 있다.

  • \n: 줄 바꿈 (Newline)
  • \t: 수평 탭 (Horizontal Tab)
  • \": 큰따옴표 출력
  • \\: 역슬래시() 출력
  • \a: 경고음 (Alert)

getchar()putchar()

getchar()putchar()는 한 번에 문자 하나만을 입출력하기 위한 함수이다. 사용법은 다음과 같다.

char c;
c = getchar(); // 문자 하나를 입력받아 c에 저장한다.
putchar(c); // c에 저장된 문자를 출력한다.

전처리기 (Preprocessor)

전처리기는 소스 코드가 컴파일러에 의해 번역되기 전에 특정 작업을 먼저 수행하는 프로그램이다. 전처리기 지시자는 # 문자로 시작한다.

#include 와 헤더 파일

**Header File(헤더 파일)**은 확장자가 .h인 텍스트 파일로, 주로 함수 원형, 매크로 정의, 자료형 재정의 등을 포함한다. #include 지시자는 이러한 헤더 파일을 소스 코드에 포함시키는 역할을 한다.

  • #include <stdio.h>: 시스템 헤더 파일을 포함할 때 사용한다.
  • #include "myheader.h": 사용자가 직접 작성한 헤더 파일을 포함할 때 사용하며, 현재 소스 파일이 있는 폴더부터 검색한다.

주요 시스템 헤더 파일은 다음과 같다.

  • stdio.h: 표준 입출력 함수 (printf, scanf 등)
  • math.h: 수학 관련 함수 (pow, sqrt 등)
  • string.h: 문자열 처리 함수 (strcpy, strlen 등)
  • stdlib.h: 메모리 할당, 유틸리티 함수 (malloc, exit 등)

#define 과 매크로

#define 지시자는 특정 식별자(기호 상수 또는 매크로)를 지정된 문자열로 치환하는 역할을 한다.

  • 기호 상수: 값에 이름을 부여하여 가독성과 유지보수성을 높인다.

    #define PI 3.141592
  • 인자가 있는 매크로: 함수처럼 동작하는 코드를 정의한다.

    #define SQUARE(x) ((x) * (x))

    매크로 정의 시, 인자와 전체 식을 괄호로 감싸는 것이 중요하다.

    괄호가 없으면 연산자 우선순위에 의해 예기치 않은 결과가 발생할 수 있다.

typedef 를 이용한 자료형 재정의

typedef 키워드는 이미 존재하는 자료형에 새로운 이름을 부여하는 기능이다. 이는 코드의 가독성을 높이고, 다른 시스템으로 코드를 이식할 때 자료형의 크기 차이로 인한 문제를 쉽게 해결할 수 있게 도와준다.

typedef int myint; // int 자료형을 myint라는 이름으로도 사용할 수 있다. 
myint salary; // int salary; 와 동일하다.

기본 연산자

연산자의 기본 개념

  • Operator(연산자): 덧셈(+), 곱셈(*)과 같이 특정 연산을 수행하도록 정의된 기호나 키워드이다.
  • Operand(피연산자): 연산의 대상이 되는 변수나 값이다.

연산자는 피연산자의 수에 따라 단항, 이항, 삼항 연산자로 분류된다.

주요 연산자

대입 연산자 (Assignment Operator)

Assignment Operator(대입 연산자) =는 오른쪽 피연산자의 값을 왼쪽 피연산자(변수)에 저장하는 역할을 한다. 연산자들 중 우선순위가 매우 낮아 대부분의 다른 연산이 끝난 후 마지막에 수행된다.

관계 연산자 (Relational Operators)

**Relational Operator(관계 연산자)**는 두 피연산자의 값을 비교하는 데 사용된다. 연산 결과는 참(true)이면 1, 거짓(false)이면 0의 정수 값을 가진다.

  • >,<, >=, <=, ==(같다), !=(같지 않다)

증감 연산자 (Increment/Decrement Operators)

Increment/Decrement Operator(증감 연산자) ++--는 피연산자의 값을 1 증가시키거나 감소시킨다. 연산자의 위치에 따라 평가 결과가 달라진다.

  • 전위(Prefix): ++a, --a. 변수의 값을 먼저 증감시킨 후, 그 결과를 수식의 값으로 사용한다.
  • 후위(Postfix): a++, a--. 변수의 현재 값을 먼저 수식의 값으로 사용한 후, 변수의 값을 증감시킨다.

논리 연산자 (Logical Operators)

**Logical Operator(논리 연산자)**는 논리적인 관계를 평가하는 데 사용된다. C언어에서는 0을 거짓으로, 0이 아닌 모든 값을 참으로 간주한다.

  • && (AND): 두 피연산자가 모두 참일 때만 1(참)을 반환한다.
  • || (OR): 두 피연산자 중 하나라도 참이면 1(참)을 반환한다.
  • ! (NOT): 피연산자가 참이면 0(거짓)을, 거짓이면 1(참)을 반환한다.

단축 평가 (Short-circuit Evaluation)

논리 연산자 &&||는 **Short-circuit Evaluation(단축 평가)**를 수행한다.

  • && 연산에서 첫 번째 피연산자가 거짓(0)이면, 전체 결과는 무조건 거짓이므로 두 번째 피연산자를 평가하지 않는다.
  • || 연산에서 첫 번째 피연산자가 참(1)이면, 전체 결과는 무조건 참이므로 두 번째 피연산자를 평가하지 않는다.

이러한 특성은 b++와 같은 증감 연산자가 논리 연산식 내에 있을 때 예기치 않은 동작의 원인이 될 수 있으므로 주의해야 한다.