[Experiment 2] Array, Pointer and C++ Standard Library

Keywords: C++ Back-end

Task 1 (Template Class)

#include <iostream>
using namespace std;
// Definition of Class A
class A{
public:
	A(int x0=0, int y0=0): x{x0}, y{y0} {}
	void show() const { cout << x << ", " << y << endl; }
private:
	int x, y;
};
// Definition of class B
class B{
public:
	B(double x0, double y0): x{x0}, y{y0} {}
	void show() const { cout << x << ", " << y << endl;}
private:
	double x, y;
};
int main()
{
	A a(3, 4);
	a.show();
	B b(3.2, 5.6);
	b.show();
	system("pause");
}

Looking at the code, you can see that class A and class B are the same except for the different types of data members. Class definitions are similar. Is there a mechanism to abstract the same parts from the definitions of a similar set of classes, and express the different parts in terms of changes? Class templates provide such a mechanism.

#include <iostream>
#include <string>
using namespace std;
// Define Class Template X
template <typename T>
class X
{
public:
    X(T x0, T y0) : x{x0}, y{y0} {}
    void show() const { cout << x << ", " << y << endl; }

private:
    T x, y;
};
int main()
{
    X<int> x1(3, 4);
    x1.show();
    X<double> x2(3.2, 5.6);
    x2.show();
    X<string> x3("hello", "c plus plus");
    x3.show();
    system("pause");
}

The advantage of using template classes is that they can be "specialized" into many specific classes. For example, code line23, which specializes a class template to a case where the data is a string class. Of course, there is also a precondition, provided that the code operations in the class templates are supported for these types of specialization. For example, the show() method of the code line10 class template X uses the output stream object cout and the insert operator < to output data. It must support the output operations of data of type int,doube, string. Otherwise, error messages will occur during template specialization.

Task 2 (string class)

String string in C++, strictly speaking, is not a real type, it's actually a template class basic_string The specialized form of the class. Using string = std::basic_ String<char>;

#include <iostream>
#include <string>
int main()
{
    using namespace std;
    string s1, s2;
    s1 = "nuist";                                 // assignment
    s1[0] = 'N';                                  // Supports access through [] and indexing
    cout << boolalpha << (s1 == "nuist") << endl; // string comparison
    cout << s1.length() << endl;                  // String Length
    cout << s1.size() << endl;                    // String Length
    s2 = s1 + ", 2050";                           // String Connection
    cout << s2 << endl;
    string email{"xyz@gmail.com"};
    auto pos = email.find("@"); // Finds the index position for the first occurrence of the substring'@', and returns string::npos if it fails
    if (pos == string::npos)
        cout << "illegal email address";
    else
    {
        auto s1 = email.substr(0, pos);  // Substring from index 0 ~ pos-1
        auto s2 = email.substr(pos + 1); // Substring from pos+1 to end
        cout << s1 << endl;
        cout << s2 << endl;
    }
    string phone{"15216982937"};
    cout << phone.replace(3, 5, "*****") << endl; // Replace five consecutive characters starting at index position 3 with *
    string s3{"cosmos"}, s4{"galaxy"};
    cout << "s3: " + s3 + " s4: " + s4 << endl;
    s3.swap(s4); // exchange
    cout << "s3: " + s3 + " s4: " + s4 << endl;
    string s5{"abc"};
    const char *pstr = s5.c_str(); // Method c_str() converts string class string groups into C-style strings
    cout << pstr << endl;
    string s6{"12306"};
    int x = stoi(s6); // Convert string to int
    cout << x << endl;
    system("pause");
}

#include <iostream>
#include <string>
#include <limits>
int main()
{
    using namespace std;
    string s1;
    cin >> s1; // Extracts a string from the input stream to s1, and ends when spaces, carriage returns, and tabs are encountered
    cout << "s1: " << s1 << endl;
    cin.ignore(numeric_limits<streamsize>::max(), '\n'); // Empty Input Buffer
    getline(cin, s1);                                    // Extract a line of string from the input stream to s1 until it breaks
    cout << "s1: " << s1 << endl;
    string s2, s3;
    getline(cin, s2, ' '); // Extract string from input stream to s2 until delimiter space is specified
    getline(cin, s3);
    cout << "s2: " << s2 << endl;
    cout << "s3: " << s3 << endl;
    system("pause");
}

