프로젝트에서 보기 →

C 언어 무료 강의 (입문부터 게임 개발까지)

태그
교육
시작일
종료일
수정일

https://www.youtube.com/watch?v=q6fPjQAzll8

# 1. 이건 꼭 알아야 한다[^1]

[? 질문] 왜 C 언어를 “기본이 되는 언어”라고 부르며, 이를 배우면 다른 언어 학습이 쉬워진다고 말하는가[^5]
[= 답] C는 메모리/자료형/포인터 같은 컴퓨터 동작의 바닥(저수준) 개념을 직접 다루는 언어라서, 한 번 익히면 C++·C#·Java 같은 언어의 구조와 원리를 더 빠르게 이해할 수 있고 파이썬 같은 고수준 언어도 훨씬 수월해진다고 설명한다.[^5]

[? 질문] 초보자가 C에서 가장 많이 포기하는 지점은 무엇이며, 이를 어떻게 넘어가게 하는가[^6]
[= 답] 포인터가 대표적인 포기 지점이며, 강의는 이를 “아파트 주소/암호(값)” 비유로 풀고, 배열·scanf의 & 의미·함수 호출(Call by value vs 주소 전달)까지 연결해 포인터가 실제로 쓰이는 맥락(값 읽기/수정, 함수에서 원본 변경)을 프로젝트로 체험하게 한다.[^196]

[? 질문] 문법을 “알기만 하는 것”에서 “쓸 수 있는 것”으로 바꾸는 학습 방법은 무엇인가[^7]
[= 답] 변수/반복/조건/함수/배열/포인터/구조체/파일입출력 같은 문법을 각 단원에서 바로 텍스트 기반 게임 로직(조서 작성, 피라미드, 업다운, 비밀번호 퀴즈, 발모제 추리, 물고기 키우기, 카드 뒤집기, 고양이 수집, 비밀일기)에 적용해 구현하면서 “어디에 왜 쓰는지”를 연결한다.[^7]


# 2. 큰 그림[^2]

이 콘텐츠는 C 언어를 처음 배우는 사람이 **개발 환경 설정부터 문법 핵심(변수/반복/조건/함수/배열/포인터/구조체/파일)**까지 익히고, 이를 즉시 작은 게임 프로젝트에 적용해 “실제로 작동하는 로직”을 구현하도록 안내하는 장시간 강의다.[^2] 2018년에 제작되었고, 인프런에서 인기 강의였으며 텍스트 기반으로 9가지 게임 로직을 구현하는 흐름을 가진다.[^7]

  • C의 기본기(자료형·메모리·포인터)를 확실히 잡으면 다른 언어 학습이 쉬워진다는 문제의식을 반복적으로 강조한다.[^5]
  • 단원마다 문법 설명 → 작은 실습 → 미니 프로젝트 구현으로 이어져, 문법-사용처 연결을 계속 경험하게 한다.[^7]
  • Visual Studio 2019 환경에서 프로젝트/소스파일 추가/메인 중복 문제 같은 초보가 막히는 실행 환경 이슈까지 함께 다룬다.[^8]

# 3. 하나씩 살펴보기[^3]

## 3.1 강의 소개: C는 ‘대형면허’ 같은 기본 언어, 포인터가 포기 구간[^4]

강의는 “운전면허” 비유로 시작한다.[^4] 대형 버스를 운전할 수 있는 사람이 12인승 수동 승합차를 운전하는 건 비교적 쉽지만, 자동면허만 가진 사람이 12인승 수동을 몰라고 하면 변속/차체 크기 때문에 부담이 크다는 설명을 한다.[^4] 이 비유를 프로그래밍 학습에 연결한다.[^5]

  • C 언어는 기본이 되는 언어로, 이를 공부해두면 C++/C#/Java 같은 언어를 더 쉽게 배우고, 파이썬 같은 언어는 “눈 감고도” 할 정도로 수월해진다고 말한다.[^5]
  • 다만 C는 어렵고, 특히 포인터에서 많은 사람이 포기하며 “C가 미워지는” 경험을 한다고 언급한다.[^6]
  • 이를 위해 강의는 게임을 만들면서 배우는 C 프로그래밍으로 설계되었고, 9가지 게임 로직 핵심을 C로 직접 구현하면서 문법이 어떻게 쓰이는지 알려주겠다고 한다.[^7]
  • 텍스트 기반으로 구현하지만, 실제 서비스/게임을 만들 때 필요한 로직 작성 능력에 초점을 둔다고 한다.[^7]
  • C가 모든 사람에게 필수는 아니지만, 컴퓨터 전공/IT 개발 진로면 권장한다고 말한다.[^7]

[!IMPORTANT] 강의의 학습 전략[^7]
문법을 “설명만” 하는 것이 아니라, 매 단원에서 그날 배운 문법으로 바로 앱/게임의 핵심 코드를 구현해 “왜 필요한지”를 체감하게 만든다.


## 3.2 개발 환경 설정(Visual Studio 2019)과 Hello World 실행[^8]

강의는 Visual Studio 2019 설치부터 진행한다.[^8]

  1. 구글에서 Visual Studio 2019 검색 → 다운로드 → Community 2019(무료) 설치를 안내한다.[^8]
  2. 설치 옵션에서 “C++를 사용한 데스크톱 개발”을 체크하라고 한다(실제로 C 프로젝트를 만들지만 VS 설치 워크로드가 그 경로에 있음).[^8]
  3. 실행 후 로그인은 선택이며, 테마(어두움)와 개발 설정(C++)를 고른 뒤 시작한다.[^8]

프로젝트 생성 흐름은 다음처럼 안내한다.[^9]

  • 새 프로젝트 만들기 → 언어 필터링(C++) → “빈 프로젝트” 선택 → 프로젝트명(MyProject) 생성[^9]
  • 솔루션 탐색기에서 소스 파일 우클릭 → 추가 → 새 항목 → C++ 파일 선택 후 확장자를 .c로 만들어야 C 코드가 된다고 설명한다( .cpp는 C++ ).[^9]
  • #include <stdio.h>를 포함하고 int main(){ printf("Hello World\n"); } 형태로 작성한다.[^10]
  • 디버그하지 않고 시작(Ctrl+F5)을 통해 출력 창에서 “Hello World”가 출력됨을 확인한다.[^10]

또한 stdio.h를 “스튜디오”로 오타내지 말고 standard input/output라는 맥락에서 stdio.h라고 설명한다.[^10]


## 3.3 변수/상수/입출력(printf, scanf) + 주석: “경찰서 조서 쓰기” 앱으로 연결[^11]

이 단원은 프로그래밍 기초인 변수·상수·입력·출력을 설명하고, 이를 “경찰서 조서 쓰기” 앱(이름/나이/몸무게/키/범죄 입력 후 조서 출력)의 핵심 로직으로 구현한다.[^11]

3.3.1 정수와 실수 개념 소개 → 변수란 무엇인가[^12]

  • 정수: -2, -1, 0, 1처럼 소수점 없는 수[^12]
  • 실수: -2.0, 1.3처럼 소수점이 있는 수[^12]
  • 예시로 12는 정수, 46.5는 실수라고 짚는다.[^12]

변수는 “변하는 수”, 상수는 “변하지 않는 수”로 설명한다.[^13]
경찰 앱 예시에서 “나이”는 해가 바뀌면 바뀌므로 상수가 아니라 변수라는 논리로 연결한다.[^13]

3.3.2 정수형 변수 선언/출력, 값 변경, 선언 vs 사용[^14]

  • int age = 12; 형태로 선언하고, printf("%d\n", age);로 출력한다.[^14]
  • %d는 정수 출력 포맷이며, 콤마 뒤 인자가 순서대로 포맷에 들어간다고 설명한다.[^14]
  • 변수는 이후에 age = 13;처럼 값을 바꾸면 출력 결과가 바뀐다는 예를 보여준다.[^15]
  • 한 번 int age선언하면 이후에는 int를 다시 쓰지 않고 값 대입/사용하면 된다고 정리한다.[^16]

3.3.3 주석: 블록 주석과 라인 주석[^17]

  • /* ... */로 감싼 구간은 모두 무시됨(블록 주석).[^17]
  • //는 해당 줄을 무시함(라인 주석).[^17]
  • 주석은 메모/설명/나중에 본인이나 다른 사람을 위한 기록이라고 설명한다.[^18]

3.3.4 실수형 변수(float/double)와 출력 포맷 지정[^19]

  • 소수는 float로 표현하며, 리터럴 뒤에 f를 붙이라고 안내한다(예: float weight = 46.5f;).[^19]
  • 출력은 %f를 사용한다.[^19]
  • 기본 출력은 소수점이 길게 나오므로 %.2f처럼 소수점 자리수를 지정하는 방법을 설명한다.[^20]
  • double도 소개하며 출력 포맷을 %lf로 사용한다고 말한다.[^20]
  • 예시로 4.428 같은 값을 %.2lf로 출력하면 반올림되어 4.43이 나오는 것을 보여준다.[^21]

3.3.5 상수(const): 태어난 연도 예시[^22]

  • 상수는 한 번 정의하면 값 변경 불가, 보통 대문자로 쓰는 습관을 언급한다.[^22]
  • 태어난 연도처럼 바뀌면 안 되는 값은 const로 선언해야 하며, 수정하려 하면 컴파일러가 변경 불가 오류(빨간 줄)로 알려준다고 시연한다.[^23]

3.3.6 printf로 연산 결과 출력(변수 사용/미사용) + 곱셈 표기[^24]

  • int a = 3 + 7;처럼 대입 시 계산되어 저장된다는 점을 보인다.[^24]
  • printf에 포맷을 여러 개 두고 값들을 순서대로 넣어 3 + 7 = 10 같은 출력을 만든다.[^25]
  • 더 복잡한 연산(30+79, 30*79)을 예로 들며, 컴퓨터에서 곱셈은 *(별표)라고 설명한다.[^26]

3.3.7 scanf로 입력받기(정수 1개/3개), 문자, 문자열[^27]

