C++: Vector

Các khóa học qua video:
Python SQL Server PHP C# Lập trình C Java HTML5-CSS3-JavaScript
Học trên YouTube <76K/tháng. Đăng ký Hội viên
Viết nhanh hơn - Học tốt hơn
Giải phóng thời gian, khai phóng năng lực

Giới thiệu

Giống như là mảng (array), vector trong C++ là một đối tượng dùng để chứa các đối tượng khác, và các đối tượng được chứa này cũng được lưu trữ một cách liên tiếp trong vector.

Tuy nhiên, nếu như số lượng phần tử (size) của một mảng là cố định, thì ở vector, nó hoàn toàn có thể thay đổi trong suốt quá trình làm việc của chương trình

So với mảng, cách dùng của vector thì linh hoạt hơn nhiều, và đây là 1 số điểm nổi trội của vector so với mảng array:

  • Bạn không cần phải khai báo kích thước cho vector như mảng ví dụ int A[100], vector có thể tự động thay đổi kích thước.
  • Nếu bạn thêm 1 phần tử vào vector đã đầy rồi, thì vector sẽ tự động tăng kích thước của nó lên để dành chỗ cho giá trị mới này.  Vector còn có thể cho bạn biết số lượng các phần tử mà bạn đang lưu trong nó.
  • Dùng số phần tử âm vẫn được trong vector ví dụ như A[-10], A[-3], điều này rất tiện trong việc cài đặt các thuật toán khác.

Cách dùng vector

Để có thể dùng vector thì chúng ta phải khai báo header vector và thư viện std:

#include<vector>

Và để khai báo một vector ta dùng cú pháp:

vector<kiểu_dữ_liệu> tên_vector;

Chú ý kiểu của vector được để trong cặp ngoặc nhọn.

Vì kích thước của vector có thể thay đổi trong quá trình thực thi chương trình, cho nên ta không cần khai báo kích thước cho nó, hoặc nếu thích khai báo thì bạn cũng có thể khai báo theo một trong những cách như ví dụ sau:

vector<int> A(10);
vector<int> A(10, 2);

Ta cũng có thể khởi tạo cho một vector bằng giá trị của một vector khác như ví dụ sau:

vector<int> A(10,2);
vector<int> B(A);

Với dòng lệnh trên thì vector B sẽ là bản sao của vector A.

Thao tác với vector

Sau đây là một số hàm thường được dùng để thao tác với vector:

tên_vector.push_back(phần_tử);

Thêm một phần tử vào vị trí sau cùng của vector.

name_of_vector.pop_back();

Bỏ đi phần tử cuối cùng của vector.

name_of_vector.clear();

Loại bỏ tất cả các phần tử của vector.

name_of_vector.front();

Lấy phần tử đầu tiên của vector.

name_of_vector.back();

Lấy phần tử cuối cùng của vector.

name_of_vector.at(n);

Lấy phần tử vị trí thứ n của vector (từ 0).

name_of_vector.size();

Trả về số lượng phần tử của vector.

name_of_vector.empty();

Kiểm tra vector có phần tử hay không.

Duyệt vector bằng iterator

 

vector<integer>::iterator iter_name; // Khai báo con trỏ để duyệt
for (iter_name = name_of_vector.begin(); iter_name != name_of_vector.end(); iter_name++) {
  cout << *iter_name << endl;
}

Chú ý, sau khi bạn dùng áp dụng toán tử ++ vào biến iterator, nó sẽ chỉ đến phần tử tiếp theo của vector. Còn toán tử * (value of) cho biết giá trị của phần tử mà con trỏ iterator đang trỏ tới.

Ví dụ áp dụng

Ta có bài toán như ảnh dưới đây:

Ta xử lý bài toán này như sau:

#include<iostream>
#include<stdio.h>
#include<vector>
#include<string.h>
using namespace std;

Khai báo một data structure chứa thông tin khách hàng:

typedef struct customer{
  char mName[100];
  char mCusType[3]; //Loại khách hàng: CN/CT/NN
  char mProduct[100];
  int mQuantity;
  double mPrice;
}TY_Customer;

Khai báo một vector để chứa và quản lý thông tin khách hàng TY_Customer:

typedef std::vector<TY_Customer> TY_CustomerList;
TY_CustomerList vList;