Combining code with run results, you can see:

  1. When entering a string object, CIN >> S1 defaults to spaces, carriage returns, Tab keys, etc. It does not support cases where a string contains spaces.
  2. Using getline(cin, s1), a string containing spaces can be read in. You can also specify a delimiter to read through parameters, such as code line18.
  3. Buffers are involved in both input and output. Try to remove line12, run the program again, and observe the results. Check the literature to see which scenarios require emptying the buffer.

Use of cin.ignore()

#include <iostream>
#include <string>
int main()
{
    using namespace std;
    string s;
    // Repeat typing the string, converting lowercase characters to uppercase until you press ctrl+Z
    while (getline(cin, s))
    {
        for (auto &ch : s)
            ch = toupper(ch);
        cout << s << "\n";
    }
    system("pause");
}

  1. Code line11, using getline(cin, s) as the loop condition for while, repeats the entry until the key Ctrl+Z is pressed to end the loop.
  2. Code line14, uses the standard library function toupper() to convert lowercase characters to > uppercase characters.
  3. line13, range for, and automatic type derivation, using the reference type here. Try changing the reference type to normal type, recompile and run the program, and see if the results are different? Consider and understand different types of flexible references in encoding based on running results.
    Changing the reference type to a normal type does not change the original string.

Task 3 (vector template)

A vector is a dynamic array class template provided by the C++ standard library and can be seen as an ordered container encapsulating arrays of dynamic sizes.

  • Characteristic
    • It is safer than ordinary arrays.
    • Compared to a fixed-size array class template array, the size of the array object is variable when vector s are used to specialize into a specific type of array class. Space is allocated on demand on the heap. Support random access.
  • Application Scenarios
    • Where the number of data items cannot be determined, and data items often need to be appended or deleted at the end
#include <iostream>
#include <vector>
template <typename T>
void output(T x)
{
    for (const auto &i : x)
        std::cout << i << ", ";
    std::cout << "\b\b \n";
}

int main()
{
    using namespace std;
    vector<int> v1;                // Create a vector Object v1, no size specified, element is int, uninitialized
    vector<int> v2(5);             // Create a vector Object v2 containing five elements, which are of type int and have an initial value of 0 as the default
    vector<int> v3(5, 42);         // Creates a vector Object v3 containing five elements, which are of type int, with an initial value of 42
    vector<int> v4{9, 2, 3, 0, 1}; // Create a vector Object v4 with an int element, using the Initialize List method
    vector<int> v5{v4};            // Create a vector Object v5, created with an existing Object v4
    output(v2);
    output(v3);
    output(v4);
    output(v5);
    system("pause");
}

#include <iostream>
#include <vector>
int main()
{
    using namespace std;
    vector<int> v{1, 9, 2, 5, 6};
    // Traversal mode 1:Range for
    for (auto const &i : v)
        cout << i << ", ";
    cout << "\b\b \n";
    // Traversal Mode 2: Using Iterators
    for (auto it = v.begin(); it != v.end(); ++it)
        cout << *it << ", ";
    cout << "\b\b \n";
    // Traversal Mode 3: Using Reverse Iterator
    for (auto it = v.rbegin(); it != v.rend(); ++it)
        cout << *it << ", ";
    cout << "\b\b \n";
    system("pause");
}

This code example traverses the output of the vectorobject v in three ways, all of which use automatic type inference auto. Among them, mode 2 uses an iterator and mode 3 uses a reverse iterator. begin(), end(), rbegin(), rend() are commonly used member functions of vectors. Where:

Member functionfunction
begin()Returns an iterator pointing to the first element
end()Returns an iterator pointing to the position after the last element
rbegin()Return to last element
rend()Returns an iterator pointing to the position before the first element

It appears to be similar to a pointer, accessed indirectly by an asterisk. However, iterators are abstractions and generalizations of pointers. Although it behaves like a pointer, it is not a pointer.