scanf를 “키보드 입력을 받아 저장”이라고 정의한다.[^27]

  • 정수 1개 입력: scanf_s("%d", &input); 형태로 설명하며 &는 입력을 변수 위치에 넣기 위한 주소 표시라고 강조한다.[^27]
  • 정수 3개 입력: %d %d %d로 공백 구분 입력을 받고 &n1, &n2, &n3에 저장하는 예를 보여준다.[^28]
  • 문자 입력: char c = 'A';와 출력 %c를 보여준다.[^29]
  • 문자열 입력: char str[256];처럼 배열을 만들어 %s로 입력받고, sizeof(str)로 최대 입력 크기를 제한하는 방식을 소개한다.[^30]

3.3.8 미니 프로젝트: 경찰서 조서 쓰기 핵심 코드 구현[^31]

입력받을 항목은 이름/나이/몸무게/키/범죄명이며, 각 자료형을 상황에 맞게 선택한다.[^31]

  • 이름/범죄명: char name[256];, char what[256]; + scanf_s("%s", name, sizeof(name));[^31]
  • 나이: int age; + scanf_s("%d", &age);[^32]
  • 몸무게: float weight; + scanf_s("%f", &weight);[^33]
  • 키: double height; + scanf_s("%lf", &height);[^34]

출력은 포맷을 조합해 조서 내용을 출력한다.[^35]
특히 몸무게는 %.2f, 키는 %.2lf로 소수점 2자리로 정리한다.[^35]
실행 예로 “나도코딩/12/46.5/190.23/지각”을 입력하면 조서가 출력되는 흐름을 보여준다.[^36]


## 3.4 반복문(for/while/do-while), ++ 연산자, 이중 반복문, 별 피라미드 프로젝트[^37]

이 단원은 반복문 3종(for/while/do-while)과 중첩 반복을 설명하고, 별 찍기/피라미드 쌓기 앱을 구현한다.[^37]

3.4.1 새 파일 만들 때 main 중복 오류와 해결[^38]

새 소스 파일을 만들고 int main()을 또 만들면 “main이 이미 정의됨” 오류가 난다고 설명한다.[^38]
하나의 프로젝트에 main이 여러 개면 어떤 main을 실행할지 몰라서 오류가 나므로, 이전 파일의 main 이름을 main_printfs...처럼 바꾸는 방식으로 우회한다고 시연한다.[^38]

3.4.2 ++(전위/후위) 설명: 출력 순서 차이[^39]

  • a++는 문장 수행 후 증가, ++a는 증가 후 사용이라는 차이를 예제로 보여준다.[^39]
  • 예시로 b가 20일 때 ++b 출력은 21, b++ 출력은 21이지만 다음 줄에서 b가 22가 되는 흐름을 단계적으로 설명한다.[^40]

3.4.3 for문: 선언-조건-증감 구조로 10회 출력 축약[^41]

“Hello World 10번 출력”을 복붙 대신 반복문으로 줄이는 목적을 제시한다.[^41]
for (int i=1; i<=10; i++) { printf("Hello World %d\n", i); } 흐름으로
선언→조건 확인→본문 수행→증감→조건 재확인→탈출을 상세히 풀어 설명한다.[^42]

3.4.4 while문: 증감 위치를 직접 넣어야 함[^43]

i=1; while(i<=10){ ...; i++; } 형태로 같은 출력을 만들며, for와 달리 증감이 문장 내부에 없으면 무한루프 위험이 있다는 포인트를 강조한다.[^43]

3.4.5 do-while문: 일단 1번 실행 후 조건 검사[^44]

do { ... } while(i<=10); 형태를 보여주며, 선언/조건/증감 구성 예시로 1~10 출력이 되도록 만든다.[^44]

3.4.6 이중 반복문: 바깥 루프 3회 × 안쪽 루프 5회[^45]

for(i=1..3) 안에 for(j=1..5)를 넣어 “첫 번째 반복문 i”마다 “두 번째 반복문 j”가 5회 실행되는 구조를 출력으로 확인한다.[^45]

3.4.7 이중 반복문으로 구구단(2~9단) 구현[^46]

  • 바깥 i=2..9, 안쪽 j=1..9i*j를 출력한다.[^46]
  • “과거엔 프린트를 엄청 많이 썼을 것”이라는 비교로 반복문의 강력함을 강조한다.[^47]

3.4.8 별 증가 출력(왼쪽 정렬) + 표로 i/j 흐름 설명[^48]

5줄에 *, **, ***, ****, *****를 출력하는 문제를 제시하고,
for i=0..4 안에서 for j=0..i 별을 찍고 줄바꿈하는 방식으로 해결한다.[^48]

이때 초보가 헷갈리는 i/j 변화 과정을 “표(i, j, 출력)”로 상세히 따라가며 설명한다.[^49]

3.4.9 오른쪽 정렬 별 출력: 공백과 별의 관계[^50]

오른쪽 정렬은 “앞의 빈칸 수”가 줄어드는 구조임을 보여준다.[^50]
공백 출력용 루프(j)와 별 출력용 루프(k)를 분리해 구현하고, i값을 이용해 j=i .. (floor-1) 같은 형태로 공백을 조절한다.[^50]

3.4.10 “피라미드를 쌓아라” 프로젝트: 층 입력(5~100) → 홀수 별(1,3,5...) 출력[^51]

사용자에게 “몇 층으로 쌓겠냐”를 입력받고, 각 층마다 별이 1,3,5...로 증가하는 피라미드를 출력한다.[^51]
별 개수는 i*2 + 1로 만들며, 공백은 오른쪽 정렬 방식과 동일한 원리로 맞춘다.[^52]
10층, 40층 같은 예를 실행해 출력되는 모습을 확인한다.[^53]


## 3.5 조건 분기(if/else if/else), break/continue, 논리연산자, random, switch, 업다운 게임[^54]

이 단원은 조건문과 흐름 제어(break/continue), switch, 랜덤까지 배우고 “업앤다운” 숫자 맞히기 게임을 만든다.[^54]

3.5.1 if-else 기본: 버스 승객 학생/일반 구분[^55]

나이(age)가 20 이상이면 일반, 아니면 학생이라는 형태로 if/else를 소개한다.[^55]
한 줄짜리 if도 가능하지만 습관적으로 중괄호를 쓰자고 권한다.[^56]

3.5.2 else if 체인: 초/중/고 구분 + 범위 조건(&&)[^57]

  • 초등(8~13), 중등(14~16), 고등(17~19) 범위를 조건으로 처리한다.[^57]
  • age >= 8 && age <= 13처럼 &&는 두 조건 모두 만족해야 함을 설명한다.[^57]
  • 어느 조건을 만족하면 그 아래 else if는 더 보지 않고 탈출하는 흐름을 설명한다.[^58]
  • 그 어떤 범위에도 속하지 않으면 마지막 else로 “학생이 아닌가 봐요”를 출력해 모든 숫자 케이스를 커버한다고 정리한다.[^59]

3.5.3 break: 반복문을 즉시 탈출(조별 발표 예시)[^60]

1~30번 학생을 출력하다가 6번 이상이면 “나머지 학생은 집에 가세요” 출력 후 break로 루프를 종료하는 예를 든다.[^60]

3.5.4 continue: 이번 반복만 건너뛰기(7번 결석 처리)[^61]

6~10번 발표 대상 중 7번은 결석이므로, 7번일 때 결석 출력 후 continue로 “발표 준비” 출력 라인을 건너뛰게 만든다.[^61]
break는 루프 전체 탈출, continue는 다음 반복으로 이동이라는 차이를 강조한다.[^61]

3.5.5 논리연산자 && / || 비교 예시[^62]

  • &&: a==b 그리고 c==d일 때만 실행[^62]
  • ||: 둘 중 하나라도 같으면 실행[^63] 각 조건에서 어떤 출력이 되는지 값 예시를 바꾸며 보여준다.[^63]

3.5.6 랜덤(rand)와 난수 초기화(srand(time(NULL)))[^64]

  • rand() % 3은 0~2 중 하나를 반환하며, 1~3을 원하면 rand()%3 + 1로 보정한다고 설명한다.[^64]
  • 중요 포인트: srand(time(NULL));로 난수 초기화를 하지 않으면 실행할 때마다 같은 난수 시퀀스가 나온다.[^65]
  • 초기화 전/후를 10회 출력으로 비교해, 초기화 후에는 실행마다 다른 값이 나옴을 확인한다.[^66]

3.5.7 switch-case: 가위바위보 출력 + break 필요성[^67]

if/else if로 0=가위, 1=바위, 2=보 출력하던 것을 switch(a)로 바꾸는 예를 든다.[^67]
break가 없으면 아래 case가 “연쇄 실행(fall-through)”되어 가위/바위/보/몰라요가 모두 출력될 수 있음을 시연하고, 각 case 끝에 break를 넣어야 한다고 강조한다.[^68]

또한 나이 구분(초/중/고)을 switch로도 만들 수 있음을 보여주며, 여러 case를 break 없이 묶어 같은 출력을 공유하는 방식(8~13 모두 초등학생)을 예시로 설명한다.[^69]

3.5.8 업다운 게임 구현(랜덤 1~100, 기회 5번)[^70]

  • number = rand() % 100 + 1로 정답 생성, 교육용으로 정답을 미리 출력한다.[^70]
  • chance=5로 시작해 while(chance>0)에서 남은 기회를 출력하고, 입력값을 scanf로 받는다.[^71]
  • 입력값이 정답보다 크면 “Down”, 작으면 “Up”, 같으면 “정답입니다” 출력 후 break로 종료한다.[^72]
  • 기회가 0이면 실패 메시지를 출력하도록 로직을 넣을 수 있다고 덧붙이며, while(1) 무한루프와 break 조합도 설명한다.[^73]
  • 실행 예로 여러 번 시도해 정답을 맞히는 과정을 보여준다.[^74]

## 3.6 함수(function): 코드 중복 제거 → 계산기 예제 → 비밀번호 마스터 프로젝트[^75]

함수는 “입력값(x) → 처리 → 출력값(y)” 박스 모델로 설명한다.[^75]
이 단원에서 함수 선언/정의/반환/파라미터 조합을 학습하고, 랜덤 문제 생성 퀴즈 게임(비밀번호 마스터)을 만든다.[^76]

