Essential C++--Exercise of Chpt.2

Posted by GaryAC on Wed, 26 Jan 2022 21:29:39 +0100

preface

  this article is used to record reading the book Essential C + +, CHPT 2. Finish the exercises after class.

Text (Code)

2.1 Continuous Input

   the previous main() only allows the user to enter a location value, and then ends the program. If the user wants to get two or more element values, he must execute the program two or more times. Rewrite main() so that it allows the user to keep entering position values until the user wants to stop.

#include <iostream>

using namespace std;

#if 0 
// instance A from template class 
template <Class T1, Class T2> Class A
{
public:
    int a;

    int func_a(T1 a, T2 b);
}

// function func_a definition of class A from template class
template <Class T1, Class T2> int A<T1, T2>::func_a(T1 a ,T2 b)
{
    return (a + b);
}
#endif

void pr_sequence(int idx, int elem)
{
    cout << elem << (!(idx % 10) ? '\n' : ' ');
}

bool fibon_elem(int pos, int & elem)
{
    if (pos <= 0 || pos > 1024)
    {
        cout << "invalid pos[" << pos << "]" << endl;
        return false;
    }

    switch(pos)
    {
        case 2:
        {
            cout << "1 ";
        }
        case 1:
        {
            cout << "1 ";
            break;
        }
        default:
        {
            cout << "1 1 ";
            break;
        }
    }

    int n_1 = 1, n_2 = 1;

    for(int i = 3; i <= pos; i++)
    {
        elem = n_1 + n_2;
        n_1 = n_2;
        n_2 = elem;

        pr_sequence(i, elem);
    }
    cout << endl;
    
    return true;
}

bool usr_try_query(void)
{
    bool b_usr_try = false;
    char c_usr_ipt = false;
    
    cout << "try it? (Y/y: yes, N/n: no): ";
    cin >> c_usr_ipt;

    if ('Y' == c_usr_ipt || 'y' == c_usr_ipt)
    {
        b_usr_try = true;
    }
    else
    {
        b_usr_try = false;

        if ('N' != c_usr_ipt && 'n' != c_usr_ipt)
        {
            cout << "invalid input character[" << c_usr_ipt << "]" << endl;
        }
    }

    return b_usr_try;
}

int get_usr_pos(void)
{
    int i_usr_pos = 0;
    
    cout << "pls input a pos(1~1024): ";
    cin >> i_usr_pos;
    cout << endl;

    return i_usr_pos;
}

int main()
{
    int i_pos;
    int i_elem;
    
    while(usr_try_query())
    {
        i_pos = get_usr_pos();
        
        if (false == fibon_elem(i_pos, i_elem))
        {
            cout << "cal fibon elem failed!" << endl;
            continue;
        }

        cout << "get fibon elem[" << i_elem << "]" << endl;
    }

    cout << "usr exit" << endl;
    return 0;
}

2.2 List Pentagonal

   the evaluation formula of Pentagonal sequence is:
P ( n ) = n ( 3 n āˆ’ 1 ) / 2 P(n) = n(3n-1)/2 P(n)=n(3nāˆ’1)/2
   thus, element values such as 1, 5, 12, 22 and 35 are generated. Try to define a function and use the above formula to put the generated elements into the vector passed in by the user. The number of elements is specified by the user. Please check the validity of the number of elements (too large may cause overflow problems). Next, write the second function, which can print out all the elements of a given vector one by one. The second parameter of this function accepts a string indicating the type of sequence stored in the vector. Finally, write a main() to test the above two functions.

#include <iostream>
#include <vector>
#include <string>

using namespace std;

bool is_num_valid(int num)
{
    return !(num <= 0 || num > 1024);
}

int get_penta_val(int num, vector<int> &v_store)
{
    if (true != is_num_valid(num))
    {
        cout << "invalid num: " << num << endl;
        return -1;
    }

    if (num <= v_store.size())
    {
        cout << "already ok!" << endl;
        return 0;
    }

    for(int i = v_store.size()+1; i <= num; i++)
    {
        v_store.push_back(i * (3 * i - 1) / 2);
    }
    
    return 0;    
}