#include <iostream>
#include <vector>
int main()
{
    using namespace std;
    vector<int> v1{42};
    cout << "v1.size() = " << v1.size() << endl;
    cout << "v1.capacity() = " << v1.capacity() << endl;
    v1.push_back(55); // Add a data to the tail
    v1.push_back(90);
    cout << "v1.size() = " << v1.size() << endl;
    cout << "v1.capacity() = " << v1.capacity() << endl;
    for (auto i = 0; i < 8; ++i)
        v1.push_back(i);
    cout << "v1.size() = " << v1.size() << endl;
    cout << "v1.capacity() = " << v1.capacity() << endl;
    v1.pop_back(); // Delete a data from the tail
    cout << "v1.size() = " << v1.size() << endl;
    cout << "v1.capacity() = " << v1.capacity() << endl;
    system("pause");
}

Member functionfunction
size()Returns the current number of elements
capacity()Returns the maximum number of elements that can be accommodated without space reallocation
push_back()Append element to tail
pop_back()Remove element from tail
#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
template <typename T>
void output(const T &obj)
{
    for (auto i : obj)
        std::cout << i << ", ";
    std::cout << "\b\b \n";
}

int main()
{
    using namespace std;
    vector<string> v{"music", "film"};
    v.insert(v.begin(), "literature"); // Insert element before iterator v.begin()
    output(v);
    cout << v.at(1) << endl; //Returns the element with index 1. The at() method does index crossover checking compared to v[1].
    v.erase(v.begin());      // Remove element at iterator v.begin() position
    output(v);
    v.push_back("literature");
    v.push_back("art");
    output(v);
    reverse(v.begin(), v.end()); // Flip over elements in v (reverse order)
    output(v);
    sort(v.begin(), v.end()); // Sort elements in v in ascending order
    output(v);
    system("pause");
}

Combining the code with the results of the run, you can see that in this code:

  1. Insert elements before the specified iterator position in the container using method insert(), and remove elements that specify > iterator position using method erase();
  2. reverse() in the algorithm library is used to flip data items in container object v1. Sort data items in V1 in ascending order using sort().

Task 4 (array template)

Array is a fixed-size array class template provided by the C++ standard library.

  • Characteristic
    • It is safer than ordinary arrays. At the same time, there is no deterioration in efficiency.
    • Compared to the dynamic array class template vector, the size of the array object created is fixed when array is specialized to a specific type of array class.
    • Support random access.
  • Application Scenarios
    Generally, if the number of elements is fixed, array s are safer and more efficient than vector s.
#include <iostream>
#include <array>
template <typename T>
void output(T const &obj)
{
    for (auto i : obj)
        std::cout << i << ", ";
    std::cout << "\b\b \n";
}

int main()
{
    using namespace std;
    array<int, 5> x1; // Define array object x1, containing five int elements, uninitialized
    x1.fill(42);      // Fill each element of the array object x1 with 42
    x1[0] = 999;      // Support random access through subscripts; No cross-border check
    x1.at(1) = 666;   // Support access to index through at method; For cross-border checking, an exception is reported when the index crosses the boundary
    output(x1);
    array<int, 5> x2{}; // Defines the array object x2, which contains five int elements and is initialized to zero
    output(x2);
    array<int, 5> x3{9, 2, 1, 0, 7}; // Defines the array object x3, which contains five int elements and is initialized to the specified value
    output(x3);
    system("pause");
}

  1. Use the template class array to define the method of the object. Since arrays are fixed-size array classes, you must specify type parameters and number of elements when constructing objects. Supports initialization of array object elements. For example, line16, line22, line25.
  2. Support random access, such as line10-11. Instead of checking for index boundaries in [] mode, at() method will check for index boundaries beyond which an exception will be reported.
  3. Array object elements are populated using the method fill provided by the array class template. Such as line9.
#include <iostream>
#include <array>
#include <string>
int main()
{
    using namespace std;
    array<string, 5> names{"Bob", "Alice", "Leo"};
    names.at(3) = "Bill";
    names.at(4) = "Nancy";
    for (auto it = names.begin(); it != names.end(); ++it)
        cout << *it << ", ";
    cout << "\b\b \n";
    for (auto it = names.rbegin(); it != names.rend(); ++it)
        cout << *it << ", ";
    cout << "\b\b \n";
    system("pause");
}