Định nghĩa 4 hàm chính để thực hiện các chức năng:

  • Nhập số khách hàng
  • Thông tin khách hàng
  • Sắp xếp thông tin khách hàng
  • In ra danh sách khách hàng
int input_number_of_customers(void);
void input_customers_infor(TY_CustomerList* vList, int n);
void display_list(TY_CustomerList* vList);
void sort_customer_list(TY_CustomerList* vList);

Ta cũng định nghĩa một số hàm bổ trợ cho các hàm chính ở trên như sau:

void print_menu(void); //in menu chọn
double get_discount(char* mCusType); //lấy thông tin giảm giá
double calculate_money(TY_Customer *tmp); //tính tổng tiền của mỗi khách
void print_a_customer_info(TY_Customer *tmp); //hiển thị thông tin từng khách
bool compare(TY_Customer tmp1, TY_Customer tmp2); //phương thức so sánh đề sắp xếp
void check_valid_input(void); //kiểm tra dữ liệu đầu vào đúng hay sai

Tất nhiên ta sẽ dùng standard input/output function để nhập vào các thông tin từ bàn phím.

Bắt đầu với hàm nhập số khách hàng, vì số khách hàng là một số luôn dương nên chúng ta cần check thêm điều kiện đầu vào:

int input_number_of_customers(void){
  cout << "Please input number of customers (n>=1): \t";
  int n;
  cin >> n;

  while(!cin || n <=0) {
    // user didn't input a number
    cout << "Please input a positive numeric data! \n";
    cin.clear(); // reset failed bit
    cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); //skip bad input
    cin >> n;
  }

  return n;
}

Tiếp đến là hàm nhập thông tin khách hàng, các thông tin sẽ được đưa vào biến tạm tmp và đưa vào vector thông qua hàm push_back như sau:

Chúng ta cũng cần check các dữ liệu dạng số numeric.

void input_customers_infor(TY_CustomerList* vList, int n){
  //nhập thông tin khách hàng
  char select;
  if (!vList->empty()) {
    cout << "List is not empty. Do you want to add more data? (Y/N): ";
    cin >> select;
    if (select == 'N' || select == 'n')
    return;
  }

  TY_Customer tmp;
  for (int i = 0; i < n; i++) {
    cout << "Please input information of customer #" << i+1;
  
    cout << "\nInput customer name: ";
    cin >> tmp.mName;
    cout << "Customer name = " << tmp.mName << "\n";
  
    do {
      cout << "\nInput customer type [CN/CT/NN]: ";
      cin >> tmp.mCusType;
      //customer type must be CN, CT or NN
    } while ((strcmp(tmp.mCusType, "CN") != 0) && strcmp(tmp.mCusType, "CT") != 0 && strcmp(tmp.mCusType, "NN") != 0);
    cout << "Customer type = " << tmp.mCusType << "\n";
  
    cout << "\nInput product name: ";
    cin >> tmp.mProduct;
  
    cout << "Product = " << tmp.mProduct << "\n";
  
    // Quantity and Price must be digit data
    cout << "\nInput product quantity (Numeric): ";
    cin >> tmp.mQuantity;
  
    while(!cin) {
      // user didn't input a number
      cin.clear(); // reset failed bit
      cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); //skip bad input
      cin >> tmp.mQuantity;
    }
    cout << "Quantity = " << tmp.mQuantity << "\n";
  
    cout << "\nInput product price (Numeric): ";
    cin >> tmp.mPrice;
    while(!cin) {
      // user didn't input a number
      cin.clear(); // reset failed bit
      cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); //skip bad input
      cin >> tmp.mPrice;
    }
    cout << "Price = " << tmp.mPrice << "\n";
  
    if(!cin){
      // user didn't input a number
      cin.clear(); // reset failed bit
      cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); //skip bad input
    }
    vList->push_back(tmp);
  }
}

Có rất nhiều cách để duyệt các phần tử của một vector, ở đây chúng ta dùng cách đơn giản nhất là auto hoặc iterator:

void display_list(TY_CustomerList* vList) {
  if(vList->empty()) {
    cout << "NO RECORDS\n";
    return;
  }
  cout << "NAME\t" << "TYPE\t" << "PRODUCT\t" << "QUANTITY\t" << "PRICE\t" << "MONEY\n";
  cout << "---------------------------------------------------------------\n";

  for (auto tmp : *vList) {
    print_a_customer_info(&tmp);
  }
}