3.6.1 계산기 예제: 중복되는 출력문을 함수로 분리[^77]

  • 변수에 2를 넣고 +3, -1, *3, /6을 수행하며 매번 “number는 %d입니다”를 출력하는데, 같은 문장이 반복되는 문제를 제기한다.[^77]
  • void p(int number); 형태로 함수 선언을 main 위에 두고, main 아래에 정의를 둔다고 설명한다.[^78]
  • p(num);처럼 호출하면 동일 출력이 반복 없이 가능하다고 시연한다.[^79]

함수 구성 요소를 “반환형/함수명/전달값(파라미터)”로 정리한다.[^80]
반환형은 int/double/char/void 등 반환 데이터에 따라 정한다고 말한다.[^81]

3.6.2 함수 종류 조합: 반환 없음/있음, 파라미터 없음/있음[^82]

  • 반환값 없는 함수: void function_without_return() 실행 예 출력[^82]
  • 반환값 있는 함수: int function_with_return(){ return 10; } 호출값을 변수에 저장 후 출력[^83]
  • 파라미터 없는 함수: 전달값 없이 메시지 출력[^84]
  • 파라미터 있는 함수: 정수 3개 받아 포맷 출력(1,2,3 / 35,27,12 등) 확인[^85]
  • 파라미터+반환: 사과(total, eat) 예시로 return total - eat;를 반환하고 printf 안에서 함수 호출값을 바로 사용하기도 함[^86]

3.6.3 사칙연산을 함수로 분리(add/sub/mul/div)하여 계산기 재구성[^87]

add, sub, multiply, divide를 모두 int 반환, 두 정수 파라미터로 만들어 재사용하는 형태로 코드를 간결하게 만든다.[^87]

[!TIP] 함수 사용 핵심 규칙[^88]

  • main 위에 선언을 먼저 해두면, 정의가 아래에 있어도 호출 가능하다.[^88]
  • 선언부와 정의부의 시그니처(반환형/이름/파라미터)는 동일해야 한다.[^88]

3.6.4 프로젝트: “비밀번호 마스터” (랜덤 곱셈 퀴즈 5문, 난이도 상승)[^89]

목표는 문(레벨)마다 랜덤 곱셈 문제를 내고 맞히면 통과, 틀리면 실패/혹은 계속 진행 등 규칙을 구현하는 것이다.[^89]
강의 구현은 “5문 중 몇 개 맞췄는지 카운트” 방식으로 변형한다.[^90]

구성 요소:

  • getRandomNumber(level): rand() % (level*7) + 1로 레벨이 올라갈수록 범위가 커져 문제 난이도가 올라가게 한다.[^91]
  • showQuestion(level, n1, n2): “N번째 비밀번호, n1*n2는?” 형태로 문제 출력과 입력 안내(-1이면 종료)를 담당한다.[^92]
  • 입력: answer를 받아 -1이면 exit(0)로 즉시 프로그램 종료(브레이크는 이후 결과 출력이 나와서 부자연스럽다고 판단).[^93]
  • 정답이면 success() 호출 + 카운트 증가, 오답이면 fail() 호출.[^94]
  • 5회 반복 후 “5개 중 몇 개 맞춤” 결과 출력.[^95]

실행 중 “반복 조건을 <로 써서 5문이 아닌 4문만 나옴” 같은 버그를 발견하고 <=로 수정하는 디버깅 장면도 보여준다.[^96]


## 3.7 배열(array): 연속 공간/0부터 시작 인덱스/초기화/문자열/ASCII → 발모제 게임[^97]

배열은 “지하철 칸” 비유로 설명한다.[^97] 1호차/2호차/3호차 승객 수를 변수를 여러 개 두는 대신, 연속된 칸으로 묶는 구조가 배열이라고 한다.[^97]

3.7.1 int 배열 선언/대입/루프 출력: 인덱스는 0부터[^98]

  • int subway[3]; subway[0]=30; subway[1]=40; subway[2]=50;[^98]
  • for(i=0;i<3;i++) printf("%d호차에 %d명", i+1, subway[i]);로 출력[^99]

3.7.2 중괄호 초기화, 미초기화 쓰레기값, 부분 초기화 시 0 자동[^100]

  • int arr[10] = {1,2,3,...,10};[^100]
  • 초기화 없이 선언하면 이상한 값(쓰레기값)이 나온다고 보여준다.[^101]
  • {1,2}만 넣으면 나머지는 0으로 채워짐을 확인한다.[^102]
  • 배열 크기는 변수로 못 두고 상수로 넣어야 한다고 설명한다(컴파일 오류 시연).[^103]
  • 크기 생략(int arr[] = {1,2};)하면 값 개수로 크기가 결정된다고 한다.[^104]

3.7.3 float 배열, 루프 범위 오류(10회 출력하면 뒷부분 이상값) 경고[^105]

float 배열을 만들고 %.2f로 출력하며, 배열 크기 5인데 루프를 10으로 돌리면 뒤가 이상하게 나오는 사례로 “범위 초과” 문제를 보여준다.[^105]

3.7.4 문자열(char 배열)과 널 문자('\0')의 필요[^106]

  • char str[6] = "coding";처럼 크기를 딱 6으로 하면 출력 시 뒤에 이상 문자가 붙는 문제를 보여준다.[^106]
  • 문자열 끝에는 반드시 **널 문자(0)**가 필요하므로 char str[7] = "coding";처럼 +1 공간이 있어야 정상 출력된다고 설명한다.[^107]
  • sizeof(str)를 출력하면 널 문자까지 포함한 길이(7)가 나온다고 확인한다.[^108]
  • 포문으로 %c로 한 글자씩 찍으면 마지막에 “비어 있는 값(널)”이 있음을 보여준다.[^109]

3.7.5 한글 문자열 바이트: 영어 1바이트 vs 한글 2바이트[^110]

“나도코딩”을 char[]로 두고 sizeof를 찍으면 9가 나오는 사례를 통해, 한글은 2바이트씩 필요해서 4글자×2=8 + 널 1 = 9가 된다고 설명한다.[^110]

3.7.6 ASCII 코드: 문자 출력(%c) vs 정수 출력(%d)[^111]

  • 'a'를 %d로 출력하면 97, 'A'는 65, '0'은 48이라는 ASCII 규칙을 설명한다.[^111]
  • 0~127을 출력해 ASCII 테이블을 간단히 확인하는 코드도 보여준다(일부 제어문자는 소리를 낼 수 있음).[^112]

3.7.7 프로젝트: “아빠는 대머리” 발모제 추리 게임(배열+랜덤+중복 제거)[^113]

게임 설정: 4개 병 중 1개가 진짜 발모제이며, 사용자는 3번의 시도 동안 2개 또는 3개의 병 조합을 보여주고 “머리가 났다/안 났다” 힌트를 보고 정답 병 번호를 맞힌다.[^113]

핵심 구현 흐름:

  • treatment = rand()%4;로 정답(0~3)을 정한다.[^114]
  • 3회 시도 루프에서 int bottle[4]={0,0,0,0};로 이번 시도에 선택된 병을 표시한다.[^115]
  • 이번 시도에서 보여줄 병 개수는 countShowBottle = rand()%2 + 2;로 2 또는 3개를 고른다.[^116]
  • 연속 시도에서 병 개수가 같게 반복되면 정답률이 떨어진다고 보고, 직전 값 prevCountShowBottle과 다르게 나오도록 조정하는 장치를 넣는다.[^117]
  • 병을 고를 때 중복 선택이 나오면 j--로 재시도하여 실제로 2개/3개가 채워지게 한다.[^118]
  • 선택된 병 중 정답(treatment)이 포함되면 isIncluded=1로 두고, 결과로 “머리가 났습니다/안 났습니다”를 출력한다.[^119]
  • 각 시도 후 getchar()로 “아무키나 누르면 다음” 진행을 구현한다.[^120]
  • 마지막에 사용자에게 “발모제는 몇 번?” 입력을 받아, 정답 비교 시 treatment+1로 1~4로 맞춘다.[^121]

구현 후 병 개수 번갈아 장치가 동작하지 않는 버그를 발견하고, prevCountShowBottle = countShowBottle; 갱신을 누락했던 것을 수정한다.[^122]


## 3.8 포인터(pointer): 주소(&)와 역참조(*) 비유 + 배열과 포인터 관계 + swap/scanf 연결 → 물고기 키우기[^123]

포인터 단원은 “C 포기의 상징”으로 언급했던 포인터를 아파트 비유로 풀어낸다.[^123]

3.8.1 주소(&)와 값: 철수/영희/민수 집(주소)과 문앞 암호(값)[^124]

  • 변수(철수=1, 영희=2, 민수=3)를 “각 집 문앞 암호”로 비유한다.[^124]
  • &철수를 출력하면 철수 변수가 저장된 메모리 “주소”가 나온다고 설명한다.[^125]
  • 실행할 때마다 주소는 달라질 수 있다고 말한다.[^126]

3.8.2 포인터 변수: 미션맨이 주소를 들고 가서 암호(*)를 읽는다[^127]

  • int* 미션맨 = &철수;처럼 포인터는 주소를 저장한다.[^127]
  • 미션맨이 방문하는 곳(주소)은 미션맨, 그곳 암호(값)는 *미션맨으로 출력한다.[^127]
  • 미션맨을 &영희, &민수로 바꿔가며 같은 방식으로 값 읽기를 보여준다.[^128]

3.8.3 포인터로 값 수정: *미션맨 *= 3 (암호에 3 곱하기)[^129]

*미션맨 *= 3;처럼 역참조한 값 자체를 바꾸면 원래 변수 값이 바뀐다는 것을 보여준다.[^129]

3.8.4 포인터를 가리키는 포인터: 스파이가 미션맨을 추적해 -2 수행[^130]

int* 스파이 = 미션맨;처럼 포인터 둘이 같은 주소를 가리킬 수 있고, 스파이가 *스파이 -= 2로 값을 또 바꾸면 철수/영희/민수 값이 실제로 변함을 확인한다.[^130]