This code uses the at() method to access the elements of object names through an index. line14-20, uses iterators, reverse iterators, and automatic type derivation to iterate through the string array object names.

Task 5 (LIveShow)

The problem scenario is described below:
An independent musician is hosting a small free live show. livehouse is limited in capacity to accommodate up to 100 music fans. Online booking registration is now open through a platform. Online booking registration information class Info is as follows:

  • Data Members
    • Nickname
    • Contact
    • City of your residence
    • Number of scheduled attendees (n)
  • Function members
    • Constructor
      With parameters to initialize booking information (nickname, contact, city, number of scheduled attendees)
    • print()
      Print information (nickname, contact information, city, number of people scheduled to attend)
  • Write code to achieve the following requirements:
    • Designs and implements an information class Info for recording the registration audience information. The class definition is saved in the file info.hpp
    • Write the main function file task5.cpp:
    • Define a vector class object, audience_info_list, to store the audience information for online booking registration;
    • Define a const constant capacity to hold the maximum number of audiences a live house can hold
    • Enter each reservation registration information from the keyboard until it stops (press Ctrl+Z, or you can program your own other
      Stop typing) or the maximum number of scheduled attendees is reached, output audience_ Info_ All Reserved Audiences in List Object
      Interest.
    • When a user makes an appointment, prompts the user to enter q to quit when the number of scheduled attendees exceeds the remaining capacity of the livehouse site.
      Or, enter u to update the reservation information.
    • Print audience information for an appointment to a live house

ReserveInfo.cpp

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

using namespace std;

// Reservation Class
class ReserveInfo
{
private:
    string nick_name;
    string contact;
    string city;
    int reserve_num;

public:
    ReserveInfo();
    ReserveInfo(string nick_name, string contact, string city, int reserve_num);
    ~ReserveInfo();

    int get_reserve_num() const;
    void print();
};

ReserveInfo::ReserveInfo()
{
}
ReserveInfo::ReserveInfo(string nick_name, string contact, string city, int reserve_num) : nick_name(nick_name), contact(contact), city(city), reserve_num(reserve_num)
{
}

ReserveInfo::~ReserveInfo()
{
}

int ReserveInfo::get_reserve_num() const
{
    return reserve_num;
}

void ReserveInfo::print()
{
    cout << left << endl
         << setw(15) << "\n Salutation:" << setw(15) << nick_name
         << setw(15) << "\n Contact information:" << setw(15) << contact
         << setw(15) << "\n City:" << setw(15) << city
         << setw(15) << "\n Reservations:" << setw(15) << reserve_num << endl;
}

LiveShow.cpp

#include <iostream>
#include <vector>
#include <string>
#include <iomanip>
#include "ReserveInfo.cpp"
using namespace std;

// Live Performance Category
class LiveShow
{
private:
    vector<ReserveInfo> reserve_list;
    const int capasity = 100;

public:
    LiveShow();
    ~LiveShow();
    int get_capacity_remain();
    void add_reserve();
    void print();
};
LiveShow::LiveShow()
{
}
LiveShow::~LiveShow()
{
}

int LiveShow::get_capacity_remain()
{
    int capacity_remain = capasity;
    for (auto const reserve_info : reserve_list)
    {
        capacity_remain -= reserve_info.get_reserve_num();
    }
    return capacity_remain;
}
void LiveShow::add_reserve()
{
    cout << "Enter information:\n\n call/Nickname, Contact(mailbox/Cell-phone number),City, intended attendance\n";
    string str_temp;
    while (cin >> str_temp)
    {
        string nick_name;
        string contact;
        string city;
        int reserve_num;
        nick_name = str_temp;
        cin >> contact >> city >> reserve_num;
        if (reserve_num > this->get_capacity_remain())
        {
            char option;
            cout << "Dear " << nick_name << " Sorry, there are only" << this->get_capacity_remain() << "Locations."
                 << "\n1. input u,To update(update)Booking Information"
                 << "\n2. input q,Exit Reservation"
                 << "Your choice:";
            cin >> option;
            if (option == 'u')
            {
                continue;
            }
            if (option == 'q')
            {
                break;
            }
        }else{
            ReserveInfo reserveInfo(nick_name, contact, city, reserve_num);
            reserve_list.push_back(reserveInfo);
        }
    }
}

