C++

[C++ 기초 플러스] Chapter 07 프로그래밍 연습 풀이

(ꐦ •᷄ࡇ•᷅) 2025. 1. 8. 17:29
본 풀이는 제가 공부하면서 작성한 것이므로 정답이 아닐 수도 있습니다. 

01.

// 쌍을 이루는 두 수를 반복해서 입력할 것을 사용자에게 요구하는 프로그램
// 두 수 중 적어도 어느 하나가 0으로 입력될 때까지 입력은 계속됨

#include <iostream>
using namespace std;

float HarmonicMean(int x, int y)
{
    float a = static_cast<float>(x);
    float b = static_cast<float>(y);
    
    return 2.0f * a * b / (a + b);
}

int main()
{
    int m, n;

    cout << "[조화 평균 계산 프로그램]" << '\n';
    cout << "두 쌍의 숫자를 공백으로 구분하여 입력하세요." << '\n';
    cout << "(*둘 중 하나가 0이면 프로그램 종료*)" << '\n';
    
    while (true)
    {
        if (!(cin >> m >> n))
        {
            cout << "잘못된 입력입니다. 다시 입력하세요." << '\n';
            cout << "(*둘 중 하나가 0이면 프로그램 종료*)" << '\n';
            cin.clear();
            cin.ignore(100, '\n');
            continue;
        }
        
        if (m == 0 || n == 0) break;
        
        cout << "조화 평균: " << HarmonicMean(m, n) << '\n' << "\n";
    }
    
    return 0;
}

결과

01 - 1. cin.ignore(100, '\n')의 의미

더보기

 

  • 입력 스트림에서 최대 100개의 문자를 읽고 버린다.
  • '\n'(엔터키 입력)이 입력 스트림에서 발견되면, 읽기를 멈춘다.
  • 입력 버퍼에 남아 있는 불필요한 문자들을 제거하여, 이후 입력을 올바르게 처리할 수 있도록 한다.

입력에서 문제가 발생했을 때, 특히 cin이 잘못된 형식을 입력받았을 경우 스트림이 에러 상태가 되고, 버퍼에 남아 있는 데이터가 이후 입력에 영향을 줄 수 있다.

cin.ignore()를 사용하면 입력 버퍼를 정리하여 이런 문제를 방지할 수 있다.

 

02.

// 골프 스코어를 최대 10개까지 입력할 것을 사용자에게 요구하여 배열에 저장하는 프로그램
// 10개의 스코어를 입력하기 전이라도 사용자가 입력을 끝낼 수 있어야 함.
// 모든 스코어를 한 줄에 출력하고, 평균 스코어를 보고해야 함.
// 입력, 출력, 평균 스코어는 각각 다른 함수를 사용.

#include <iostream>
using namespace std;

int Input(float* scores);
void Output(const int* scores, int size);
float Avg(const float* scores, int size);

const int MAX_INPUT = 10;

// 입력을 받는다.
// 입력을 얼마만큼 받았는지 반환.
int Input(float* scores)
{
    cout << "골프 스코어 평균 계산 프로그램\n";
    cout << "최대 10개의 스코어를 입력하세요.\n";
    cout << "(*숫자가 아닌 문자를 누르면 입력 종료*)\n";
    int size = 0;
    for (int i = 0; i < MAX_INPUT; i++)
    {
        cout << (i + 1) << "번째 스코어 >>";

        float score;
        cin >> score;

        if (!cin) // 입력 불량
        {
            cin.clear();
            cin.ignore(100, '\n');
            cout << "입력 불량... 입력을 끝내겠습니다. \n";
            break;
        }

        scores[i] = score;
        size++;
    }

    return size;
}

void Output(const float* scores, int size)
{
    cout << "입력받은 점수들>>";
    for (int i = 0; i < size; i++)
        cout << scores[i] << " ";

    cout << '\n';
    cout << "평균 점수>> " << Avg(scores, size) << '\n';
    cout << "프로그램을 종료합니다.";
}

// 평균을 구한다.
float Avg(const float* scores, int size)
{
    float sum = 0;
    for (int i = 0; i < size; i++)
        sum += scores[i];
    
    return sum / static_cast<float>(size);
}