void pr_usr_vector(vector<int> &vec, string &type)
{
    cout << "vector type: " << type << endl;

    for(int i = 0; i < vec.size(); i++)
    {
        cout << vec.at(i) << ((9 == i % 10) ? '\n' : ' ');
    }
    cout << endl;
    
    return;
}

bool get_another_try(void)
{
    bool bTry = false;
    char cUsrIpt = 0;

    cout << "Try it? (Y/y: yes  N/n: no): ";
    cin >> cUsrIpt;

    if ('Y' == cUsrIpt || 'y' == cUsrIpt)
    {
        bTry = true;
    }
    else
    {
        bTry = false;

        if ('N' != cUsrIpt && 'n' != cUsrIpt)
        {
            cout << "invalid input[" << cUsrIpt << "]" << endl;
        }
    }
   
    return bTry;
}

int get_usr_input_num(int &num)
{
    cout << "pls input num(1~1024): ";
    cin >> num;

    if (num <= 0 || num > 1024)
    {
        cout << "invalid input num: " << num << endl;
        return -1;
    }

    cout << "get input num: " << num << endl;
    return 0;
}

int main()
{
    static vector<int> v_usr;
    int i_usr_input = 0;
    string str_type("string");

    while(get_another_try())
    {
        if (0 != get_usr_input_num(i_usr_input))
        {
            continue;
        }
        
        if (0 != get_penta_val(i_usr_input, v_usr))
        {
            cout << "update user vector failed!" << endl;
            return -1;
        }

        pr_usr_vector(v_usr, str_type);
    }

    cout << "usr exit" << endl;
    return 0;
}

2.3 Split Pentagonal List

  split the Pentagonal sequence evaluation function in exercise 2.2 into two functions, one of which is inline, to check whether the number of elements is reasonable. If it is reasonable and has not been calculated, the second function is executed to perform the actual evaluation.

#include <iostream>
#include <vector>
#include <string>

#include "2.3.h"     // header file

using namespace std;

bool is_num_valid(int num)
{
    return !(num <= 0 || num > 1024);
}

int get_penta_val(int num, vector<int> &v_store)
{
    if (true != is_num_valid(num))
    {
        cout << "invalid num: " << num << endl;
        return -1;
    }

    if (num <= v_store.size())
    {
        cout << "already ok!" << endl;
        return 0;
    }

    for(int i = v_store.size()+1; i <= num; i++)
    {
        v_store.push_back(i * (3 * i - 1) / 2);
    }
    
    return 0;    
}

void pr_usr_vector(vector<int> &vec, string &type)
{
    cout << "vector type: " << type << endl;

    for(int i = 0; i < vec.size(); i++)
    {
        cout << vec.at(i) << ((9 == i % 10) ? '\n' : ' ');
    }
    cout << endl;
    
    return;
}

bool get_another_try(void)
{
    bool bTry = false;
    char cUsrIpt = 0;

    cout << "Try it? (Y/y: yes  N/n: no): ";
    cin >> cUsrIpt;

    if ('Y' == cUsrIpt || 'y' == cUsrIpt)
    {
        bTry = true;
    }
    else
    {
        bTry = false;

        if ('N' != cUsrIpt && 'n' != cUsrIpt)
        {
            cout << "invalid input[" << cUsrIpt << "]" << endl;
        }
    }
   
    return bTry;
}

int main()
{
    static vector<int> v_usr;
    int i_usr_input = 0;
    string str_type("string");

    while(get_another_try())
    {
        if (0 != get_usr_input_num(i_usr_input))
        {
            continue;
        }
        
        if (0 != get_penta_val(i_usr_input, v_usr))
        {
            cout << "update user vector failed!" << endl;
            return -1;
        }

        pr_usr_vector(v_usr, str_type);
    }

    cout << "usr exit" << endl;
    return 0;
}

The   header file is as follows:

#ifndef _2_3_H_
#define _2_3_H_

#include <iostream>

using namespace std;