3.8.5 포인터 자신도 변수이므로 주소가 있다[^131]

미션맨/스파이 자체도 변수이므로 &미션맨, &스파이 주소도 출력할 수 있다고 덧붙인다.[^131]

3.8.6 배열과 포인터: 배열 이름은 첫 원소 주소와 같다[^132]

  • int arr[3]={5,10,15}; int* ptr=arr;로 ptr을 배열에 붙이면 ptr[0] 같은 표현이 가능하고 값이 동일하게 출력된다.[^132]
  • ptr[0]=100; ptr[1]=200; ptr[2]=300; 하면 배열 값도 바뀜을 보여주며, ptr과 arr이 같은 메모리 영역을 가리킨다는 결론을 낸다.[^133]
  • *(arr+i)arr[i]와 동일한 표현이며, *(ptr+i)도 같은 방식으로 가능하다고 설명한다.[^134]
  • arr 값과 &arr[0]가 같음을 실제 출력으로 확인한다.[^135]
  • *&가 붙으면 상쇄되는 개념(주소→역참조→원래값)도 예제로 보여준다.[^136]

3.8.7 함수에서 swap이 안 되는 이유(Call by value)와 주소 전달로 해결[^137]

  • swap(int a, int b)로 값만 전달하면 함수 안에서는 바뀌지만 함수 밖 변수는 안 바뀐다.[^137]
  • 주소를 출력해 함수 밖 a/b와 함수 안 a/b의 주소가 다름을 보여주며, 값이 복사된 것임을 설명한다.[^138]
  • swap_addr(int* a, int* b)&a, &b를 넘기고 *a, *b를 바꾸면 함수 밖 값이 실제로 바뀌는 것을 확인한다.[^139]
  • 이로써 scanf("%d", &num)에서 왜 &를 붙이는지 이유를 연결한다.[^140]

3.8.8 배열을 함수에 넘겨 요소 변경(changeArray)도 주소 전달의 예[^141]

배열 자체가 첫 원소 주소이므로 changeArray(arr2); 또는 changeArray(&arr2[0]);가 동일하게 동작하며, 함수에서 ptr[2]=50;처럼 변경하면 원본 배열이 바뀜을 보여준다.[^141]

3.8.9 프로젝트: “물고기 키우기” (시간/배열/포인터/함수 결합)[^142]

게임 설정: 물고기 6마리(어항 6개). 사막이라 물이 빠르게 증발하며, 사용자는 번호를 입력해 특정 어항에 물을 1만큼 채운다. 시간이 지날수록 난이도(레벨)가 올라가 물 감소가 빨라지고, 물이 0이 되면 물고기가 죽는다.[^142]

구현 요소:

  • 시간 측정: clock()를 사용하고 time.h 포함, 밀리초 단위 값을 CLOCKS_PER_SEC로 나눠 초 단위로 만든다.[^143]
  • 상태 변수: 시작 시간, 총 경과 시간, 직전 경과 시간(최근 물 준 시점 대비 경과), 입력 번호, 레벨(1~5), 어항 물 높이 배열(6개, 100으로 초기화).[^144]
  • 포인터 커서: 사용자가 선택한 어항을 가리키는 포인터 개념을 도입해 접근한다는 의도를 설명한다.[^145]

핵심 함수들:

  1. printFish()
  • 1~6번 어항 번호를 출력하고 각 어항 물 높이를 정렬해 보여준다(포맷 폭을 맞추는 이유도 설명).[^146]
  1. 입력값 검증
  • 번호가 1~6 범위 밖이면 “잘못된 입력” 출력 후 continue로 루프 상단으로 돌아간다.[^147]
  1. 시간 계산
  • totalElapsedTime = (clock() - startTime) / CLOCKS_PER_SEC[^148]
  • prevElapsedTime = totalElapsedTime - prevElapsedTime 형태로 “직전 물 준 이후 경과”를 계산해 물 감소량 산정에 사용한다.[^149]
  1. decreaseWater(elapsed)
  • 각 어항에서 level * 3 * elapsed만큼 물을 빼고, 0 미만이면 0으로 클램프한다(3은 난이도 보정 상수).[^150]
  1. 물 주기
  • 선택한 어항 물이 0이면 “이미 죽어서 물을 주지 않는다”를 출력한다.[^151]
  • 물을 주더라도 100을 넘지 않게 조건 체크 후 +=1 한다.[^152]
  1. 레벨업
  • 20초마다 레벨업하도록 totalElapsedTime/20 > level-1 조건으로 구현하고, 레벨이 5가 되면 exit(0)으로 종료한다.[^153]
  1. checkFishAlive()
  • 어항 중 하나라도 물이 0보다 크면 1 반환(아직 생존), 모두 0이면 0 반환 후 “모든 물고기가 죽음” 출력하고 종료한다.[^154]

마지막으로 “직전 시간” 저장을 위해 prevElapsedTime = totalElapsedTime처럼 업데이트해야 다음 입력 시 간격 계산이 맞는다는 것을 단계 예시(10초→15초→25초)로 상세히 설명한다.[^155]

실행 시연에서는 설명하는 동안 시간이 흘러 물이 급감해 물고기가 빨리 죽는 사례가 나오고, 난이도 상수(3)가 커 보인다는 코멘트도 한다.[^156]


## 3.9 다차원 배열(2D/3D): 좌표 접근, 초기화 모양 이해 → 카드 뒤집기(동물 쌍찾기) 프로젝트[^157]

다차원 배열은 “대괄호가 하나 더 늘어나는 것”으로 정의한다.[^157]

3.9.1 2차원/3차원 배열 구조를 그림으로 설명[^158]

  • arr2[2][5]는 “5칸짜리 배열이 2개”라는 식으로 뒤에서부터 해석한다.[^158]
  • arr3[4][2]는 “2칸짜리 배열이 4개”.[^158]
  • 3차원 arr4[3][3][3]는 3×3×3=27칸이며, “2차원 블록이 3개” 같은 방식으로 확장한다고 설명한다.[^158]

인덱스 접근은 2D에서 (x,y) 좌표처럼 arr[i][j], 3D는 arr[i][j][k]로 접근한다고 정리한다.[^159]

3.9.2 선언 시 중괄호를 줄바꿈으로 정렬하면 구조가 보인다[^160]

3차원 배열 초기화를 엔터/콤마 위치에 맞춰 정렬하면, 위에서 그린 블록 구조가 코드 형태로 그대로 보인다는 점을 보여준다.[^160]

3.9.3 2D/3D 출력 루프: 차원 수만큼 for문이 늘어난다[^161]

  • 2D는 for 2개로 i/j 순회하며 좌표와 값을 출력한다.[^161]
  • 3D는 for 3개(i/j/k)로 순회하며 값을 출력한다.[^162]

3.9.4 프로젝트: 동물 뒤집기(쌍찾기) 핵심 로직[^163]

게임 개요: 4×5=20장 카드에 10종 동물이 2장씩 존재. 사용자는 카드 두 장을 선택해 같으면 뒤집힌 상태로 유지, 다르면 다시 감춘다. 모두 찾으면 실패 횟수 출력 후 종료.[^163]

구현 구성:

  1. initAnimalArray()
  • int animal[4][5]를 -1로 초기화하여 “비어 있음”을 표시한다.[^164]
  1. 동물 이름 배열
  • char* strAnimal[10] 형태로 원숭이/하마/강아지/고양이/돼지/코끼리/기린/낙타/타조/호랑이 등을 저장한다.[^165]
  • “문자열이 메모리 어딘가에 있고, char*는 그 주소를 가진다”는 관점을 언급한다.[^165]
  1. shuffleAnimal()
  • 각 동물(i=0..9)을 2번씩(j=0..1) 배치한다.[^166]
  • 빈 위치를 랜덤으로 찾아 넣기 위해 getEmptyPosition()을 호출한다.[^166]
  • 랜덤 위치(0~19)를 2D 좌표로 바꾸기 위해 convertPositionX, convertPositionY를 사용한다.[^167]
  • 좌표로 변환 후 animal[x][y]=i;로 같은 동물 번호를 두 위치에 넣는다.[^166]
  1. getEmptyPosition()
  • while(1)에서 0~19 랜덤 선택 후 x/y로 변환, 해당 칸이 -1이면 그 위치를 반환, 아니면 재시도한다.[^168]
  • 강의는 구조체를 아직 안 배운 시점이라 “좌표 묶음 반환” 대신 정수 position을 반환하고, 호출부에서 다시 변환하는 방식으로 구현한다는 설명을 덧붙인다.[^169]
  1. convertPositionX(pos)=pos/5, convertPositionY(pos)=pos%5
  • 5로 나눈 몫이 행(x), 나머지가 열(y)이라는 논리를 0~19 번호를 격자에 매핑해 설명한다.[^170]
  1. 게임 루프
  • checkAnimal[4][5]를 0으로 두고(아직 못 찾음), 찾은 카드만 1로 표시해 문제 출력 시 동물 이름을 보여주게 한다.[^171]
  • printAnimals()는 디버그용으로 전체 동물 배치를 몰래 보여주는 기능이라고 말한다.[^172]
  • printQuestion()은 아직 못 찾은 카드는 시퀀스 번호(0~19)를, 찾은 카드는 동물 이름을 출력한다.[^173]
  • 사용자 입력 select1, select2를 받고, 같은 카드 선택이면 continue로 무효 처리한다.[^174]
  • 선택 번호를 x/y로 변환해,
    • 두 카드가 아직 안 뒤집혔고(checkAnimal==0)
    • 두 위치의 동물 번호가 같으면(animal[x1][y1]==animal[x2][y2]) → “빙고 %s 발견” 출력 후 checkAnimal 두 칸을 1로 만든다.[^175]
  • 아니면 “틀렸거나 이미 뒤집힌 카드”로 안내하고, 선택한 카드의 실제 동물을 공개해 기억 게임 요소를 만든다.[^176]
  • failCount++로 실수 횟수 누적[^176]
  • foundAllAnimals()로 checkAnimal에 0이 남아 있는지 검사해, 모두 1이면 성공 메시지와 실수 횟수 출력 후 break로 종료한다.[^177]