int main()
{
    float scores[MAX_INPUT] = {};
    int size = Input(scores);
    Output(scores, size);
    
    return 0;
}

결과

03.

// box 구조체를 값으로 전달받아, 각 멤버의 값을 출력하는 함수를 작성하라.
// box 구조체의 주소를 전달받아, volume 멤버를 다른 세 가지 멤버의 곱으로 설정하는 함수를 작성하라.
// 앞의 두 함수를 사용하는 간단한 프로그램을 작성하라.

#include <iostream>
using namespace std;

struct box
{
    char maker[40];
    float height;
    float width;
    float length;
    float volume;
};

// box 구조체를 값으로 전달받아, 각 멤버의 값을 출력하는 함수
void PrintBox(box box)
{
    cout << "box를 출력합니다.\n";
    cout << "Maker: " << box.maker << '\n';
    cout << "Height: " << box.height << '\n';
    cout << "Width: " << box.width << '\n';
    cout << "Length: " << box.length << '\n';
    cout << "Volume: " << box.volume << '\n';
    cout << '\n';
}

void SetVolume(box& box)
{
    cout << "box의 부피를 설정합니다.\n";
    cout << '\n';
    box.volume = box.height * box.width * box.length;
}

int main()
{
    box box1 = {"SS", 5.0, 5.0, 5.0, 0.0};
    PrintBox(box1);
    SetVolume(box1);
    PrintBox(box1);
    
    return 0;
}

결과

04.

// 그랑프리를 타려면 뽑아 낸 모든 수가 들어맞아야 한다.
// 승률은 범위에 속하는 모든 수를 바르게 뽑을 확률과
// 메가 수를 바르게 뽑을 확률을 곱한 것이다.
// 즉 47개의 수에서 5개의 수를 바르게 뽑을 확률과 27개의 수에서 1개의 수를 바르게 뽑을 확률을 곱한 것이다.

#include <iostream>
using namespace std;

long double probability(unsigned numbers, unsigned picks);

int main()
{
    const unsigned fieldNumbers = 47; // 전체 번호 수
    const unsigned fieldPicks = 5;   // 뽑을 번호 수
    const unsigned megaNumbers = 27; // 메가 수 전체 번호 수
    const unsigned megaPicks = 1;    // 메가 수 뽑는 수

    const long double g_probability = probability(fieldNumbers, fieldPicks) * probability(megaNumbers, megaPicks);
    
    cout << "그랑프리를 탈 수 있는 확률은\n";
    cout << 1.0 / g_probability << "입니다.\n";
    cout << "프로그램을 종료합니다.\n";
    
    return 0;
}

// 조합의 수
long double probability(unsigned numbers, unsigned picks)
{
    long double result = 1.0;
    long double n;
    unsigned p;

    for (n = numbers, p = picks; p > 0 ; n--, p--)
        result = result * n / p;
    return result;
}

결과

05.

// 팩토리얼을 재귀 함수로 구현

#include <iostream>
using namespace std;

unsigned factorial(unsigned n)
{
    if (n == 1) return 1;
    return n * factorial(n - 1);
}

int main()
{
    cout << "[팩토리얼을 구하는 프로그램]\n";
    cout << "수를 입력하세요. \n";
    cout << "**입력 불량 시 종료 \n";
    unsigned n;
    while (cin >> n)
    {
        cout << n << "의 팩토리얼 = " << factorial(n) << " 입니다.\n";
    }
    
    return 0;
}

결과

06.

// Fill_array() 함수 구현
// Show_array() 함수 구현
// Reverse_array() 함수 구현

#include <iostream>
using namespace std;

void Fill_array(double* array, int length);
void Show_array(double* array, int length);
void Reverse_array(double* array, int length);

int main()
{
    const int length = 10;
    
    cout << "배열을 채웁니다.\n";
    double array[length] = {};
    Fill_array(array, length);
    cout << '\n';
    
    Show_array(array, length);
    cout << '\n';

    cout << "배열을 뒤집습니다.\n";
    Reverse_array(array, length);
    cout << '\n';
    
    Show_array(array, length);
    cout << '\n';

    cout << "첫번째 원소와 마지막 원소를 제외하고 배열을 뒤집습니다.\n";
    Reverse_array(array + 1, length - 2);
    cout << '\n';
    
    Show_array(array, length);
    cout << '\n';

    cout << "프로그램을 종료합니다.\n";
    
    return 0;
}