inline int get_usr_input_num(int &num)
{
    cout << "pls input num(1~1024): ";
    cin >> num;

    if (num <= 0 || num > 1024)
    {
        cout << "invalid input num: " << num << endl;
        return -1;
    }

    cout << "get input num: " << num << endl;
    return 0;
}

#endif

2.4 Split Pentagonal List_V2

   write a function to store the Pentagonal sequence elements with a local static vector. This function returns a const pointer to the vector. If the size of the vector is less than the specified number of elements, expand the size of the vector. Next, implement the second function to accept a location value and return the element at that location. Finally, write main() to test these functions.
   note: refer to subsection 2.3 for the included header files.

#include <iostream>
#include <vector>
#include <string>

#include "2.3.h"     // header file

using namespace std;

bool is_num_valid(int num)
{
    return !(num <= 0 || num > 1024);
}

const vector<int> *get_vec(int num)
{
    static vector<int> vec;
    
    if (num <= vec.size())
    {
        cout << "already ok!" << endl;
        return &vec;  
    }

    for(int i = vec.size()+1; i <= num; i++)
    {
        vec.push_back(i * (3 * i - 1) / 2);
    }
    
    return &vec;    
}

void pr_usr_vector(const vector<int> &vec, string &type)
{
    cout << "vector type: " << type << endl;

    for(int i = 0; i < vec.size(); i++)
    {
        cout << vec.at(i) << ((9 == i % 10) ? '\n' : ' ');
    }
    cout << endl;
    
    return;
}

bool get_another_try(void)
{
    bool bTry = false;
    char cUsrIpt = 0;

    cout << "Try it? (Y/y: yes  N/n: no): ";
    cin >> cUsrIpt;

    if ('Y' == cUsrIpt || 'y' == cUsrIpt)
    {
        bTry = true;
    }
    else
    {
        bTry = false;

        if ('N' != cUsrIpt && 'n' != cUsrIpt)
        {
            cout << "invalid input[" << cUsrIpt << "]" << endl;
        }
    }
   
    return bTry;
}

int main()
{
    const vector<int> *pv_usr = 0;
    int i_usr_input = 0;
    string str_type("string");

    while(get_another_try())
    {
        if (0 != get_usr_input_num(i_usr_input))
        {
            continue;
        }

        if (true != is_num_valid(i_usr_input))
        {
            cout << "invalid num: " << i_usr_input << endl;
            continue;
        }
        
        pv_usr = 0;
        if (!(pv_usr = get_vec(i_usr_input)))
        {
            cout << "update user vector failed!" << endl;
            return -1;
        }

        pr_usr_vector(*pv_usr, str_type);
    }

    cout << "usr exit" << endl;
    return 0;
}

2.5 First Meeting with Overload

   implement an overloaded max() function to accept the following parameters: (a) two integers, (b) two floating-point numbers, (c) two strings, (d) an integer vector, (f) a string vector, (g) an integer array and an integer value representing the size of the array, (h) an array of floating-point numbers and an integer value representing the size of the array, (i) An array of strings and an integer value representing the size of the array. Finally, write main() to test these functions.

#include <iostream>
#include <string>
#include <vector>

using namespace std;

int max(int a, int b)
{
    cout << "func: int + int" << endl;
    cout << "get max: " << (a < b ? b : a) << endl;
    
    return 0;
}

int max(float a, float b)
{
    cout << "func: float + float" << endl;
    cout << "get max: " << (a < b ? b : a) << endl;
    
    return 0;
}

int max(string a, string b)
{
    cout << "func: string + string" << endl;
    cout << "get max: " << (a < b ? b : a) << endl;
    
    return 0;
}

int max(vector<int> &vec)
{
    cout << "func: vector<int>" << endl;

    if (vec.empty())
    {
        cout << "vector empty!" << endl;
        return 0;
    }

    int i_max = vec.at(0);
    for(int i = 1; i < vec.size(); i++)
    {
        i_max = i_max < vec.at(i) ? vec.at(i) : i_max;
    }
    
    cout << "get max: " << i_max << endl;
    
    return 0;
}