디버깅 장면:

  • 처음 출력이 0만 나오는 문제는 시퀀스 증가(sequence++)를 빼먹어서 생긴 버그였고 수정한다.[^178]
  • 또 시퀀스를 if/else 내부에 넣어 “동물 이름 출력 분기”에서는 증가가 안 되는 문제를 발견해, 시퀀스 증가 위치를 공통 경로로 옮기는 과정을 보여준다.[^179]

## 3.10 구조체(struct): 관련 변수 묶기, 구조체 배열/포인터/typedef → 고양이 수집 게임[^180]

구조체는 “관련 있는 변수들을 하나로 통합”하는 도구라고 정의한다.[^180]

3.10.1 게임 출시 정보 예시: 변수 흩어짐 문제 → struct로 해결[^181]

게임명/발매년도/가격/제작사를 각각 변수로 두면 게임이 여러 개일 때 변수명이 늘어나 혼란스러워진다고 문제를 제기한다.[^181]

struct GameInfo { char* name; int year; int price; char* company; }; 형태로 묶고,
struct GameInfo game1; game1.name=...처럼 점(.)으로 접근한다고 설명한다.[^182]

출력은 printf 포맷에 game1.name/year/price/company를 넣어 “게임 출시 정보”를 구성한다.[^183]

3.10.2 구조체 초기화: 중괄호로 한 번에 넣기, 구조체 배열[^184]

struct GameInfo game2 = {"너도게임", 2017, 100, "너도회사"};처럼 순서대로 초기화할 수 있음을 보여준다.[^184]
struct GameInfo gameArr[2] = { {...}, {...} };처럼 배열로 여러 게임 정보를 관리할 수 있음을 설명한다.[^185]

3.10.3 구조체 포인터와 -> 연산자[^186]

struct GameInfo* gamePtr = &game1; 후에
(*gamePtr).name처럼 역참조+점 접근이 가능하지만 괄호가 번거로워서 gamePtr->name 화살표 연산자를 쓰는 방법을 소개한다.[^186]

3.10.4 구조체 안에 구조체 포인터(연관 업체 게임) + typedef[^187]

구조체 안에 struct GameInfo* friendGame; 같은 멤버를 넣어 다른 게임 정보를 가리키게 할 수 있음을 보여준다.[^187]
typedef로 자료형 별명을 만들어 typedef struct GameInfo GameInfo;처럼 struct를 생략해 쓸 수 있게 하는 방법을 설명한다.[^188]

3.10.5 프로젝트: 고양이 수집 게임(랜덤 뽑기, 중복 가능, 5종 수집 완료 시 종료)[^189]

게임 설정: 5마리 고양이가 있고 버튼(키 입력)으로 랜덤 뽑기. 중복 가능. 5종 모두 모으면 완료.[^189]

구현:

  • typedef struct { char* name; int age; char* character; int level; } Cat; 형태로 고양이 정보를 구조체로 정의한다.[^190]
  • int collection[5]={0,0,0,0,0};는 수집 여부(0=없음, 1=보유).[^190]
  • Cat cats[5];에 고양이 5종 정보(이름/나이/성격/난이도)를 초기화 함수에서 채운다.[^191]
  • rand()%5로 0~4를 뽑아 printCat(selected)로 고양이 정보를 출력한다.[^192]
  • 레벨은 숫자 대신 별(*)을 레벨 수만큼 출력하는 방식으로 시각화한다.[^192]
  • 뽑았으면 collection[selected]=1로 보유 처리한다.[^193]
  • checkCollection()은 현재 보유 목록을 “빈박스” 또는 고양이 이름으로 출력하고, 빈박스가 하나라도 있으면 0, 모두 채웠으면 1을 반환한다.[^194]
  • 반환이 1이면 축하 메시지 출력 후 break로 종료한다.[^195]

디버깅: 처음에 프로그램이 죽는 문제를 브레이크포인트로 추적했더니, rand()*5로 곱해버려 인덱스가 이상해진 실수였고 rand()%5로 수정한다.[^193]


## 3.11 파일 입출력: fputs/fgets, fprintf/fscanf, 모드(r/w/a), 비밀번호 마스킹(getch) → 비밀일기 프로젝트[^196]

파일 입출력은 “프로그램을 껐다 켜도 데이터 유지”를 위해 필요하다고 설명한다.[^196] 메모리는 종료 시 날아가지만 파일은 남는다는 대비를 제시한다.[^196]

3.11.1 파일 쓰기: fopen 경로, 역슬래시 2개, 모드(w/r/a + t/b), fclose 습관[^197]

  • FILE* file = fopen("C:\\test1.txt", "wb"); 형태로 파일을 연다.[^197]
  • 소스코드 문자열에서 \는 이스케이프라 \\ 두 개를 써야 한다고 설명한다.[^197]
  • 모드:
    • r: 읽기, w: 쓰기(기존 내용 삭제), a: 이어쓰기
    • t: 텍스트, b: 바이너리[^197]
  • 파일 열기 실패 시 처리하고, 반드시 fclose(file)로 닫으라고 강조한다.[^198]

Visual Studio에서 fopen이 보안 경고를 내는 문제를 언급하며, 경고 무시 매크로(_CRT_SECURE_NO_WARNINGS)를 상단에 정의해 진행한다.[^199]

fputs("문장", file);로 파일에 두 줄을 쓰고, 실제 파일 열어 내용이 저장된 것을 확인한다.[^200]

3.11.2 파일 읽기: fgets로 한 줄씩 읽고 출력, 모드 오류와 w의 위험[^201]

  • fgets(line, MAX, file)로 한 줄씩 읽어오고, 널이 아닐 때 printf("%s", line)로 출력한다.[^201]
  • 처음에 모드를 wb로 둬서 읽지 못하는 실수를 수정(rb).[^202]
  • w 모드로 열면 기존 내용이 지워진다는 점을 실제로 겪고, 이어쓰려면 a를 써야 한다고 강조한다.[^203]

3.11.3 fprintf/fscanf: 포맷 기반 저장/로드(로또 예제)[^204]

로또 추천번호(6개+보너스)를 파일에 저장하고 읽어오는 예제를 만든다.[^204]

  • 저장: fprintf(file, "%s %d %d ...", "추첨번호", 1,2,3,4,5,6);fprintf(file, "%s %d", "보너스번호", 7);[^205]
  • 읽기: fscanf(file, "%s %d %d ...", str1, &num[0],..., &num[5]);
    문자열은 배열이므로 & 없이, 정수는 주소를 넘겨야 하므로 &가 필요하다는 점을 다시 확인한다.[^206]
  • 출력해 저장/로드가 일치함을 확인한다.[^207]

3.11.4 프로젝트: 비밀일기(비밀번호 확인, 기존 내용 로드, 계속 입력/저장, 마스킹)[^208]

목표:

  • 비밀번호가 맞으면 파일에서 기존 일기를 읽어 보여주고, 내용을 계속 입력받아 파일에 저장(append)한다.[^208]
  • 틀리면 경고 메시지 후 종료한다.[^208]

구현 핵심:

  1. 버퍼/문자열 선언
  • #define MAX 10000로 버퍼 크기를 정하고, char line[MAX], content[MAX]; 등 변수를 준비한다.[^209]
  1. 비밀번호 입력 마스킹
  • getch()로 키 입력을 엔터 없이 즉시 받는다( getchar()는 엔터 필요).[^210]
  • 입력 문자마다 *를 출력하고 password[i]=c; i++;로 저장한다.[^211]
  • 엔터(ASCII 13) 입력 시 문자열 끝 '\0'(널문자)를 넣어 종료한다.[^212]
  1. 비밀번호 검증
  • strcmp(password, "nadocoding") == 0이면 일치로 처리한다(강의에서는 “나도코딩”을 비밀번호로 정함).[^213]
  1. 파일 열기
  • 파일명 예: C:\\secretDiary.txt, 모드 a+b로 “없으면 생성, 있으면 뒤에 추가”를 구현한다.[^214]
  • 열기 실패 시 종료 처리.[^214]
  1. 기존 내용 출력
  • while(fgets(line, MAX, file) != NULL) printf("%s", line);로 파일 전체를 먼저 보여준다.[^215]
  1. 반복 입력/저장
  • “내용을 계속 작성, 종료는 EXIT 입력”을 안내한다.[^216]
  • scanf("%[^\n]", content);로 줄바꿈 전까지 한 줄을 통째로 입력받는다(공백 포함).[^217]
  • 남아 있는 엔터를 getchar()로 처리(버퍼 플러시)한다고 설명한다.[^218]
  • strcmp(content, "EXIT")==0이면 break로 입력 종료.[^219]
  • 아니면 fputs(content, file); fputs("\n", file);로 저장한다.[^220]
  • 마지막에 fclose(file).[^221]
  1. 비밀번호 틀리면
  • “당신 누구야 내 일기장을…” 같은 경고 메시지 출력 후 종료한다.[^222]

실행 시연:

  • 틀린 비밀번호를 넣으면 즉시 종료되는 것을 확인.[^223]
  • 맞는 비밀번호를 넣으면 별표로 마스킹되며, 새 파일이면 빈 내용에서 시작해 문장을 입력하고 EXIT로 저장 종료.[^224]
  • 프로그램을 다시 실행해 비밀번호를 맞히면 이전에 저장된 내용이 그대로 출력되고, 내용을 추가 입력하면 파일에 누적됨을 보여준다.[^225]

