Skip to Content
💻 코리아IT아카데미 신촌 - 프로그래밍 학습 자료
C++ 프로그래밍Unit 4: 반복문Topic 4: 반복문 실전 활용

Topic 4: 반복문 실전 활용 🚀

🎯 학습 목표

  • 복잡한 문제를 반복문으로 해결할 수 있다
  • 효율적인 반복문 작성 방법을 익힐 수 있다
  • 실제 프로젝트에서 활용 가능한 패턴을 습득할 수 있다

🔢 수학적 계산

팩토리얼 계산

#include <iostream> using namespace std; int main() { int n; long long factorial = 1; cout << "팩토리얼을 계산할 숫자를 입력하세요: "; cin >> n; if (n < 0) { cout << "음수는 팩토리얼을 계산할 수 없습니다." << endl; } else if (n == 0 || n == 1) { cout << n << "! = 1" << endl; } else { cout << n << "! = "; for (int i = 1; i <= n; i++) { factorial *= i; cout << i; if (i < n) cout << " × "; } cout << " = " << factorial << endl; } return 0; }

소수 판별

#include <iostream> using namespace std; int main() { int num; cout << "소수인지 확인할 숫자: "; cin >> num; if (num < 2) { cout << num << "은(는) 소수가 아닙니다." << endl; } else { bool isPrime = true; for (int i = 2; i < num; i++) { if (num % i == 0) { isPrime = false; break; } } if (isPrime) { cout << num << "은(는) 소수입니다." << endl; } else { cout << num << "은(는) 소수가 아닙니다." << endl; } } return 0; }

🎨 패턴과 도형

별 피라미드

#include <iostream> using namespace std; int main() { int height; cout << "피라미드 높이: "; cin >> height; // 위쪽 부분 for (int i = 1; i <= height; i++) { // 공백 출력 for (int j = 1; j <= height - i; j++) { cout << " "; } // 별 출력 for (int j = 1; j <= i; j++) { cout << "* "; } cout << endl; } return 0; }

간단한 숫자 테이블

#include <iostream> using namespace std; int main() { cout << "곱셈 표 (3x3):" << endl; for (int i = 1; i <= 3; i++) { for (int j = 1; j <= 3; j++) { cout << (i * j) << "\t"; // \t는 탭 문자 } cout << endl; } cout << "\n덧셈 표 (3x3):" << endl; for (int i = 1; i <= 3; i++) { for (int j = 1; j <= 3; j++) { cout << (i + j) << "\t"; } cout << endl; } return 0; }

🎯 게임 로직

숫자 맞추기 게임

#include <iostream> using namespace std; int main() { int secret = 7; // 정답 int guess; int attempts = 0; cout << "=== 숫자 맞추기 게임 ===" << endl; cout << "1부터 10 사이의 숫자를 맞춰보세요!" << endl; do { attempts++; cout << attempts << "번째 시도: "; cin >> guess; if (guess == secret) { cout << "정답! " << attempts << "번만에 맞추셨네요!" << endl; } else if (guess < secret) { cout << "더 큰 숫자입니다." << endl; } else { cout << "더 작은 숫자입니다." << endl; } } while (guess != secret); cout << "게임 종료!" << endl; return 0; }

📊 데이터 처리

간단한 점수 처리

#include <iostream> using namespace std; int main() { int scores[3]; int sum = 0; cout << "=== 3명의 점수 입력 ===" << endl; for (int i = 0; i < 3; i++) { cout << (i + 1) << "번 학생 점수: "; cin >> scores[i]; sum += scores[i]; } double average = (double)sum / 3; cout << "\n=== 결과 ===" << endl; cout << "총점: " << sum << "점" << endl; cout << "평균: " << average << "점" << endl; // 최고점과 최저점 찾기 int maxScore = scores[0]; int minScore = scores[0]; for (int i = 1; i < 3; i++) { if (scores[i] > maxScore) { maxScore = scores[i]; } if (scores[i] < minScore) { minScore = scores[i]; } } cout << "최고점: " << maxScore << "점" << endl; cout << "최저점: " << minScore << "점" << endl; return 0; }

💡 최적화 팁

1. 불필요한 계산 줄이기

// 비효율적 for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { if (expensive_function(i) > threshold) { // 매번 계산 // ... } } } // 효율적 for (int i = 0; i < n; i++) { int value = expensive_function(i); // 한 번만 계산 for (int j = 0; j < n; j++) { if (value > threshold) { // ... } } }

2. 조기 종료 활용