void Fill_array(double* array, int length)
{
    cout << "double 형 값을 입력하세요.\n";
    cout << "문자를 입력하면 입력을 멈춥니다.\n";
    
    double n;
    for (int i = 0; i < length; i++)
    {
        if (!(cin >> n))
        {
            cin.clear();
            cin.ignore(100, '\n');
            cout << "입력 종료\n";
            break;
        }
        array[i] = n;
    }
}

void Show_array(double *array, int length)
{
    cout << "배열을 출력합니다.\n";
    for (int i = 0; i < length; i++)
        cout << array[i] << " ";
    cout << '\n';
}

// 인덱스를 증가시키면서 양 끝값을 바꾼다.
void Reverse_array(double* array, int length)
{
    double temp = 0;
    for (int i = 0; i < length / 2; i++)
    {
        temp = array[i];
        array[i] = array[length - 1 - i];
        array[length - 1 - i] = temp;
    }
}

결과

07.

// 배열 처리 함수가 범위를 나타내는 두 개의 포인터 매개변수를 사용하도록 수정.
// 실제로 입력받은 개수를 리턴하는 대신, fill_array() 함수는
// 배열에서 마지막으로 채워진 곳 바로 다음 위치를 지시하는 포인터를 리턴.
// 다른 두 함수는 이 포인터를 두 번째 매개변수로 사용하여 데이터의 끝을 판단해야 함.

#include <iostream>
const int MAX = 5;

double* fill_array(double* start, double* end);
void show_array(double* start, double* end);
void revalue(double r, double* start, double* end);

int main()
{
    using namespace std;
    double properties[MAX];

    double* end = fill_array(properties, properties + MAX);
    show_array(properties, end);
    if (end != properties)
    {
        cout << "Enter revaluation factor: ";
        double factor;
        while (!(cin >> factor))    // bad input
        {
            cin.clear();
            while (cin.get() != '\n')
                continue;
            cout << "Bad input; Please enter a number: ";
        }
        revalue(factor, properties, end);
        show_array(properties, end);
    }
    cout << "Done.\n";
    // cin.get();
    // cin.get();
    return 0;
}

double* fill_array(double* start, double* end)
{
    using namespace std;
    double temp;
    double* i;
    int count = 1;
    for (i = start; i != end; i++)
    {
        cout << "Enter value #" << count++ << ": ";
        cin >> temp;
        if (!cin)    // bad input
        {
            cin.clear();
            while (cin.get() != '\n')
                continue;
            cout << "Bad input; input process terminated.\n";
            break;
        }
        if (temp < 0)     // signal to terminate
            break;
        *i = temp;
    }
    return i;
}

void show_array(double* start, double* end)
{
    using namespace std;
    int count = 1;
    for (double* i = start; i != end; i++)
    {
        cout << "Property #" << count++ << ": $";
        cout << *i << '\n';
    }
}

void revalue(double r, double* start, double* end)
{
    for (double* i = start; i != end; i++)
        *i *= r;
}

결과

08.

// STL array를 사용하지 않고 Listing07.15 다시 구현
// 1. 계절명에 대해 const char* 배열 사용, 그리고 그 비용에 대하여 double로 array 객체 사용
// 2. 1 + double 배열 사용하며 그 배열을 단일 멤버로 가지는 구조체 사용
// 2만 할 거임.
#include <iostream>
using namespace std;

const int SEASONS = 4;
const char* seasons[SEASONS] = { "Spring", "Summer", "Fall", "Winter"};

struct Cost
{
    double costBySeason[SEASONS] = {};
};

void fill(Cost* cost)
{
    for (int i = 0; i < SEASONS; i++)
    {
        cout << seasons[i] << "에 소모되는 비용: ";
        cin >> cost->costBySeason[i];
    }
}

void show(const Cost& cost)
{
    double total = 0;
    cout << "\n계절별 비용\n";
    for (int i = 0; i < SEASONS; i++)
    {
        cout << seasons[i] << " : $" << cost.costBySeason[i] << "\n";
        total += cost.costBySeason[i];
    }

    cout << "총 비용 : $" << total << "\n";
}