int max(vector<float> &vec)
{
    cout << "func: vector<float>" << endl;

    if (vec.empty())
    {
        cout << "vector empty!" << endl;
        return 0;
    }

    float f_max = vec.at(0);
    for(int i = 1; i < vec.size(); i++)
    {
        f_max = f_max < vec.at(i) ? vec.at(i) : f_max;
    }
    
    cout << "get max: " << f_max << endl;
    
    return 0;
}

int max(vector<string> &vec)
{
    cout << "func: vector<string>" << endl;

    if (vec.empty())
    {
        cout << "vector empty!" << endl;
        return 0;
    }

    string str_max = vec.at(0);
    for(int i = 1; i < vec.size(); i++)
    {
        str_max = str_max < vec.at(i) ? vec.at(i) : str_max;
    }
    
    cout << "get max: " << str_max << endl;
    
    return 0;
}

int max(int (&arr)[2], int num)
{
    cout << "func: int array + int" << endl;

    if (0 == num)
    {
        cout << "array empty!" << endl;
        return 0;
    }
    
    int i_max = arr[0];
    for(int i = 1; i < num; i++)
    {
        i_max = i_max < arr[i] ? arr[i] : i_max;
    }
    
    cout << "get max: " << i_max << endl;
    
    return 0;
}

int max(float (&arr)[2], int num)
{
    cout << "func: float array + int" << endl;

    if (0 == num)
    {
        cout << "array empty!" << endl;
        return 0;
    }
    
    float f_max = arr[0];
    for(int i = 1; i < num; i++)
    {
        f_max = f_max < arr[i] ? arr[i] : f_max;
    }
    
    cout << "get max: " << f_max << endl;
    
    return 0;
}

int max(string (&arr)[2], int num)
{
    cout << "func: string array + int" << endl;

    if (0 == num)
    {
        cout << "array empty!" << endl;
        return 0;
    }
    
    string str_max = arr[0];
    for(int i = 1; i < num; i++)
    {
        str_max = str_max < arr[i] ? arr[i] : str_max;
    }
    
    cout << "get max: " << str_max << endl;
    
    return 0;
}

enum func_idx
{
    int_int,
    float_float,
    string_string,
    vec_int,
    vec_float,
    vec_string,
    arr_int,
    arr_float,
    arr_string,
};

int get_func_idx(int &idx)
{
    cout << "pls input your choice: ";
    cin >> idx;

    if (idx < int_int || idx > arr_string)
    {
        cout << "invalid input[" << idx << "]" << endl;
        return -1;
    }
    
    return 0;
}

bool try_another_one(void)
{
    char c_ipt = 0;
    bool b_try = 0;
    
    cout << "try it? (Y/y: yes  N/n: no): ";
    cin >> c_ipt;

    if ('Y' == c_ipt || 'y' == c_ipt)
    {
        b_try = true;
    }
    else
    {
        b_try = false;

        if ('N' != c_ipt && 'n' != c_ipt)
        {
            cout << "invalid input: " << c_ipt;
        }
    }
    
    return b_try;
}

int main()
{
    int idx = 0;
    while(try_another_one())
    {
        if (0 != get_func_idx(idx))
        {
            continue;
        }

        switch(idx)
        {
            case int_int:
            {
                max((int)2,(int)3);
                break;
            }
            case float_float:
            {
                max((float)2.1,(float)3.2);
                break;
            }
            case string_string:
            {
                string str1("test!");
                string str2("yeah!");

                max(str1,str2);
                break;
            }
            case vec_int:
            {
                vector<int> vec_1;

                vec_1.push_back(2);
                vec_1.push_back(3);
                
                max(vec_1);
                break;
            }
            case vec_float:
            {
                vector<float> vec_2;

                vec_2.push_back(2.1);
                vec_2.push_back(3.2);
                
                max(vec_2);
                break;
            }
            case vec_string:
            {
                vector<string> vec_3;

                vec_3.push_back("test!");
                vec_3.push_back("yeah!");
                
                max(vec_3);
                break;
            }
            case arr_int:
            {
                int arr_1[2] = {2, 3};

                max(arr_1, 2);
                break;
            }
            case arr_float:
            {
                float arr_2[2] = {2.1, 3.2};

                max(arr_2, 2);
                break;
            }
            case arr_string:
            {
                string arr_3[2] = {"test!", "yeah!"};

                max(arr_3, 2);
                break;
            }
        }
    }

	cout << "user exit!" << endl;
	
    return 0;
}