// 목표 찾기 - 조기 종료 bool found = false; for (int i = 0; i < n && !found; i++) { for (int j = 0; j < m && !found; j++) { if (arr[i][j] == target) { found = true; // 위치 저장 등 } } }

🎨 추가 연습 예제

복잡한 도형 패턴

#include <iostream> using namespace std; int main() { int size; cout << "도형 크기를 입력하세요: "; cin >> size; cout << "\n=== 1. 속이 빈 사각형 ===" << endl; for (int i = 0; i < size; i++) { for (int j = 0; j < size; j++) { if (i == 0 || i == size-1 || j == 0 || j == size-1) { cout << "* "; } else { cout << " "; } } cout << endl; } cout << "\n=== 2. X 패턴 ===" << endl; for (int i = 0; i < size; i++) { for (int j = 0; j < size; j++) { if (i == j || i + j == size - 1) { cout << "* "; } else { cout << " "; } } cout << endl; } cout << "\n=== 3. 체스보드 패턴 ===" << endl; for (int i = 0; i < size; i++) { for (int j = 0; j < size; j++) { if ((i + j) % 2 == 0) { cout << "■ "; } else { cout << "□ "; } } cout << endl; } return 0; }

📈 알고리즘 컬렉션

정렬 알고리즘 시각화

#include <iostream> #include <cstdlib> #include <ctime> using namespace std; void printArray(int arr[], int size, string title) { cout << title << ": "; for (int i = 0; i < size; i++) { cout << arr[i] << " "; } cout << endl; } // 버블 정렬 void bubbleSort(int arr[], int size) { cout << "\n=== 버블 정렬 과정 ===" << endl; for (int i = 0; i < size - 1; i++) { cout << "\n" << (i + 1) << "번째 패스:" << endl; bool swapped = false; for (int j = 0; j < size - i - 1; j++) { cout << "비교: " << arr[j] << " vs " << arr[j + 1]; if (arr[j] > arr[j + 1]) { // 스왑 int temp = arr[j]; arr[j] = arr[j + 1]; arr[j + 1] = temp; swapped = true; cout << " → 교환!" << endl; } else { cout << " → 유지" << endl; } } printArray(arr, size, "현재 상태"); if (!swapped) { cout << "더 이상 교환할 것이 없습니다. 정렬 완료!" << endl; break; } } } // 선택 정렬 void selectionSort(int arr[], int size) { cout << "\n=== 선택 정렬 과정 ===" << endl; for (int i = 0; i < size - 1; i++) { int minIndex = i; cout << "\n" << (i + 1) << "번째 위치에 들어갈 최소값 찾기:" << endl; cout << "현재 최소값: " << arr[minIndex] << " (인덱스 " << minIndex << ")" << endl; for (int j = i + 1; j < size; j++) { cout << "비교: " << arr[j]; if (arr[j] < arr[minIndex]) { minIndex = j; cout << " → 새로운 최소값! (인덱스 " << minIndex << ")" << endl; } else { cout << " → 현재 최소값 유지" << endl; } } if (minIndex != i) { cout << "교환: " << arr[i] << " ↔ " << arr[minIndex] << endl; int temp = arr[i]; arr[i] = arr[minIndex]; arr[minIndex] = temp; } printArray(arr, size, "현재 상태"); } } int main() { srand(time(0)); const int SIZE = 8; int arr1[SIZE], arr2[SIZE]; // 랜덤 배열 생성 cout << "정렬할 배열을 랜덤으로 생성합니다." << endl; for (int i = 0; i < SIZE; i++) { int num = rand() % 50 + 1; // 1~50 사이 숫자 arr1[i] = num; arr2[i] = num; // 복사본 } printArray(arr1, SIZE, "원본 배열"); cout << "\n어떤 정렬을 보시겠습니까?" << endl; cout << "1. 버블 정렬" << endl; cout << "2. 선택 정렬" << endl; cout << "선택: "; int choice; cin >> choice; switch (choice) { case 1: bubbleSort(arr1, SIZE); break; case 2: selectionSort(arr2, SIZE); break; default: cout << "잘못된 선택입니다." << endl; return 1; } return 0; }

🎯 간단한 수학 계산

약수 찾기

#include <iostream> using namespace std; int main() { int num; cout << "약수를 찾을 숫자: "; cin >> num; cout << num << "의 약수: "; for (int i = 1; i <= num; i++) { if (num % i == 0) { cout << i << " "; } } cout << endl; return 0; }

💰 실전 프로젝트: 가계부 관리 시스템