int main()
{
    Cost cost;
    fill(&cost);
    show(cost);
    return 0;
}

결과

09.

// 책에 서술된 대로 구현

#include <iostream>
#include <string>
using namespace std;

const int SLEN = 30;

struct student
{
    char fullName[SLEN];
    char hobby[SLEN];
    int ooplevel;
};

// getinfo는 두 개의 매개변수를 취한다.
// 하나는 student 구조체 배열의 첫번째 원소를 지시하는 포인터
// 다른 하나는 그 배열의 원소 수를 나타내는 int 값
// 학생들과 관련된 데이터를 요구하며 배열에 저장하고 배열이 다 찼거나
// 학생 이름에 빈 줄이 입력되면 종료된다.
// 이 함수는 배열에 실제로 채워진 원소 수를 리턴한다. 
int getinfo(student pa[], int n)
{
    int size = 0;
    cout << "학생 정보를 입력하세요.\n";
    for (int i = 0; i < n; i++)
    {
        cout << "이름을 입력하세요: ";

        // 최대 SLEN-1까지 입력을 받아, 마지막에 '\0'이 자동으로 추가됨
        cin.getline(pa[i].fullName, SLEN);

        if (pa[i].fullName[0] == '\0')
        {
            cout << "입력 종료\n";
            break;
        }
        cout << "취미를 입력하세요: ";
        cin >> pa[i].hobby;

        cout << "ooplevel (int): ";
        cin >> pa[i].ooplevel;

        // 개행 문자 처리
        cin.ignore(100, '\n');
        
        size++;
    }

    return size;
}

void display1(student st)
{
    cout << "\ndisplay1";
    cout<< "\n이름: " << st.fullName << '\n';
    cout<< "취미: " << st.hobby << '\n';
    cout<< "ooplevel: " << st.ooplevel << '\n';
}

void display2(const student* ps)
{
    cout << "\ndisplay2";
    cout<< "\n이름: " << ps->fullName << '\n';
    cout<< "취미: " << ps->hobby << '\n';
    cout<< "ooplevel: " << ps->ooplevel << '\n';
}

void display3(const student pa[], int n)
{
    cout << "\ndisplay3";
    for (int i = 0; i < n; i++)
    {
        cout<< "\n이름: " << pa[i].fullName << '\n';
        cout<< "취미: " << pa[i].hobby << '\n';
        cout<< "ooplevel: " << pa[i].ooplevel << '\n';
    }
}

int main()
{
    cout << "학급의 학생 수를 입력하십시오: ";
    int classSize;
    cin >> classSize;
    cin.ignore(100, '\n');

    student* ptr_stu = new student[classSize];
    int entered = getinfo(ptr_stu, classSize);
    for (int i = 0; i < entered; i++)
    {
        display1(ptr_stu[i]);
        display2(&ptr_stu[i]);
    }

    display3(ptr_stu, entered);
    cout << "프로그램을 종료합니다. \n";
    
    return 0;
}

결과

10.

// 책에 서술된 대로 구현

#include <iostream>
#include <string>
using namespace std;

const int CAL_NUM = 4;

double calculate(double* x, double* y, double (*p)(double, double))
{
    return (*p)(*x, *y);
}

double add(double x, double y)
{
    return x + y;
}

double sub(double x, double y)
{
    return x - y;
}

double mul(double x, double y)
{
    return x * y;
}

double div(double x, double y)
{
    return x / y;
}

int main()
{
    // 함수들을 지시하는 포인터들의 배열
    double(*functions[])(double, double) = { add, sub, mul, div };

    double x = 1.9;
    double y = 2.5;
    cout << "add: " << calculate(&x, &y, functions[0]) << '\n';
    cout << "sub: " << calculate(&x, &y, functions[1]) << '\n';
    cout << "mul: " << calculate(&x, &y, functions[2]) << '\n';
    cout << "div: " << calculate(&x, &y, functions[3]) << '\n';
    
    cout << "프로그램을 종료합니다. \n";
    
    return 0;
}

 

결과