Sau đấy là hàm sắp xếp các phần tử của vector, chúng ta chỉ việc dùng sort của thư viện std:

void sort_customer_list(TY_CustomerList* vList){
  if(vList->empty()) {
    cout << "NO RECORDS\n";
    return;
  }
  cout << "Sorted customers information by DESC price\n";
  std::sort(vList->begin(), vList->end(), compare);
}

Trong đó compare là con trỏ hàm chỉ đến hàm quy định thứ tự sort do ta tự định nghĩa:

bool compare(TY_Customer tmp1, TY_Customer tmp2){
  return (tmp1.mPrice > tmp2.mPrice);
}

Sau đây là solution hoàn chỉnh cho bài toán trên:

#include<bits/stdc++.h>
#include<stdio.h>
#include<vector>
#include<string.h>

using namespace std;

// Define customer type
#define PERSIONAL_CUSTOMER "CN"
#define COMPANY_CUSTOMER "CT"
#define FOREIGNER_CUSTOMER "NN"

// Declare structure information
typedef struct customer
{
  char mName[100];
  char mCusType[3]; //Type of customer CN/CT/NN
  char mProduct[100];
  int mQuantity;
  double mPrice;
} TY_Customer;

// Declare a vector type for list of customers
typedef std::vector<TY_Customer> TY_CustomerList;

// Main functions
int input_number_of_customers(void);
void input_customers_infor(TY_CustomerList* vList, int n);
void display_list(TY_CustomerList* vList);
void sort_customer_list(TY_CustomerList* vList);

// Other supporting functions
void print_menu(void); // Print selection menu
double get_discount(char* mCusType); //Get discount information
double calculate_money(TY_Customer *tmp); //Calculate total amount of money of each customer
void print_a_customer_info(TY_Customer *tmp); //Display information of a customer
bool compare(TY_Customer tmp1, TY_Customer tmp2); // Used for vector sort
void check_valid_input(void); // Check input data is valid or not

int main(int argc, char const *argv[]){
  int select;
  static int numberOfCustomers = 0;

  char ss[2];
  // Declare a list
  //TY_Customer *cList = NULL;
  // Use vector to store customers information
  TY_CustomerList vList;

  /* CUSTOMERS MANAGERMENT PROGRAM */
  while(1){
    print_menu();
    cin >> select;

    // User input wrong data
    if(!cin){
      // user didn't input a number
      cin.clear(); // reset failbit
      cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); //skip bad input
    }

    switch (select) {
      case 1: //Input number of customer
        numberOfCustomers = input_number_of_customers();
        break;

      case 2:
        input_customers_infor(&vList, numberOfCustomers);
        break;

      case 3:
        sort_customer_list(&vList);
        break;

      case 4:
        display_list(&vList);
        break;

      case 5:
        vList.clear();
        exit (1);
        break;

      default:
        break;
    }
  }

  return 0;
}

int input_number_of_customers(void){
  cout << "Please input number of customers (n>=1): \t";
  int n;
  cin >> n;

  while(!cin || n <=0) {
    // user didn't input a number
    cout << "Please input a positive numeric data! \n";
    cin.clear(); // reset failed bit
    cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); //skip bad input
    cin >> n;
  }

  return n;
}