void LiveShow::print()
{
    for(auto reserve_info : reserve_list){
        cout << "So far, there are a total of " << capasity-get_capacity_remain() << " The audience is scheduled to attend. The scheduled audience information is as follows:\n";
        reserve_info.print();
    }
}

Test.cpp

#include <iostream>
#include <vector>
#include <string>
#include <iomanip>
#include "LiveShow.cpp"
int main()
{
    LiveShow liveShow_bth;
    liveShow_bth.add_reserve();
    liveShow_bth.print();
    system("pause");
}

test result

Task 6 (Encryption/Decryption)

A TextCoder class is designed and implemented for simple encryption and decryption of English text strings. Requirements are as follows

  • Data Members
    text private, used to store strings to be encrypted or decrypted (English characters only inside strings)

  • Function members
    encoder() is public for encrypting data member texts to return encrypted English text as a return value
    The encryption rules are as follows:

    Each letter is replaced with the fifth subsequent letter, that is:
    Character a is replaced with f, character b with g, character u with z, character v with a, character Z with e
    Change, and so on.
    Capital character A is replaced with capital letter F, capital character B with capital letter G, and capital character Z with capital character E.
    Characters other than letters remain unchanged.
    abcdefghijklmnopqrstuvwxyz

    decoder() is public and is used to decrypt data member texts to return the decrypted English text as a return value
    The decryption rules are as follows:

    Each alphabetic character is replaced by its fifth preceding character, that is:
    The characters f are replaced with a, g with b, a with v, B with w, and so on. (Uppercase class
    Same)
    Characters other than letters remain unchanged.

In the main program, loop in English text, use the TextCoder-like construction object to complete the encryption operation, and decrypt the encrypted text received after transmission. Until you press Ctrl+Z to terminate the program.
TextCoder.cpp

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

using namespace std;

class TextCoder
{
private:
    string text;

public:
    TextCoder();
    TextCoder(string text);
    ~TextCoder();

    void set_text(string text);
    string get_text();
    string encoder();
    string decoder();
};

TextCoder::TextCoder()
{
}
TextCoder::TextCoder(string text) : text(text)
{
}

TextCoder::~TextCoder()
{
}

void TextCoder::set_text(string text)
{
    this->text = text;
}

string TextCoder::get_text()
{
    return text;
}

string TextCoder::decoder()
{
    string text_decoded = text;
    for (int i = 0; i < text_decoded.length(); i++)
    {
        if (text_decoded[i] >= 65 && text_decoded[i] <= 90)
        {
            text_decoded[i] = 90 - (90-text_decoded[i] + 5)%26;
        }else if(text_decoded[i] >= 97 && text_decoded[i] <= 122){
            text_decoded[i] = 122 - (122-text_decoded[i] + 5)%26;
        }    
    }
    return text_decoded;
}

string TextCoder::encoder()
{
    string text_encoded = text;
    for (int i = 0; i < text_encoded.length(); i++)
    {
        if (text_encoded[i] >= 65 && text_encoded[i] <= 90)
        {
            text_encoded[i] = (text_encoded[i]-65 + 5)%26 + 65;
        }else if(text_encoded[i] >= 97 && text_encoded[i] <= 122){
            text_encoded[i] = (text_encoded[i]-97 + 5)%26 + 97;
        }    
    }
    return text_encoded;
}

Test.cpp

#include "TextCoder.cpp"
#include <iostream>
#include <string>
int main()
{
    using namespace std;
    string text, encoded_text, decoded_text;
    cout << "Enter English text: ";
    while (getline(cin, text))
    {
        encoded_text = TextCoder(text).encoder(); // Temporary anonymous object used here
        cout << "Encrypted English text:\t" << encoded_text << endl;
        decoded_text = TextCoder(encoded_text).decoder(); // Temporary anonymous object used here
        cout << "Decrypted English Text:\t" << decoded_text << endl;
        cout << "\n Enter English text: ";
        system("pause");
    }
}

Test results:

Posted by intodesi on Wed, 27 Oct 2021 09:35:50 -0700