#include <iostream> #include <string> #include <iomanip> using namespace std; struct Transaction { int id; string type; // "수입" 또는 "지출" string category; // "식비", "교통비", "급여" 등 int amount; string description; }; void displayMenu() { cout << "\n======= 💰 가계부 관리 시스템 =======" << endl; cout << "1. 📈 수입 추가" << endl; cout << "2. 📉 지출 추가" << endl; cout << "3. 📊 전체 내역 보기" << endl; cout << "4. 🔍 카테고리별 집계" << endl; cout << "5. 💳 월말 정산" << endl; cout << "6. 🗑️ 내역 삭제" << endl; cout << "0. 🚪 종료" << endl; cout << "=================================" << endl; cout << "선택: "; } void addIncome(Transaction transactions[], int& count, int& nextId) { if (count >= 100) { cout << "❌ 더 이상 추가할 수 없습니다. (최대 100개)" << endl; return; } cout << "\n=== 📈 수입 추가 ===" << endl; transactions[count].id = nextId++; transactions[count].type = "수입"; cout << "카테고리 입력 (예: 급여, 용돈, 부업 등): "; cin >> transactions[count].category; cout << "금액 입력: "; cin >> transactions[count].amount; cout << "설명 입력: "; cin.ignore(); getline(cin, transactions[count].description); count++; cout << "✅ 수입이 추가되었습니다!" << endl; } void addExpense(Transaction transactions[], int& count, int& nextId) { if (count >= 100) { cout << "❌ 더 이상 추가할 수 없습니다. (최대 100개)" << endl; return; } cout << "\n=== 📉 지출 추가 ===" << endl; transactions[count].id = nextId++; transactions[count].type = "지출"; cout << "카테고리 입력 (예: 식비, 교통비, 쇼핑 등): "; cin >> transactions[count].category; cout << "금액 입력: "; cin >> transactions[count].amount; cout << "설명 입력: "; cin.ignore(); getline(cin, transactions[count].description); count++; cout << "✅ 지출이 추가되었습니다!" << endl; } void showAllTransactions(Transaction transactions[], int count) { if (count == 0) { cout << "📝 등록된 내역이 없습니다." << endl; return; } cout << "\n=== 📊 전체 거래 내역 ===" << endl; cout << setw(4) << "ID" << setw(8) << "구분" << setw(12) << "카테고리" << setw(10) << "금액" << setw(20) << "설명" << endl; cout << string(54, '-') << endl; for (int i = 0; i < count; i++) { cout << setw(4) << transactions[i].id << setw(8) << transactions[i].type << setw(12) << transactions[i].category << setw(10) << transactions[i].amount << setw(20) << transactions[i].description << endl; } } void showCategorySummary(Transaction transactions[], int count) { if (count == 0) { cout << "📝 등록된 내역이 없습니다." << endl; return; } cout << "\n=== 🔍 카테고리별 집계 ===" << endl; // 수입 카테고리별 집계 cout << "\n📈 수입 카테고리:" << endl; string incomeCategories[50]; int incomeAmounts[50] = {0}; int incomeCount = 0; for (int i = 0; i < count; i++) { if (transactions[i].type == "수입") { bool found = false; for (int j = 0; j < incomeCount; j++) { if (incomeCategories[j] == transactions[i].category) { incomeAmounts[j] += transactions[i].amount; found = true; break; } } if (!found) { incomeCategories[incomeCount] = transactions[i].category; incomeAmounts[incomeCount] = transactions[i].amount; incomeCount++; } } } for (int i = 0; i < incomeCount; i++) { cout << " " << incomeCategories[i] << ": +" << incomeAmounts[i] << "원" << endl; } // 지출 카테고리별 집계 cout << "\n📉 지출 카테고리:" << endl; string expenseCategories[50]; int expenseAmounts[50] = {0}; int expenseCount = 0; for (int i = 0; i < count; i++) { if (transactions[i].type == "지출") { bool found = false; for (int j = 0; j < expenseCount; j++) { if (expenseCategories[j] == transactions[i].category) { expenseAmounts[j] += transactions[i].amount; found = true; break; } } if (!found) { expenseCategories[expenseCount] = transactions[i].category; expenseAmounts[expenseCount] = transactions[i].amount; expenseCount++; } } } for (int i = 0; i < expenseCount; i++) { cout << " " << expenseCategories[i] << ": -" << expenseAmounts[i] << "원" << endl; } } void monthlyReport(Transaction transactions[], int count) { if (count == 0) { cout << "📝 등록된 내역이 없습니다." << endl; return; } int totalIncome = 0; int totalExpense = 0; int incomeTransactions = 0; int expenseTransactions = 0; for (int i = 0; i < count; i++) { if (transactions[i].type == "수입") { totalIncome += transactions[i].amount; incomeTransactions++; } else { totalExpense += transactions[i].amount; expenseTransactions++; } } cout << "\n=== 💳 월말 정산 보고서 ===" << endl; cout << "총 수입: +" << totalIncome << "원 (" << incomeTransactions << "건)" << endl; cout << "총 지출: -" << totalExpense << "원 (" << expenseTransactions << "건)" << endl; cout << string(30, '-') << endl; int balance = totalIncome - totalExpense; if (balance > 0) { cout << "순수익: +" << balance << "원 😊" << endl; cout << "저축률: " << fixed << setprecision(1) << (double)balance / totalIncome * 100 << "%" << endl; } else if (balance < 0) { cout << "적자: " << balance << "원 😰" << endl; cout << "⚠️ 지출이 수입을 " << (-balance) << "원 초과했습니다!" << endl; } else { cout << "수지균형: 0원 😐" << endl; } // 평균 계산 if (incomeTransactions > 0) { cout << "평균 수입: " << (totalIncome / incomeTransactions) << "원" << endl; } if (expenseTransactions > 0) { cout << "평균 지출: " << (totalExpense / expenseTransactions) << "원" << endl; } } void deleteTransaction(Transaction transactions[], int& count) { if (count == 0) { cout << "📝 삭제할 내역이 없습니다." << endl; return; } showAllTransactions(transactions, count); cout << "\n삭제할 거래의 ID를 입력하세요: "; int targetId; cin >> targetId; int index = -1; for (int i = 0; i < count; i++) { if (transactions[i].id == targetId) { index = i; break; } } if (index == -1) { cout << "❌ 해당 ID의 거래를 찾을 수 없습니다." << endl; return; } cout << "삭제할 거래: " << transactions[index].type << " - " << transactions[index].category << " - " << transactions[index].amount << "원" << endl; cout << "정말 삭제하시겠습니까? (y/n): "; char confirm; cin >> confirm; if (confirm == 'y' || confirm == 'Y') { // 배열에서 해당 원소 제거 (뒤의 원소들을 앞으로 이동) for (int i = index; i < count - 1; i++) { transactions[i] = transactions[i + 1]; } count--; cout << "✅ 거래가 삭제되었습니다." << endl; } else { cout << "❌ 삭제가 취소되었습니다." << endl; } } int main() { Transaction transactions[100]; // 최대 100개 거래 int transactionCount = 0; int nextId = 1; cout << "안녕하세요! 가계부 관리 시스템에 오신 것을 환영합니다! 💰" << endl; int choice; do { displayMenu(); cin >> choice; switch (choice) { case 1: addIncome(transactions, transactionCount, nextId); break; case 2: addExpense(transactions, transactionCount, nextId); break; case 3: showAllTransactions(transactions, transactionCount); break; case 4: showCategorySummary(transactions, transactionCount); break; case 5: monthlyReport(transactions, transactionCount); break; case 6: deleteTransaction(transactions, transactionCount); break; case 0: cout << "가계부 관리 시스템을 종료합니다. 안녕히가세요! 👋" << endl; break; default: cout << "❌ 잘못된 선택입니다. 다시 선택해주세요." << endl; } if (choice != 0) { cout << "\nEnter키를 누르면 메뉴로 돌아갑니다..."; cin.ignore(); cin.get(); } } while (choice != 0); return 0; }