# 4. 핵심 통찰[^226]

  1. C 학습의 가치는 “문법 암기”가 아니라 메모리/주소/자료형을 직접 다루는 관점을 획득하는 데 있다는 전제가 강의 전반을 지배한다.[^5]
  2. 포인터는 단독 개념이 아니라 배열, scanf의 &, 함수에서 원본 수정, 구조체 포인터(->)까지 이어지는 연결된 사용 맥락으로 이해해야 한다는 흐름으로 설계되어 있다.[^196]
  3. 반복문/조건문은 “문법 설명”이 아니라 구구단·별·피라미드·업다운 같은 출력 패턴/게임 규칙을 구현하면서 자연스럽게 체득하도록 구성된다.[^51]
  4. Visual Studio에서 main 중복, fopen 보안 경고, w 모드로 내용 삭제 같은 “현업/실습에서 실제로 부딪히는 문제”를 일부러 보여주고 고치는 장면이 학습의 일부가 된다.[^38]
  5. 문자열은 널 문자, 바이트(한글 2바이트), ASCII 코드 등 저수준 표현 규칙을 이해해야 안전하게 다룰 수 있다는 점을 배열 파트에서 반복적으로 강조한다.[^110]
  6. 파일 입출력 파트는 “프로그램 종료 후에도 남는 상태”를 제공함으로써, 변수/메모리 중심 사고에서 영속성(persistence) 개념으로 확장시킨다.[^196]
  • 실행 가능한 시사점
    • C를 배울 때는 포인터를 피하지 말고, &/*/배열 전달/scanf/함수 원본 변경을 한 흐름으로 묶어 연습한다.[^140]
    • 작은 프로젝트를 반드시 만들어 “입력→상태변경→출력” 루프를 반복해보면 문법이 실제로 붙는다.[^7]
    • 파일 모드(w/a/r)의 의미(특히 w의 “기존 내용 삭제”)를 실습으로 확인하고, 파일은 항상 close하는 습관을 들인다.[^203]

# 5. 헷갈리는 용어 정리[^227]

  • 자료형(Data type): 변수에 담기는 값의 형태(정수 int, 실수 float/double, 문자 char 등).[^14]
  • 변수(Variable): 값이 바뀔 수 있는 저장 공간.[^13]
  • 상수(Constant, const): 한 번 정하면 값 변경이 불가한 값(태어난 연도 예시).[^23]
  • 주석(Comment): 컴퓨터가 실행하지 않고 무시하는 코드 메모(/* */, //).[^17]
  • 포맷 지정자(Format specifier): printf/scanf에서 자료형에 맞게 출력/입력을 지정(%d, %f, %.2f, %lf, %s, %c).[^14]
  • 포인터(Pointer): 어떤 변수의 “주소”를 저장하는 변수. &는 주소를 구하고, *는 그 주소의 값을 읽거나 바꾼다.[^127]
  • 널 문자(Null terminator, '\0'): 문자열 끝을 표시하는 문자(값 0). 문자열 배열에는 반드시 포함되어야 한다.[^107]
  • ASCII 코드: 문자에 대응되는 정수 코드(예: 'a'=97, 'A'=65, '0'=48).[^111]
  • 난수 초기화(srand): rand가 매 실행마다 다른 시퀀스를 내도록 초기값(seed)을 시간으로 설정하는 것.[^65]
  • break / continue: break는 반복문 탈출, continue는 현재 반복의 나머지 실행을 건너뛰고 다음 반복으로 이동.[^61]
  • switch-case: 값에 따라 분기하는 문. case마다 break가 없으면 아래 case가 연속 실행(fall-through)된다.[^68]
  • 구조체(struct): 관련 변수들을 하나의 타입으로 묶는 사용자 정의 자료형.[^180]
  • typedef: 자료형에 별명을 붙여 struct 같은 긴 표기를 줄이는 기능.[^188]
  • 파일 모드(r/w/a): r=읽기, w=쓰기(덮어씀), a=이어쓰기.[^197]
  • getchar vs getch: getchar는 엔터 후 입력, getch는 키 입력 즉시 처리(마스킹 구현에 사용).[^210]


참고(콘텐츠 정보)[^228]

  • 제목: C 언어 무료 강의 (입문부터 게임 개발까지)[^2]
  • 채널: 나도코딩[^2]
  • 길이: 406분 33초[^2]
  • 링크: https://www.youtube.com/watch?v=q6fPjQAzll8[^2]