2.6 Retry with Template Function

   complete exercise 2.5 again with template and make appropriate changes to the main() function.

#include <iostream>
#include <string>
#include <vector>

using namespace std;

template <typename T>
int max(T &a, T &b)
{
	cout << "get max: " << (a < b ? b : a) << endl;  
	return 0;
}

template <typename T>
int max(vector<T> &vec)
{
    cout << "func: vector<string>" << endl;

    if (vec.empty())
    {
        cout << "vector empty!" << endl;
        return 0;
    }

    T t_max = vec.at(0);
    for(int i = 1; i < vec.size(); i++)
    {
        t_max = t_max < vec.at(i) ? vec.at(i) : t_max;
    }
    
    cout << "get max: " << t_max << endl;
    
    return 0;
}

template <typename T>
int max(T (&arr)[2], int num)
{
    cout << "func: string array + int" << endl;

    if (0 == num)
    {
        cout << "array empty!" << endl;
        return 0;
    }
    
    T t_max = arr[0];
    for(int i = 1; i < num; i++)
    {
        t_max = t_max < arr[i] ? arr[i] : t_max;
    }
    
    cout << "get max: " << t_max << endl;
    
    return 0;
}

enum func_idx
{
    int_int,
    float_float,
    string_string,
    vec_int,
    vec_float,
    vec_string,
    arr_int,
    arr_float,
    arr_string,
};

int get_func_idx(int &idx)
{
    cout << "pls input your choice: ";
    cin >> idx;

    if (idx < int_int || idx > arr_string)
    {
        cout << "invalid input[" << idx << "]" << endl;
        return -1;
    }
    
    return 0;
}

bool try_another_one(void)
{
    char c_ipt = 0;
    bool b_try = 0;
    
    cout << "try it? (Y/y: yes  N/n: no): ";
    cin >> c_ipt;

    if ('Y' == c_ipt || 'y' == c_ipt)
    {
        b_try = true;
    }
    else
    {
        b_try = false;

        if ('N' != c_ipt && 'n' != c_ipt)
        {
            cout << "invalid input: " << c_ipt;
        }
    }
    
    return b_try;
}

int main()
{
    int idx = 0;
    while(try_another_one())
    {
        if (0 != get_func_idx(idx))
        {
            continue;
        }

        switch(idx)
        {
            case int_int:
            {
				int a = 2;
				int b = 3;
                max(a,b);
                break;
            }
            case float_float:
            {
				float a_1 = 2.1;
			    float b_1 = 3.2;

                max(a_1, b_1);
                break;
            }
            case string_string:
            {
                string str1("test!");
                string str2("yeah!");

                max(str1,str2);
                break;
            }
            case vec_int:
            {
                vector<int> vec_1;

                vec_1.push_back(2);
                vec_1.push_back(3);
                
                max(vec_1);
                break;
            }
            case vec_float:
            {
                vector<float> vec_2;

                vec_2.push_back(2.1);
                vec_2.push_back(3.2);
                
                max(vec_2);
                break;
            }
            case vec_string:
            {
                vector<string> vec_3;

                vec_3.push_back("test!");
                vec_3.push_back("yeah!");
                
                max(vec_3);
                break;
            }
            case arr_int:
            {
                int arr_1[2] = {2, 3};

                max(arr_1, 2);
                break;
            }
            case arr_float:
            {
                float arr_2[2] = {2.1, 3.2};

                max(arr_2, 2);
                break;
            }
            case arr_string:
            {
                string arr_3[2] = {"test!", "yeah!"};

                max(arr_3, 2);
                break;
            }
        }
    }

	cout << "user exit!" << endl;
	
    return 0;
}

epilogue

   create this column after reading the book Essential C + +, which is used to record the exercise in the appendix after completing each chapter. If you have any questions, please don't hesitate to correct them.

Topics: C C++