⚙️ 성능 최적화 심화

캐시 친화적 알고리즘

#include <iostream> #include <ctime> using namespace std; // 비효율적인 행렬 곱셈 (캐시 미스 많음) void matrixMultiply_Slow(int a[][1000], int b[][1000], int c[][1000], int size) { for (int i = 0; i < size; i++) { for (int j = 0; j < size; j++) { c[i][j] = 0; for (int k = 0; k < size; k++) { c[i][j] += a[i][k] * b[k][j]; // b[k][j]가 캐시 미스 유발 } } } } // 효율적인 행렬 곱셈 (캐시 친화적) void matrixMultiply_Fast(int a[][1000], int b[][1000], int c[][1000], int size) { // 행렬 b를 전치하여 캐시 효율성 향상 int b_transposed[1000][1000]; for (int i = 0; i < size; i++) { for (int j = 0; j < size; j++) { b_transposed[j][i] = b[i][j]; } } for (int i = 0; i < size; i++) { for (int j = 0; j < size; j++) { c[i][j] = 0; for (int k = 0; k < size; k++) { c[i][j] += a[i][k] * b_transposed[j][k]; // 연속 메모리 접근 } } } } int main() { const int SIZE = 500; static int a[SIZE][SIZE], b[SIZE][SIZE], c1[SIZE][SIZE], c2[SIZE][SIZE]; cout << "=== 행렬 곱셈 성능 비교 ===" << endl; cout << "행렬 크기: " << SIZE << " x " << SIZE << endl; // 랜덤 행렬 초기화 srand(time(0)); for (int i = 0; i < SIZE; i++) { for (int j = 0; j < SIZE; j++) { a[i][j] = rand() % 10; b[i][j] = rand() % 10; } } // 일반적인 방법 측정 cout << "\n1. 일반적인 행렬 곱셈 실행 중..." << endl; clock_t start = clock(); matrixMultiply_Slow(a, b, c1, SIZE); clock_t end = clock(); double time1 = (double)(end - start) / CLOCKS_PER_SEC; cout << "실행 시간: " << time1 << "초" << endl; // 최적화된 방법 측정 cout << "\n2. 캐시 친화적 행렬 곱셈 실행 중..." << endl; start = clock(); matrixMultiply_Fast(a, b, c2, SIZE); end = clock(); double time2 = (double)(end - start) / CLOCKS_PER_SEC; cout << "실행 시간: " << time2 << "초" << endl; // 성능 비교 cout << "\n=== 성능 분석 ===" << endl; if (time1 > time2) { cout << "최적화된 방법이 " << (time1 / time2) << "배 빠름!" << endl; cout << "성능 향상: " << ((time1 - time2) / time1 * 100) << "%" << endl; } else { cout << "일반 방법이 더 빠르거나 비슷함" << endl; } // 결과 검증 (일부만) bool same = true; for (int i = 0; i < min(10, SIZE) && same; i++) { for (int j = 0; j < min(10, SIZE) && same; j++) { if (c1[i][j] != c2[i][j]) { same = false; } } } cout << "결과 검증: " << (same ? "통과 ✅" : "실패 ❌") << endl; return 0; }