void input_customers_infor(TY_CustomerList* vList, int n) {
  //Input information of customers
  char select;
  if (!vList->empty()) {
    cout << "List is not empty. Do you want to add more data? (Y/N): ";
    cin >> select;
    if (select == 'N' || select == 'n')
    return;
  }

  TY_Customer tmp;
  for (int i = 0; i < n; i++) {
    cout << "Please input information of customer #" << i+1;

    cout << "\nInput customer name: ";
    cin >> tmp.mName;
    cout << "Customer name = " << tmp.mName << "\n";

    do {
      cout << "\nInput customer type [CN/CT/NN]: ";
      cin >> tmp.mCusType;
      //customer type must be CN, CT or NN
    } while ((strcmp(tmp.mCusType, "CN") != 0) && strcmp(tmp.mCusType, "CT") != 0 && strcmp(tmp.mCusType, "NN") != 0);
    cout << "Customer type = " << tmp.mCusType << "\n";

    cout << "\nInput product name: ";
    cin >> tmp.mProduct;

    cout << "Product = " << tmp.mProduct << "\n";

    // Quantity and Price must be digit data
    cout << "\nInput product quantity (Numeric): ";
    cin >> tmp.mQuantity;

    while(!cin) {
      // user didn't input a number
      cin.clear(); // reset failed bit
      cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); //skip bad input
      cin >> tmp.mQuantity;
    }
    cout << "Quantity = " << tmp.mQuantity << "\n";

    cout << "\nInput product price (Numeric): ";
    cin >> tmp.mPrice;
    while(!cin) {
      // user didn't input a number
      cin.clear(); // reset failed bit
      cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); //skip bad input
      cin >> tmp.mPrice;
    }
    cout << "Price = " << tmp.mPrice << "\n";

    if(!cin){
      // user didn't input a number
      cin.clear(); // reset failed bit
      cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); //skip bad input
    }
    vList->push_back(tmp);
  }
}

void display_list(TY_CustomerList* vList) {
  if(vList->empty()) {
    cout << "NO RECORDS\n";
    return;
  }
  cout << "NAME\t" << "TYPE\t" << "PRODUCT\t" << "QUANTITY\t" << "PRICE\t" << "MONEY\n";
  cout << "---------------------------------------------------------------\n";

  for (auto tmp : *vList) {
    print_a_customer_info(&tmp);
  }
}

void sort_customer_list(TY_CustomerList* vList) {
  if(vList->empty()) {
    cout << "NO RECORDS\n";
    return;
  }
  cout << "Sorted customers information by DESC price\n";
  std::sort(vList->begin(), vList->end(), compare);
}


/*Supporting functions definition*/
void print_menu(void) {
  cout <<"\n\t------------------------\n";
  cout <<"\tCUSTOMERS MANAGEMENT\t\n";
  cout <<"\t________________________\n";
  cout <<"\t1. Input number of customer\n";
  cout <<"\t2. Input customers information\n";
  cout <<"\t3. Sort customers information (PRICE DESC)\n";
  cout <<"\t4. Print customers information\n";
  cout <<"\t5. Exit program\n";
  cout <<"\t************************\n";
  cout <<"Please select:\n";
}

void print_a_customer_info(TY_Customer *tmp) {
  double money = calculate_money(tmp);
  cout << tmp->mName << "\t" << tmp->mCusType << "\t" << tmp->mProduct << "\t" << tmp->mQuantity << "\t" << tmp->mPrice << "\t" <<
  money << endl;
}

double get_discount(char* mCusType) {
  //Get discount of each customer type
  double discount = 0.0;
  if (strcmp(mCusType, (const char*)PERSIONAL_CUSTOMER) == 0) {
    discount = 0.8; // SaleOff 20%
  } else if (strcmp(mCusType, (const char*)COMPANY_CUSTOMER) == 0) {
    discount = 0.9; // SaleOff 10%
  } else {
    discount = 1; // SaleOff 0%
  }

  return discount;
}

double calculate_money(TY_Customer *tmp) {
  // Calculate total money of each customers
  double money = 0;
  double discount = get_discount(tmp->mCusType);
  money = tmp->mQuantity * tmp->mPrice * discount;
  //cout << "\nMoney = " << money;
  //cout << money;
  return money;
}

bool compare(TY_Customer tmp1, TY_Customer tmp2) {
  return (tmp1.mPrice > tmp2.mPrice);
}

void check_valid_input(void) {
  /*nothing*/
}

Như vậy với việc sử dụng vector thì ta có thể dễ dàng giải quyết bài toán ở trên với việc xử lý nhanh hơn rất nhiều so với sử dụng mảng, hoặc các loại danh sách liên kết khác.

» Tiếp: Thuật toán đồ thị với C++
« Trước: Sắp xếp vun đống (Heap Sort)
Các khóa học qua video:
Python SQL Server PHP C# Lập trình C Java HTML5-CSS3-JavaScript
Học trên YouTube <76K/tháng. Đăng ký Hội viên
Viết nhanh hơn - Học tốt hơn
Giải phóng thời gian, khai phóng năng lực
Copied !!!