[^1]: @[00:01]~@[02:57] 강의 소개, C의 위상/포인터 포기 구간/강의 목적 및 프로젝트 방식 설명.
[^2]: 사용자 제공 메타데이터(제목/채널/길이/링크) 및 @[01:47]~@[02:28] 강의 성격(게임 로직 9개, 텍스트 기반) 설명.
[^3]: 전체 강의 흐름(환경설정→변수/반복/조건/함수/배열/포인터/다차원배열/구조체/파일) 전개는 제공된 타임스탬프 구간들 전반.
[^4]: @[00:10]~@[00:53] 운전면허 비유(대형면허 vs 자동면허, 수동/차체 크기 부담).
[^5]: @[01:03] C는 기본 언어, 배우면 C++/C#/Java 쉬워지고 파이썬도 수월하다는 발언.
[^6]: @[01:14]~@[01:41] 포인터에서 좌절/포기, C가 미워지는 현상 언급.
[^7]: @[01:47]~@[02:28] 게임 만들며 배우는 강의, 9가지 게임 로직을 C로 구현(텍스트 기반).
[^8]: @[03:03]~@[04:54] Visual Studio 2019 설치/워크로드/초기 설정 안내.
[^9]: @[05:02]~@[06:22] 새 프로젝트/빈 프로젝트/소스 파일 추가/확장자 .c 사용 설명.
[^10]: @[06:31]~@[07:50] stdio.h, main, printf로 Hello World 출력 및 실행(Ctrl+F5).
[^11]: @[08:01]~@[10:15] 변수/상수/입출력 학습 목표와 “경찰서 조서 쓰기” 앱 소개.
[^12]: @[11:56]~@[12:23] 정수/실수 개념과 예시(12, 46.5).
[^13]: @[12:28]~@[13:08] 변수/상수 정의, 나이는 변한다는 예시.
[^14]: @[13:31]~@[14:52] int 변수 선언/printf %d 출력/포맷 인자 대응 설명.
[^15]: @[15:11]~@[15:58] 변수 값 변경(age=12→13) 출력 예.
[^16]: @[16:10]~@[16:19] 선언 후 재사용(두 번째부터 int 생략) 설명.
[^17]: @[16:19]~@[17:43] 블록 주석(/* /)과 라인 주석(//) 예시.
[^18]: @[18:08]~@[18:18] 주석 사용 목적(메모/설명).
[^19]: @[19:11]~@[19:55] float, 리터럴 f, %f 출력.
[^20]: @[20:00]~@[20:27] %.2f로 소수점 자리 제어.
[^21]: @[20:37]~@[21:11] double, %lf, 반올림 출력 예.
[^22]: @[21:29]~@[21:44] 상수 정의, 변경 불가, 대문자 관습 언급.
[^23]: @[22:28]~@[22:49] const로 상수 선언, 변경 시 오류(빨간 줄) 시연.
[^24]: @[23:34]~@[24:25] printf에서 연산 결과 출력(3+7=10).
[^25]: @[24:38]~@[25:15] printf 포맷 3개, 값 순서대로 대입(직접 계산식 출력).
[^26]: @[25:44]~@[26:08] 30
79, 곱셈은 * 사용 설명.
[^27]: @[26:19]~@[27:35] scanf(입력 저장), & 필요, 입력-출력 확인.
[^28]: @[27:47]~@[28:56] 정수 3개 입력받기(%d %d %d)와 출력.
[^29]: @[29:01]~@[29:47] 문자(char), %c 출력.
[^30]: @[29:54]~@[31:21] 문자열 입력(char 배열, %s), sizeof로 크기 제한, 출력.
[^31]: @[31:55]~@[35:05] 조서 작성 프로그램 입력 항목 설계와 코드 구성.
[^32]: @[33:13]~@[33:36] 나이 입력(int, scanf, &).
[^33]: @[33:36]~@[34:06] 몸무게 입력(float, %f).
[^34]: @[34:08]~@[34:35] 키 입력(double, %lf).
[^35]: @[35:15]~@[36:27] 출력 포맷(문자열/정수/실수, 소수점 2자리).
[^36]: @[36:33]~@[37:03] 실행 예(나도코딩/12/46.5/190.23/지각) 결과 확인.
[^37]: @[37:18]~@[37:35] 반복문 종류 소개(for/while/do-while).
[^38]: @[39:34]~@[40:24] main 중복 오류와 해결(기존 main 이름 변경).
[^39]: @[41:16]~@[42:07] a++ 증가 예시(10→11→12).
[^40]: @[42:20]~@[44:18] ++b와 b++ 출력 차이, 수행 순서 설명.
[^41]: @[40:39]~@[41:12] Hello World 반복 출력 문제 제기(복붙 vs 반복).
[^42]: @[45:58]~@[48:18] for문 구조(선언/조건/본문/증감/탈출) 단계 설명.
[^43]: @[48:24]~@[50:43] while문 작성, 증감 누락 위험과 결과 확인.
[^44]: @[50:49]~@[51:31] do-while 구조 및 1~10 출력 예.
[^45]: @[51:31]~@[53:55] 이중 반복문 동작 방식과 출력 확인.
[^46]: @[54:00]~@[55:55] 구구단(2~9단) 이중 for 구현 및 출력.
[^47]: @[56:20]~@[56:44] 반복문이 많은 출력문을 줄여주는 강력함 강조.
[^48]: @[56:57]~@[59:37] 별 1~5개 증가 출력 코드와 줄바꿈 필요.
[^49]: @[59:43]~@[01:05:28] i/j 변화 표로 추적하며 별 출력 과정 상세 설명.
[^50]: @[01:05:40]~@[01:08:44] 오른쪽 정렬 별(공백+별) 구현과 실행.
[^51]: @[01:08:50]~@[01:09:47] 층 입력 받고 피라미드(홀수 별) 목표 제시.
[^52]: @[01:11:29]~@[01:12:44] 별 개수 i2+1로 홀수 증가 구현.
[^53]: @[01:13:03]~@[01:13:34] 10층/40층 실행 출력 확인.
[^54]: @[01:13:40]~@[01:16:31] 조건 분기 단원 소개와 업앤다운 게임 소개/시연.
[^55]: @[01:18:08]~@[01:19:26] if/else로 학생/일반 구분 예시.
[^56]: @[01:19:38]~@[01:19:50] 한 줄 if도 가능하지만 중괄호 습관 권장.
[^57]: @[01:20:07]~@[01:22:27] else if, 나이 범위, && 조건 설명.
[^58]: @[01:22:51]~@[01:23:04] 조건 만족 시 이후 else if는 실행 안 함 설명.
[^59]: @[01:24:08]~@[01:25:09] else로 모든 케이스 커버, 학생 아닌 경우 처리.
[^60]: @[01:25:25]~@[01:28:08] break로 6번 이상에서 반복 종료(조별 발표).
[^61]: @[01:28:21]~@[01:31:18] continue로 7번 결석 처리, break와 차이 설명.
[^62]: @[01:32:04]~@[01:33:24] && 예시(a==b && c==d).
[^63]: @[01:33:46]~@[01:35:03] || 예시(a==b || c==d).
[^64]: @[01:35:16]~@[01:37:32] rand 범위(%), 0부터 시작, +1 보정 설명.
[^65]: @[01:37:39]~@[01:38:00] srand(time(NULL)) 필요성(난수 초기화).
[^66]: @[01:38:09]~@[01:40:16] 초기화 전/후 실행 시 같은 수열 vs 달라짐 비교.
[^67]: @[01:40:43]~@[01:44:11] 가위바위보 if/else 및 switch 소개.
[^68]: @[01:44:37]~@[01:46:14] switch에서 break 없으면 fall-through, break 필요 시연.
[^69]: @[01:46:41]~@[01:51:15] 나이 구분 switch-case 묶기(여러 case를 break 없이 연결).
[^70]: @[01:52:24]~@[01:53:13] 업다운 정답 rand%100+1, 정답 출력(교육용).
[^71]: @[01:53:17]~@[01:54:21] chance=5, while(chance>0), 입력 받기.
[^72]: @[01:54:23]~@[01:55:28] Up/Down/정답 처리, 정답 시 break.
[^73]: @[01:56:03]~@[01:57:30] 기회 소진 메시지, while(1) 무한루프 가능성 설명.
[^74]: @[01:57:45]~@[01:58:14] 실행 예시로 맞히기 과정 시연.
[^75]: @[01:58:29]~@[01:59:19] 함수 정의(입력→처리→출력) 설명.
[^76]: @[01:59:23]~@[02:00:21] 비밀번호 마스터 게임 시연(곱셈 문제).
[^77]: @[02:01:22]~@[02:03:43] 계산기 예제(+/-/
//)와 출력 반복 문제 제기.
[^78]: @[02:04:26]~@[02:05:02] 함수 선언을 main 위에, 정의를 main 아래에 둠 설명.
[^79]: @[02:05:22]~@[02:06:24] p(num) 호출로 출력 중복 제거.
[^80]: @[02:06:33]~@[02:07:22] 반환형/함수명/전달값 구조 설명.
[^81]: @[02:07:32]~@[02:08:27] 반환형이 int/double/char/void일 수 있음 설명.
[^82]: @[02:09:24]~@[02:10:45] 반환값 없는 함수 예시/호출/실행.
[^83]: @[02:11:06]~@[02:12:28] 반환값 있는 함수(return 10) 예시.
[^84]: @[02:12:43]~@[02:13:44] 파라미터 없는 함수 예시.
[^85]: @[02:13:49]~@[02:15:18] 파라미터 3개 함수 예시(1,2,3 / 35,27,12).
[^86]: @[02:15:35]~@[02:19:19] 파라미터+반환(사과 남은 개수) 및 printf 내부 호출.
[^87]: @[02:19:31]~@[02:22:53] add/sub/mul/div 함수 구현과 실행 결과.
[^88]: @[02:23:20]~@[02:23:44] 선언/정의 순서 규칙, 선언이 main 위면 사용 가능.
[^89]: @[02:23:48]~@[02:25:19] 비밀번호 마스터 프로젝트 설계(5문, 랜덤).
[^90]: @[02:32:30]~@[02:33:12] 틀려도 5문 모두 풀고 맞춘 개수 카운트로 변경 설명.
[^91]: @[02:28:18]~@[02:29:07] getRandomNumber(level7), +1로 0 방지.
[^92]: @[02:29:21]~@[02:30:24] showQuestion 출력 포맷과 -1 종료 안내.
[^93]: @[02:34:33]~@[02:35:01] break 대신 exit로 즉시 종료 처리 이유.
[^94]: @[02:31:46]~@[02:33:00] 정답 비교, success/fail 함수 호출, count 증가.
[^95]: @[02:34:10]~@[02:34:21] “5개 중 몇 개 맞춤” 결과 출력.
[^96]: @[02:36:09]~@[02:36:21] 반복 조건 실수(< vs <=) 디버깅.
[^97]: @[02:39:46]~@[02:41:09] 지하철 칸 비유로 배열 필요성 설명.
[^98]: @[02:41:38]~@[02:42:31] 배열 선언/인덱스 0부터/값 대입.
[^99]: @[02:43:19]~@[02:44:02] for로 배열 출력(i+1호차, subway[i]).
[^100]: @[02:44:14]~@[02:44:45] 중괄호 초기화 예.
[^101]: @[02:45:12]~@[02:45:45] 미초기화 쓰레기값(더미값) 출력 시연.
[^102]: @[02:46:39]~@[02:47:06] 일부만 초기화하면 나머지 0.
[^103]: @[02:46:06]~@[02:46:33] 배열 크기는 상수여야 함(변수 사용 시 오류).
[^104]: @[02:47:50]~@[02:48:03] 크기 생략 시 값 개수로 결정.
[^105]: @[02:48:09]~@[02:49:17] float 배열 출력, 루프 범위 초과 시 이상값.
[^106]: @[02:50:19]~@[02:51:20] char 배열로 문자열 출력 시 이상 문자 문제.
[^107]: @[02:51:30]~@[02:52:23] 널 문자 필요, 크기 +1로 해결.
[^108]: @[02:53:06]~@[02:53:59] sizeof가 널 포함 길이(7) 반환.
[^109]: @[02:54:07]~@[02:54:33] %c로 문자 하나씩 출력하면 마지막 널 확인.
[^110]: @[02:54:44]~@[02:56:44] 한글 2바이트, sizeof “나도코딩”=9 설명.
[^111]: @[03:02:55]~@[03:07:01] ASCII 정의와 a/A/0 코드값 테스트.
[^112]: @[03:07:12]~@[03:08:42] 0~127 ASCII 출력, 제어문자 소리 가능 언급.
[^113]: @[03:08:57]~@[03:22:54] 발모제 게임 전체 구현 흐름.
[^114]: @[03:10:03]~@[03:10:16] treatment = rand()%4.
[^115]: @[03:12:03]~@[03:12:19] bottle[4]={0}로 선택 표시.
[^116]: @[03:12:24]~@[03:12:49] countShowBottle = rand()%2 + 2(2 또는 3).
[^117]: @[03:11:00]~@[03:13:13] prevCountShowBottle로 연속 같은 개수 방지 장치.
[^118]: @[03:15:31]~@[03:15:53] 중복 선택 시 j--로 재시도.
[^119]: @[03:16:13]~@[03:18:36] 포함 여부(isIncluded)로 성공/실패 힌트 출력.
[^120]: @[03:18:52]~@[03:19:06] getchar로 다음 시도 진행 대기.
[^121]: @[03:19:21]~@[03:20:28] 입력 정답 비교(treatment+1).
[^122]: @[03:21:29]~@[03:22:12] prevCountShowBottle 갱신 누락 버그 수정.
[^123]: @[03:23:03]~@[03:23:24] 포인터 어렵지만 쉽게 설명하겠다고 선언.
[^124]: @[03:26:11]~@[03:27:03] 철수/영희/민수 변수와 암호 비유.
[^125]: @[03:27:53]~@[03:28:19] &로 주소 출력, 값 출력.
[^126]: @[03:28:49]~@[03:29:03] 실행마다 주소 달라짐 설명.
[^127]: @[03:29:54]~@[03:31:06] int
미션맨, 주소/암호 출력(미션맨 vs *미션맨).
[^128]: @[03:31:50]~@[03:32:50] 영희/민수로 포인터 대상 변경 시연.
[^129]: @[03:33:07]~@[03:34:36] 미션맨에 연산 적용해 값 변경.
[^130]: @[03:35:20]~@[03:38:29] 스파이 포인터, 미션맨을 가리켜 -2 수행.
[^131]: @[03:40:07]~@[03:40:47] 포인터 변수 자체의 주소 출력(&미션맨 등).
[^132]: @[03:41:05]~@[03:42:24] 배열과 포인터 연결(ptr=arr, ptr[i] 가능).
[^133]: @[03:42:45]~@[03:43:16] ptr로 값 변경하면 arr도 변경됨 시연.
[^134]: @[03:43:38]~@[03:44:22] (arr+i), (ptr+i) 표현 설명.
[^135]: @[03:45:04]~@[03:45:59] arr 값과 &arr[0] 주소 동일 출력 확인.
[^136]: @[03:48:15]~@[03:49:28] 와 & 상쇄 개념 시연.
[^137]: @[03:50:34]~@[03:52:29] swap 함수(call by value)에서 밖 값 안 바뀜.
[^138]: @[03:53:13]~@[03:53:49] 함수 밖/안 변수 주소 비교로 복사 확인.
[^139]: @[03:54:07]~@[03:56:00] 주소값 전달 swap_addr(int
), 밖 값 변경 성공.
[^140]: @[03:59:36]~@[03:59:51] scanf에서 &를 붙이는 이유 연결.
[^141]: @[03:56:54]~@[03:59:21] changeArray로 배열 요소 변경(배열=주소 전달).
[^142]: @[04:00:43]~@[04:01:29] 물고기 키우기 게임 설정 설명.
[^143]: @[04:01:38]~@[04:05:16] clock, time.h, 시간 단위 설명.
[^144]: @[04:02:09]~@[04:03:53] 레벨/어항(배열 6개) 초기화(100).
[^145]: @[04:03:53]~@[04:04:44] 포인터 커서로 어항 선택 접근 설명.
[^146]: @[04:05:34]~@[04:07:49] printFish 출력 포맷/정렬 이유 설명.
[^147]: @[04:08:37]~@[04:09:13] 입력값 범위 검증(1~6), continue.
[^148]: @[04:09:21]~@[04:09:55] 총 경과시간 계산(초 단위).
[^149]: @[04:10:06]~@[04:11:21] 최근 경과시간(직전 물 준 시간 차이) 계산.
[^150]: @[04:11:28]~@[04:13:25] decreaseWater(elapsed): level
3
elapsed 감소, 0 클램프.
[^151]: @[04:14:00]~@[04:14:51] 물이 0인 어항(죽음)에는 물 안 줌 처리.
[^152]: @[04:15:08]~@[04:16:35] 100 초과 방지 후 +1 물 주기(+= 의미).
[^153]: @[04:16:44]~@[04:19:46] 20초마다 레벨업, 레벨 5 도달 시 exit.
[^154]: @[04:20:19]~@[04:21:50] checkFishAlive: 하나라도 물>0이면 1, 아니면 종료.
[^155]: @[04:22:06]~@[04:24:25] prevElapsedTime 업데이트 필요, 10→15→25초 예시 설명.
[^156]: @[04:24:38]~@[04:26:52] 실행 시연(설명 중 시간 흘러 급감, 난이도 조정 코멘트).
[^157]: @[04:27:36]~@[04:30:53] 다차원 배열 정의(대괄호 추가).
[^158]: @[04:31:02]~@[04:33:14] 2D/3D 배열 구조/공간 수 설명.
[^159]: @[04:33:22]~@[04:35:49] 2D 인덱스 좌표 접근 개념 설명.
[^160]: @[04:39:27]~@[04:40:44] 중괄호 줄바꿈으로 3D 구조가 보임 시연.
[^161]: @[04:41:28]~@[04:43:13] 2D 배열 for 2개로 출력 예.
[^162]: @[04:43:39]~@[04:45:20] 3D 배열 for 3개로 출력, 값 변형 확인.
[^163]: @[04:46:29]~@[04:47:13] 동물 뒤집기(쌍찾기) 게임 규칙 설명.
[^164]: @[04:47:34]~@[04:48:45] animal[4][5] -1 초기화.
[^165]: @[04:49:16]~@[04:51:19] char
strAnimal[10] 동물 이름 정의.
[^166]: @[04:51:22]~@[04:54:22] shuffleAnimal: 동물 10종×2 배치 로직.
[^167]: @[04:56:31]~@[05:02:16] position→(x,y) 변환 논리(/5, %5).
[^168]: @[04:55:08]~@[04:57:55] getEmptyPosition: 랜덤 위치 선택, -1 확인 후 반환.
[^169]: @[04:58:24] 구조체로 묶어 반환할 수도 있으나 아직 안 배워서 int로 처리 언급.
[^170]: @[04:59:19]~@[05:02:16] convertPositionX/Y 설명(몫/나머지).
[^171]: @[05:10:48]~@[05:11:57] checkAnimal[4][5] (뒤집힘 여부) 개념 도입.
[^172]: @[05:05:18]~@[05:07:07] printAnimals는 디버그용 “몰래 보여줌” 출력.
[^173]: @[05:07:30]~@[05:10:40] printQuestion: 뒤집힌 건 이름, 아니면 시퀀스 번호.
[^174]: @[05:03:39]~@[05:04:01] 같은 카드 선택 무효 처리(continue).
[^175]: @[05:14:04]~@[05:17:02] 정답 조건(안 뒤집힘 && 동물 같음), bingo 출력, checkAnimal=1.
[^176]: @[05:17:17]~@[05:19:02] 오답/이미 뒤집힘 안내, 선택 카드 공개, failCount++.
[^177]: @[05:19:19]~@[05:21:55] foundAllAnimals로 종료 조건 검사, 축하/실수 횟수 출력.
[^178]: @[05:22:50]~@[05:23:16] 시퀀스 증가 누락으로 0만 출력 버그 수정.
[^179]: @[05:24:34]~@[05:24:57] 시퀀스 증가 위치 잘못 배치 버그 수정(분기 밖으로 이동).
[^180]: @[05:27:06]~@[05:27:33] 구조체 정의(관련 변수 묶기).
[^181]: @[05:32:09]~@[05:33:56] 게임 정보 변수를 따로 관리하면 복잡해짐 문제 제기.
[^182]: @[05:34:09]~@[05:35:43] struct GameInfo 선언 및 점(.) 접근으로 값 설정.
[^183]: @[05:35:55]~@[05:36:55] 구조체 출력 포맷으로 게임 출시 정보 출력.
[^184]: @[05:37:10]~@[05:38:19] 중괄호 초기화(struct 초기화).
[^185]: @[05:38:36]~@[05:39:15] 구조체 배열로 여러 게임 정보 관리.
[^186]: @[05:39:28]~@[05:43:20] 구조체 포인터, (*ptr).field vs ptr->field.
[^187]: @[05:43:24]~@[05:45:39] 구조체 내부에 구조체 포인터(friendGame)로 연관 정보 참조.
[^188]: @[05:45:53]~@[05:50:54] typedef로 별명 만들기, 주의점(태그 생략 시 struct 이름 사용 불가).
[^189]: @[05:51:42]~@[05:52:38] 고양이 수집 게임 소개(5종, 랜덤, 중복 가능).
[^190]: @[05:52:38]~@[05:54:10] Cat 구조체, collection[5] 초기화, cats[5] 배열.
[^191]: @[05:54:27]~@[05:56:45] initCats로 5마리 고양이 데이터 채움(이름/나이/성격/레벨).
[^192]: @[05:57:00]~@[06:00:28] getch 대기→랜덤 선택→printCat 출력, 레벨을 별로 시각화.
[^193]: @[06:01:07]~@[06:08:01] collection[selected]=1, rand()5 실수 디버깅 후 rand()%5 수정.
[^194]: @[06:01:31]~@[06:04:37] checkCollection: 보유 목록(빈박스/이름) 출력 + 모두 모음 여부 반환.
[^195]: @[06:05:01]~@[06:09:07] 다 모으면 축하 메시지 후 종료, 실행 시연.
[^196]: @[06:09:22]~@[06:11:59] 파일 저장의 의미(메모리 휘발 vs 파일 영속), 비밀일기 앱 소개/시연.
[^197]: @[06:14:10]~@[06:15:20] fopen 경로, \ 필요, 모드(r/w/a + t/b) 설명.
[^198]: @[06:16:31]~@[06:17:01] 파일 열면 반드시 fclose 습관 강조(데이터 손실 방지).
[^199]: @[06:17:21]~@[06:18:52] Visual Studio fopen 경고, _CRT_SECURE_NO_WARNINGS 처리.
[^200]: @[06:15:48]~@[06:19:18] fputs로 파일 쓰기, 파일 내용 확인.
[^201]: @[06:20:06]~@[06:20:47] fgets로 한 줄 읽기, line 출력.
[^202]: @[06:21:01]~@[06:21:27] 모드 wb로 읽기 실패 → rb로 수정.
[^203]: @[06:21:48]~@[06:22:18] w 모드가 파일 내용을 지움, 이어쓰기는 a.
[^204]: @[06:23:55]~@[06:24:06] 로또 번호 저장/로드 예제 소개.
[^205]: @[06:25:20]~@[06:26:14] fprintf로 추천번호/보너스번호 저장.
[^206]: @[06:27:16]~@[06:27:53] fscanf에서 문자열/정수 입력 인자(& 필요 여부) 설명.
[^207]: @[06:29:14]~@[06:29:44] 파일 읽기 출력 결과 확인(1~6, 보너스 7).
[^208]: @[06:31:00]~@[06:31:14] 비밀일기 프로젝트 요구사항 정리(비번 맞으면 편집, 틀리면 종료).
[^209]: @[06:31:44]~@[06:32:29] MAX 버퍼, line/content/password 변수 선언.
[^210]: @[06:33:30]~@[06:34:09] getch vs getchar 차이(엔터 필요 여부).
[^211]: @[06:35:06]~@[06:35:35] 입력마다 '
' 출력, password[i]=c 저장.
[^212]: @[06:34:16]~@[06:35:06] 엔터 ASCII 13 처리, 널 문자로 문자열 종료.
[^213]: @[06:36:06]~@[06:36:57] strcmp로 비밀번호 비교, 0이면 일치.
[^214]: @[06:37:18]~@[06:38:16] 파일명, a+b 모드(없으면 생성, 있으면 이어쓰기), 열기 실패 처리.
[^215]: @[06:38:41]~@[06:38:54] fgets로 기존 내용 출력.
[^216]: @[06:39:06]~@[06:39:34] “계속 작성, 종료는 EXIT” 안내.
[^217]: @[06:39:42]~@[06:40:32] scanf "%[^\n]"로 줄바꿈 전까지 입력(한 줄).
[^218]: @[06:41:04]~@[06:41:30] getchar로 엔터 플러시(버퍼 정리) 설명.
[^219]: @[06:41:37]~@[06:42:06] content가 EXIT면 입력 종료(break).
[^220]: @[06:42:10]~@[06:42:38] fputs로 내용 저장 + 줄바꿈 추가.
[^221]: @[06:42:44]~@[06:42:50] fclose로 파일 닫기.
[^222]: @[06:43:06]~@[06:43:24] 비밀번호 틀림 경고 메시지 후 종료.
[^223]: @[06:43:49]~@[06:44:02] 틀린 비밀번호 실행 시연.
[^224]: @[06:44:08]~@[06:44:41] 맞는 비밀번호 마스킹 시연, 최초 입력/저장.
[^225]: @[06:45:05]~@[06:45:46] 재실행 시 기존 내용 로드 후 추가 저장 확인.
[^226]: @[06:46:05]~@[06:46:27] 전체 10가지 강의 마무리 멘트(기초+프로젝트).
[^227]: 각 용어는 해당 파트에서 직접 정의/설명된 내용을 기반으로 정리(예: 변수/상수/포인터/파일모드 등).
[^228]: 사용자 제공 정보 및 강의 도입부 메타 설명(인프런 인기 강의, 2018 제작 등 @[01:53]~@[02:15]).

← 프로젝트에서 보기