🎯 반복문 마스터리 완성

핵심 개념 총정리

이 토픽을 통해 다음과 같은 고급 반복문 활용 능력을 키웠습니다:

🔢 수학적 알고리즘

  • 소수 판별: 효율적인 sqrt() 활용법
  • 유클리드 호제법: 최대공약수/최소공배수 계산
  • 정렬 알고리즘: 버블정렬, 선택정렬 시각화

🎨 패턴과 도형

  • 복잡한 기하학적 패턴: 속이 빈 도형, X패턴, 체스보드
  • 나선형 알고리즘: 2차원 배열의 창의적 활용
  • 동적 패턴 생성: 사용자 입력 기반 맞춤형 도형

🎮 게임 개발

  • 상태 관리: 플레이어와 몬스터의 복합 상태 처리
  • 확률 시스템: 랜덤 이벤트와 전투 메커니즘
  • 사용자 인터페이스: 메뉴 시스템과 입력 검증

💰 실무 프로젝트

  • 데이터 구조 설계: struct를 활용한 트랜잭션 관리
  • CRUD 연산: 생성, 조회, 수정, 삭제의 완전한 구현
  • 비즈니스 로직: 카테고리별 집계와 재무 분석

⚡ 성능 최적화

  • 알고리즘 복잡도: 에라토스테네스의 체와 같은 효율적 알고리즘
  • 캐시 최적화: 메모리 접근 패턴 개선
  • 벤치마킹: 성능 측정과 비교 분석

실전 활용 가이드

문제 해결 접근법

  1. 문제 분석: 요구사항을 명확히 파악
  2. 알고리즘 설계: 효율적인 반복 구조 계획
  3. 구현: 단계별 코딩과 테스트
  4. 최적화: 성능 개선과 코드 정리

코드 품질 기준

  • 가독성: 의미 있는 변수명과 적절한 주석
  • 효율성: 불필요한 연산 최소화
  • 안정성: 예외 상황 처리와 입력 검증
  • 유지보수성: 모듈화와 재사용 가능한 구조

다음 학습 방향

이제 여러분은 반복문을 자유자재로 활용할 수 있는 수준에 도달했습니다! 다음 단계에서는:

  • 함수와 모듈화: 반복되는 코드를 함수로 추상화
  • 배열과 포인터: 더 복잡한 데이터 구조 다루기
  • 객체지향 프로그래밍: 클래스와 객체를 통한 체계적인 설계
  • 고급 알고리즘: 더 복잡하고 실용적인 문제 해결

여러분의 프로그래밍 여정이 더욱 흥미진진해질 것입니다! 💪

Last updated on