프로그래밍기초 중간고사 총정리
1. 코딩과 컴파일
코딩은 단순히 코드를 치는 게 아니라 문법 + 로직으로 컴퓨터가 처리할 명령을 작성하는 것이다. 강의에서는 코딩을 “편집”으로 설명했고, 결국 문법과 로직을 이용해 변수를 다루는 과정이라고 정리했다. (leeseunghyun.me)
컴퓨터는 C언어 코드를 바로 이해하지 못하므로 컴파일이 필요하다.
| 개념 | 의미 |
|---|---|
| Syntax | 문법 |
| Logic | 처리 흐름, 순서 |
| Editor | 코드 작성 도구 |
| IDE | 통합 개발 환경 |
| Compile | 사람이 작성한 코드를 기계어로 번역 |
| Binary Code | 0과 1로 된 코드 |
| Debugging | 오류를 찾아 수정하는 과정 |
오류는 크게 문법 오류와 런타임 오류로 나뉜다. 문법 오류는 컴파일 단계에서 잡히고, 런타임 오류는 실행 중 발생한다. (leeseunghyun.me)
2. 컴퓨터 구조
CPU는 명령을 처리하는 장치이고, 내부에는 대표적으로 ALU, Controller, Register가 있다. ALU는 연산, Controller는 제어, Register는 CPU 내부의 초고속 저장소다. (leeseunghyun.me)
메모리 속도 순서:
Register > Cache > RAM > HDD/SSD
| 장치 | 역할 |
|---|---|
| Register | CPU 내부 초고속 저장소 |
| Cache | CPU와 RAM 사이의 중간 가속 역할 |
| RAM | 프로그램 실행 중 작업 공간 |
| HDD/SSD | 데이터를 영구 저장 |
중요한 말: 변수는 메모리에 저장되는 값의 공간이다.
3. 변수와 자료형
변수는 값을 저장하는 공간이고, C언어에서는 자료형에 따라 메모리 크기와 저장 범위가 달라진다. 강의에서는 정수형, 실수형, 기타 자료형으로 구분했다. (leeseunghyun.me)
정수형
| 자료형 | 크기 | 특징 |
|---|---|---|
| char | 1 byte | 문자 또는 작은 정수 |
| short | 2 byte | 작은 정수 |
| int | 4 byte | 기본 정수형 |
| long | 4 또는 8 byte | 운영체제에 따라 다름 |
| long long | 8 byte | 큰 정수 |
실수형
| 자료형 | 크기 |
|---|---|
| float | 4 byte |
| double | 8 byte |
| long double | 보통 8 byte 이상 |
기타 자료형
| 자료형 | 의미 |
|---|---|
| void | 값 없음 |
| bool / _Bool | 참/거짓 |
| enum | 열거형 |
bool을 쓰려면 보통 다음 헤더가 필요함.
#include <stdbool.h>
4. 식별자 규칙
식별자는 변수명, 함수명처럼 프로그래머가 붙이는 이름이다.
식별자 규칙:
1. 예약어 사용 불가
2. 숫자로 시작 불가
3. 대소문자 구분
4. 의미 있는 이름 사용
표기법:
| 표기법 | 예시 |
|---|---|
| camelCase | userName |
| snake_case | user_name |
| Hungarian | int형이면 iCount 같은 식 |
시험에서는 “식별자로 가능한가?” OX 나올 수 있음.
int 1age; // X
int userAge; // O
int int; // X
int user_age; // O
5. 포맷 스트링
포맷 스트링은 printf, scanf에서 자료형을 지정하는 기호다. 강의에서는 %d, %f, %lf, %c 등을 다뤘다. (leeseunghyun.me)
| 포맷 | 의미 |
|---|---|
%d | int 정수 |
%f | float 출력 |
%lf | double 입력/출력 관련 |
%c | 문자 |
%s | 문자열 |
%.2f | 소수점 둘째 자리까지 |
%.15Lf | long double 소수점 15자리 |
예시:
printf("Age: %d\n", age);
printf("Pi: %.15Lf\n", pi_precise);
printf("Status: %s\n", is_running ? "Active" : "Inactive");
stdint.h는 크기가 고정된 정수형을 쓸 때 사용한다.
#include <stdint.h>
int8_t age;
int64_t population;
uint32_t count;
inttypes.h는 고정 너비 정수형 출력용 매크로를 제공한다.
#include <inttypes.h>
printf("%" PRId64 "\n", population);
6. 표준입출력과 fgets
표준입출력에서 대표 함수는 다음과 같다. (leeseunghyun.me)
| 함수 | 설명 |
|---|---|
| printf | 출력 |
| scanf | 입력 |
| getchar | 문자 하나 입력 |
| putchar | 문자 하나 출력 |
| gets | 문자열 입력, 위험 |
| puts | 문자열 출력 |
| fgets | 안전한 문자열 입력 |
scanf()는 입력 크기 제한이 약하면 버퍼 오버플로우 문제가 생길 수 있다. scanf_s()는 Visual Studio에서는 되지만 GCC에서 범용성이 떨어질 수 있다. 그래서 문자열 입력은 보통 fgets()를 쓰는 게 안전하다. (leeseunghyun.me)
fgets 구조
fgets(버퍼이름, 읽을크기, 입력대상);
예시:
char buf[20];
fgets(buf, sizeof(buf), stdin);
| 인자 | 의미 |
|---|---|
| buf | 입력받을 배열 |
| sizeof(buf) | 최대 읽을 크기 |
| stdin | 키보드 입력 |
fgets()는 엔터까지 읽기 때문에 개행 문자를 제거해야 한다.
buf[strcspn(buf, "\n")] = '\0';
이거 시험 빈칸으로 ㅈㄴ 잘 나올 수 있음.
7. atoi, strtol, strtof
fgets()로 입력받으면 문자열이므로 숫자로 바꿔야 한다.
| 함수 | 의미 |
|---|---|
| atoi | 문자열을 int로 변환 |
| strtol | 문자열을 long으로 변환 |
| strtof | 문자열을 float으로 변환 |
atoi()는 변환 실패 시 0을 반환해서, 진짜 입력이 "0"인지 실패인지 구분이 애매하다.
if (a == 0 && buf[0] != '0') {
printf("변환 실패");
}
strtof() 구조:
float value;
char* endPtr;
value = strtof(buf, &endPtr);
검사 구조:
if (endPtr == buf || (*endPtr != '\0' && *endPtr != '\n')) {
printf("유효한 실수가 아닙니다.\n");
}
뜻:
| 조건 | 의미 |
|---|---|
endPtr == buf | 변환이 아예 안 됨 |
*endPtr != '\0' | 숫자 뒤에 이상한 문자가 남음 |
8. 연산자 우선순위
강의에서는 연산자 우선순위를 “단산비논삼대”로 정리했다. (leeseunghyun.me)
단항 > 산술 > 비교 > 논리 > 삼항 > 대입
| 우선순위 | 종류 | 예시 | ||
|---|---|---|---|---|
| 1 | 단항 | ++, --, !, ~ | ||
| 2 | 산술 | +, -, *, /, %, <<, >> | ||
| 3 | 비교 | >, <, >=, <=, ==, != | ||
| 4 | 논리 | &&, ` | ` | |
| 5 | 삼항 | 조건 ? 참 : 거짓 | ||
| 6 | 대입 | =, +=, -=, *=, /= |
주의:
x != 3
이건 “x가 3이 아니다”라는 비교식이다.
x = 3
이건 비교가 아니라 대입이다. 시험에서 낚시 가능.
9. 전위/후위 증가 연산자
i++;
후위: 현재 값을 먼저 사용하고 나중에 증가.
++i;
전위: 먼저 증가하고 증가된 값을 사용.
예시:
int i = 1;
int result = i++ + ++i;
계산:
i++ → 식에는 1 사용, i는 2
++i → i가 3이 되고, 식에는 3 사용
result = 1 + 3 = 4
i = 3
정답:
result = 4
i = 3
10. 쉬프트 연산자
쉬프트 연산자는 비트를 왼쪽/오른쪽으로 이동한다.
1 << 0 = 1
1 << 1 = 2
1 << 2 = 4
1 << 3 = 8
왼쪽 쉬프트:
x << n = x * 2^n
오른쪽 쉬프트:
x >> n = x / 2^n
예시:
4 << 1 = 8
8 >> 1 = 4
3 << 2 = 12
16 >> 2 = 4
비트 플래그 예시:
#define LOG_IN 1 << 0 // 0001
#define IS_ADMIN 1 << 1 // 0010
#define NOTIFICATION 1 << 2 // 0100
상태 추가:
status |= LOG_IN;
status |= NOTIFICATION;
상태 확인:
if (status & LOG_IN) {
// 로그인 상태
}
주의: 강의 정리에는 |= 설명에 XOR이라고 적힌 부분이 있는데, 정확히는 OR 연산이다. XOR은 ^임. 이거 헷갈리면 그대로 틀림.
11. 제어문
제어문은 프로그램의 흐름을 제어하는 문법이다. 강의에서는 분기문, 반복문, 보조 제어문으로 나눴다. (leeseunghyun.me)
분기문
| 문법 | 설명 |
|---|---|
| if | 조건이 참이면 실행 |
| else if | 추가 조건 |
| else | 위 조건이 모두 거짓일 때 |
| switch | 값에 따라 case 선택 |
반복문
| 문법 | 사용 상황 |
|---|---|
| for | 반복 횟수를 알 때 |
| while | 조건 중심 반복 |
| do while | 최소 1번 실행 후 조건 검사 |
| infinite loop | 무한 반복 |
보조 제어문
| 문법 | 의미 |
|---|---|
| break | 반복문/switch 탈출 |
| continue | 이번 반복을 건너뛰고 다음 반복 |
| return | 함수 종료 및 값 반환 |
| goto | 특정 라벨로 이동 |
goto는 코드 흐름을 파악하기 어렵게 만들어서 보통 사용을 지양한다. (leeseunghyun.me)
12. 조기 return
조기 return은 문제가 생겼을 때 함수 아래쪽까지 가지 않고 바로 종료시키는 방식이다.
예시:
FILE* fp = fopen(filename, "r");
if (fp == NULL) {
return ERR_FILE_OPEN;
}
장점:
1. 예외 상황을 빨리 처리함
2. 중첩 if문을 줄임
3. 코드 흐름이 단순해짐
단점:
1. 자원 해제가 필요한 경우 fclose 같은 정리를 빼먹을 수 있음
2. return 위치가 많으면 흐름 추적이 어려울 수 있음
그래서 파일 처리처럼 자원 정리가 필요한 경우에는 goto cleanup 구조도 사용한다.
if (!is_file_valid(fp)) {
result = ERR_INVALID_DATA;
goto cleanup;
}
cleanup:
if (fp != NULL) {
fclose(fp);
}
return result;
핵심:
조기 return은 빠른 종료, goto cleanup은 정리 보장이다.
영어단어 예상 10개
오픈북 3분이면 이거 노트에 박아놔야 함.
| 영어 | 뜻 |
|---|---|
| Syntax | 문법 |
| Logic | 논리, 처리 흐름 |
| Editor | 편집기 |
| IDE | 통합 개발 환경 |
| Compile | 번역, 컴파일 |
| Debugging | 오류 수정 |
| Variable | 변수 |
| Data Type | 자료형 |
| Format String | 데이터 형식 지정 문자열 |
| Operator | 연산자 |
| Operand | 연산에 사용되는 값/변수/식 |
| Buffer Overflow | 버퍼 범위를 초과하는 입력 문제 |
| Token | 구분자 |
| Socket | 네트워크 통신 대상 |
| Return | 함수 종료/값 반환 |
| Break | 반복문 또는 switch 탈출 |
| Continue | 다음 반복으로 이동 |
| Switch | 값에 따른 분기문 |
| Case | switch의 선택 항목 |
| Default | 해당 case가 없을 때 실행 |
10개만 낸다지만 최소 20개 적어가. 영어단어 문제는 “아는 단어인데 한국어 설명 못 써서 틀리는” 병신같은 상황이 자주 나옴.
O/X 예상 포인트
| 문장 | 정답 | ||
|---|---|---|---|
| C언어 코드는 컴파일 없이 CPU가 바로 이해한다. | X | ||
| 변수는 메모리에 값을 저장하기 위한 공간이다. | O | ||
| int는 보통 4byte이다. | O | ||
| char는 보통 1byte이다. | O | ||
| 식별자는 숫자로 시작할 수 있다. | X | ||
scanf()는 입력 주소를 인자로 받을 수 있다. | O | ||
gets()는 버퍼 오버플로우 위험이 있다. | O | ||
fgets()는 읽을 크기를 지정할 수 있다. | O | ||
fgets(buf, sizeof(buf), stdin)에서 stdin은 키보드 입력을 의미한다. | O | ||
atoi()는 변환 실패 시 0을 반환할 수 있다. | O | ||
strtof()는 문자열을 실수로 변환한다. | O | ||
++i는 먼저 증가 후 사용한다. | O | ||
i++는 먼저 사용 후 증가한다. | O | ||
x << 1은 보통 x를 2배 하는 효과가 있다. | O | ||
x >> 1은 보통 x를 2로 나누는 효과가 있다. | O | ||
&&는 논리 OR이다. | X | ||
| ` | `는 논리 OR이다. | O | |
=와 ==는 같은 의미다. | X | ||
return은 함수를 종료할 수 있다. | O | ||
goto는 코드 흐름을 복잡하게 만들 수 있어 사용을 지양한다. | O |
빈칸 문제 예상
1. fgets
char buf[20];
fgets(buf, sizeof(buf), stdin);
빈칸 후보:
fgets(____, ____, ____);
정답:
buf, sizeof(buf), stdin
2. 개행 제거
buf[strcspn(buf, "\n")] = '\0';
빈칸 후보:
buf[____(buf, "\n")] = '\0';
정답:
strcspn
3. strtof
value = strtof(buf, &endPtr);
빈칸 후보:
value = ____(buf, &endPtr);
정답:
strtof
4. 변환 실패 검사
if (endPtr == buf) {
printf("변환 실패");
}
빈칸 후보:
if (____ == buf)
정답:
endPtr
5. 비트 플래그 설정
status |= LOG_IN;
빈칸 후보:
status ____ LOG_IN;
정답:
|=
6. 비트 플래그 확인
if (status & LOG_IN) {
}
빈칸 후보:
if (status ____ LOG_IN)
정답:
&
7. 왼쪽 쉬프트
result += A << shift;
빈칸 후보:
result += A ____ shift;
정답:
<<
8. 오른쪽 쉬프트
temp_n >>= 1;
빈칸 후보:
temp_n ____ 1;
정답:
>>=
9. bool 헤더
#include <stdbool.h>
빈칸 후보:
#include <____>
정답:
stdbool.h
10. 고정 너비 정수형 헤더
#include <stdint.h>
정답:
stdint.h
단답형 예상
Q. fgets를 사용하는 이유는?
scanf()나 gets()보다 입력 크기를 제한할 수 있어 버퍼 오버플로우 위험을 줄일 수 있기 때문이다.
Q. fgets의 인자 3개는?
버퍼 이름, 읽을 크기, 입력 대상.
Q. stdin은 무엇인가?
표준 입력, 보통 키보드 입력을 의미한다.
Q. strcspn(buf, "\n")을 쓰는 이유는?
fgets()가 입력한 개행 문자 \n을 찾아서 제거하기 위해서다.
Q. 조기 return의 장점은?
오류 상황을 빠르게 처리하고 중첩 if문을 줄여 코드 흐름을 단순하게 만든다.
Q. 조기 return의 단점은?
파일, 메모리 같은 자원 해제를 빼먹을 수 있다.
Q. x << 3은 어떤 의미인가?
x를 왼쪽으로 3비트 이동하며, 보통 x * 8과 같은 효과다.
Q. x >> 2는 어떤 의미인가?
x를 오른쪽으로 2비트 이동하며, 보통 x / 4와 같은 효과다.
Q. i++와 ++i의 차이?
i++는 먼저 사용 후 증가, ++i는 먼저 증가 후 사용.
Q. break와 continue 차이?
break는 반복문을 탈출하고, continue는 현재 반복만 건너뛰고 다음 반복으로 간다.
시험 직전 최종 암기
코딩 = 문법 + 로직
컴파일 = 기계어로 번역
변수 = 메모리에 값을 저장하는 공간
자료형 = 메모리 크기와 값 범위 결정
식별자 = 이름, 숫자 시작 불가, 예약어 불가
fgets = 버퍼명, 크기, 입력대상
stdin = 키보드 입력
strcspn = 개행 제거에 사용
atoi = 문자열 → int, 실패 시 0 가능
strtof = 문자열 → float
단산비논삼대 = 단항, 산술, 비교, 논리, 삼항, 대입
i++ = 사용 후 증가
++i = 증가 후 사용
<< = 2의 제곱 곱셈
>> = 2의 제곱 나눗셈
return = 함수 종료
goto = 흐름 복잡, 사용 지양
시험에서 제일 위험한 건 쉬프트 연산자랑 fgets/strtof 구조임. 이 둘은 빈칸으로 나오면 한 줄짜리라 쉬워 보이는데, 정확히 못 외우면 바로 나감.