C/C++ Basic Skills-Common Written Exam Questions

      As the saying goes, if the foundation is unstable, the earth will shake. As a C/C++ developer, the solidity of basic skills determines the height of the career. This article organizes common C/C++ written test questions.

Table of contents

1.STL

1.1 The difference between push_back and emplace_back in vector

1.2 vector clears memory

1.3 std::array

2. Sort

2.1 Bubble sort

2.2 Quick sort

2.3 Heap sort

3.Memory

3.1 Implement memset function

4. Linked list

2.1 Bubble sort

2.2 Reverse order

2.2 Merge

(1) Modify the merge of the original linked list

(2) Merge without modifying the original linked list

5.Caching

5.1 Least recently used (LRU)

6. String

6.1 Point-by-point ipv4 address formatting

6.2 String splitting

6.3 Find the longest repeating substring

7.IO stream

7.1 String and file IO streams

7.2 Clear unwanted buffers

8.VC++

8.1 Mutex and critical sections


1.STL

1.1 The difference between push_back and emplace_back in vector

        The emplace_back() function is newly added in C++11. Its function is the same as push_back(). emplace_back can directly construct container elements through parameters, eliminating the need for a copy construction call.

#include<iostream>
#include <vector>
#include <string.h>

using namespace std;

// emplace_back() 函数是 C++11 新增加的,其功能和 push_back()相同, emplace_back可以直接通过参数构建
//容器元素,省去了一次拷贝构造的调
class ItemData
{
public:
    // 无参数构造函数
    ItemData() : m_iData(0), m_strData("")
    { 
        std::cout << "call ItemData() " << this << std::endl;
    }

    //带参数构造函数
    ItemData(int id, std::string strData) : m_iData(id), m_strData(strData)
    { 
        std::cout << "call ItemData(int id, std::string strData) " << this << std::endl;
    }
    //拷贝构造
    ItemData(const ItemData &t) : m_iData(t.m_iData), m_strData(t.m_strData)
    {  
        std::cout << "call ItemData(const ItemData &t) " << this << std::endl;
    }
    //移动构造
    ItemData(const ItemData &&t)
    {
        m_iData = std::move(t.m_iData);
        m_strData = std::move(t.m_strData);
        std::cout << "call ItemData(const ItemData &&t) " << this << std::endl;
    }
    //析构
    ~ItemData()
    {
        std::cout << "call ~ItemData() " << this << std::endl;
    }

private:
    int         m_iData; 
    std::string m_strData;
};

void test1() {
    std::cout << "----------------------- test1() ---------------------------" << std::endl;

    vector<ItemData> vec;
    vec.reserve(10);
    std::cout << "------ push_back --------" << std::endl;
    vec.push_back(ItemData(111, "hello"));
    std::cout << "------ emplace_back --------" << std::endl;
    vec.emplace_back(ItemData(222, "world"));
    std::cout << "-------- finish -------- " << std::endl;
}

void test2() {
    std::cout << "------------------------ test2() --------------------------" << std::endl;

    vector<ItemData> vec;
    vec.reserve(10);
    std::cout << "------ push_back --------" << std::endl;
    vec.push_back(ItemData(333, "stl"));
    std::cout << "------ emplace_back --------" << std::endl;
    vec.emplace_back(444, "vector");
    std::cout << "-------- finish -------- " << std::endl;
}

void vector_test() {
    test1();
    std::cout << std::endl << std::endl;
    test2();
}

int main() {

    vector_test();

    return 0;
}

1.2 vector clears memory

#include <iostream>
#include <vector>

using namespace std;

// 方法一:std::vector<int>().swap
void empty1(std::vector<int> &iVec) {
    std::vector<int>().swap(iVec);
}

// 方法二:clear() + shrink_to_fit()
void empty2(std::vector<int> &iVec) {
    iVec.clear();
    iVec.shrink_to_fit();
}

// 方法三:std::move语义转移清空
void empty3(std::vector<int> &iVec) {
    auto data = std::move(iVec);
}

// C++11增加接口shrink_to_fit()删除不存储数据的多余内存

void test1() {
     std::vector<int> iVec;
    iVec.push_back(111);
    iVec.push_back(222);
    iVec.push_back(333);
    iVec.push_back(444);
    iVec.push_back(555);

    std::cout << iVec.size() << " " << iVec.capacity() << std::endl;
    empty1(iVec);
    std::cout << iVec.size() << " " << iVec.capacity() << std::endl;
}

void test2() {
     std::vector<int> iVec;
    iVec.push_back(111);
    iVec.push_back(222);
    iVec.push_back(333);
    iVec.push_back(444);
    iVec.push_back(555);

    std::cout << iVec.size() << " " << iVec.capacity() << std::endl;
    empty2(iVec);
    std::cout << iVec.size() << " " << iVec.capacity() << std::endl;
}

void test3() {
     std::vector<int> iVec;
    iVec.push_back(111);
    iVec.push_back(222);
    iVec.push_back(333);
    iVec.push_back(444);
    iVec.push_back(555);

    std::cout << iVec.size() << " " << iVec.capacity() << std::endl;
    empty3(iVec);
    std::cout << iVec.size() << " " << iVec.capacity() << std::endl;
}

int main(int argc, char *argv[])
{
    test1();
    test2();
    test3();

    return 0; 
}

1.3 std::array

std::array allocates memory on the stack

#include <iostream>
#include <array>

using namespace std;

void test_array() {
    std::array<int, 5> arr = { 1, 2, 3, 4, 5 };
    std::cout << arr.size() << std::endl;

    for (const auto & item : arr) {
        std::cout << item << std::endl;
    }
}

int main() {
    test_array();

    return 0;
}

2. Sort

2.1 Bubble sort

#include<iostream>

using namespace std;

void show_arr(int arr[], int iLen) {
    for (int i = 0; i < iLen; i++) {
        std::cout << arr[i] << " ";
    }
    std::cout << std::endl;
}

void bubbling_sort(int arr[], int iLen) {
    int iTemp = 0;
     for (int i = 0; i < iLen - 1; i++) {
        for (int j = i + 1; j < iLen; j++) {
            if (arr[i] > arr[j]) {
                iTemp = arr[i];
                arr[i] = arr[j];
                arr[j] = iTemp;
            }
        }
    }
} 

void test_bubbling_sort() {
    int arr[10] = {90, 18, 3, 56, 32, 45, 23, 21, 9, 51};
    int iLen = sizeof(arr) / sizeof(arr[0]);
    std::cout << "before sort:: ";
    show_arr(arr, iLen);
    bubbling_sort(arr, iLen);
    std::cout << "afort sort:: ";
    show_arr(arr, iLen);
}

int main() {

    test_bubbling_sort();

    return 0;
}

2.2 Quick sort

#include <iostream>
#include <vector>
#include <unistd.h>

using namespace std;

void show_arr(int arr[], int iLen) {
    for (int i = 0; i < iLen; i++) {
        std::cout << arr[i] << " ";
    }
    std::cout << std::endl;
}

void swap(int& a, int& b) {
    int iTmp = a;
    a = b;
    b = iTmp;
}

void quick_sort(int iArr[], int iLow, int iHigh) {
    if (iLow >= iHigh) {
        return;
    }
    int iKey = 0;
    iKey = iArr[iLow];
    int i = iLow;
    int j = iHigh;
    while (i < j) {
        while (iArr[i] <= iKey && i < iHigh) {
            i++;
        }
        while (iArr[j] >= iKey && j > iLow) {
            j--;
        }
        if (i >= j) {
            break;
        }

        swap(iArr[i], iArr[j]);
        
    }
    
    swap(iArr[iLow], iArr[j]);

    //show_arr(iArr, 10);

    quick_sort(iArr, iLow, j - 1);
    quick_sort(iArr, j + 1, iHigh);
}



void test_quick_sort() {
    int arr[10] = {90, 18, 3, 56, 32, 45, 23, 21, 9, 51};
    int iLen = sizeof(arr) / sizeof(arr[0]);
    std::cout << "before sort:: ";
    show_arr(arr, iLen);
    quick_sort(arr, 0, iLen - 1);
    std::cout << "afort sort:: ";
    show_arr(arr, iLen);
}

int main(int argc, char *argv[])
{
    test_quick_sort();
    return 0; 
}

2.3 Heap sort

#include <iostream>
#include <vector>
#include <unistd.h>

using namespace std;

void show_arr(int arr[], int iLen) {
    for (int i = 0; i < iLen; i++) {
        std::cout << arr[i] << " ";
    }
    std::cout << std::endl;
}

void swap(int& a, int& b) {
    int iTmp = a;
    a = b;
    b = iTmp;
}

void build_max_heap(int iArr[], int n) {
    if (n < 2) {
        return;
    }

    //计算开始堆构建位置
    int i = n / 2 - 1;
    int left = 0;
    int right = 0;
    int iMax = 0;
    while (i >= 0) {
        left = 2 * i + 1;
        right = 2 * i + 2;
        iMax = iArr[left];
        //有右子树时
        if (right < n) {
            if (iArr[right] > iArr[left] ) {
                iMax = iArr[right];
            }
        }
        if (iMax > iArr[i]) {
            // 左子树大时父节点和左节点交换
            if (iMax == iArr[left]) {
                swap(iArr[i], iArr[left]);
            }
            else {// 右子树大时父节点和右节点交换
                swap(iArr[i], iArr[right]);
            }
        }
        i--;
    }
}

// 从小到大排序,先构建大根堆,然后用第一个和最后一个交换, 最后一个就是最大值,跳过最后一个继续构建大根堆
// 然后用第一个和倒数第二个交换,倒数第二个就是第二大,跳过最后两个继续构建大根堆
void heap_sort(int iArr[], int iLen) {
    if (!iArr || iLen < 0) {
        return;
    }

    for (int i = iLen; i >= 1; i--) {
        build_max_heap(iArr, i);
        swap(iArr[0], iArr[i - 1]);
        
    }
}

void test_heap_sort() {
    int arr[10] = {90, 18, 3, 56, 32, 45, 23, 21, 9, 51};
    int iLen = sizeof(arr) / sizeof(arr[0]);
    std::cout << "before sort:: ";
    show_arr(arr, iLen);
    heap_sort(arr, iLen);
    std::cout << "afort sort:: ";
    show_arr(arr, iLen);
}

int main(int argc, char *argv[])
{
    test_heap_sort();
    return 0; 
}

3.Memory

3.1 Implement memset function

#include<iostream>

using namespace std;

void* my_memcpy(void* pDest, void* pSrc, unsigned int iCount) {
    if (!pDest || !pSrc) {
        return NULL;
    }
    char *pD = (char*)pDest;
    char *pS = (char*)pSrc;
    if (pD <= pS || pD >= (pS + iCount)) {
        while (iCount--) {
            *pD++ = *pS++;
        }
    }
    else { //内存重叠处理
        pD = (char*)pDest + iCount - 1;
        pS = (char*)pSrc + iCount - 1;
        while (iCount--) {
            *pD-- = *pS--;
        }
    }
    return pDest;
}


int main() {

    char tmpBuf[128] = "111111222222333333444444";
    char destBuf[128] = {0};

    std::cout << "1 " << (char*)my_memcpy(destBuf, tmpBuf, 10) << std::endl;
    std::cout << "2 " << destBuf << std::endl;
    std::cout << "3 " << (char*)my_memcpy(tmpBuf + 5, tmpBuf, 10) << std::endl;
    std::cout << "4 " << tmpBuf << std::endl;


    return 0;
}

4. Linked list

2.1 Bubble sort

#include<iostream>

using namespace std;

struct Node {
    int data;
    Node* pNext;
};

//构建链表
void build_list(Node*& pHead) {
    pHead = new Node;
    pHead->data = 90;
    Node* pNode1 = new Node;
    pNode1->data = 18;
    pHead->pNext = pNode1;
    Node* pNode2 = new Node;
    pNode2->data = 3;
    pNode1->pNext = pNode2;
    Node* pNode3 = new Node;
    pNode3->data = 56;
    pNode2->pNext = pNode3;
    Node* pNode4 = new Node;
    pNode4->data = 32;
    pNode3->pNext = pNode4;
    Node* pNode5 = new Node;
    pNode5->data = 45;
    pNode4->pNext = pNode5;
    Node* pNode6 = new Node;
    pNode6->data = 23;
    pNode5->pNext = pNode6;
    Node* pNode7 = new Node;
    pNode7->data = 21;
    pNode6->pNext = pNode7;
    Node* pNode8 = new Node;
    pNode8->data = 9;
    pNode7->pNext = pNode8;
    Node* pNode9 = new Node;
    pNode9->data = 51;
    pNode8->pNext = pNode9;
    pNode9->pNext = nullptr;
}

//遍历链表内容
void show_list(Node* pHead) {
    Node* tmp = pHead;
    while (tmp) {
        std::cout << tmp->data << " "; 
        tmp = tmp->pNext;
    }
    std::cout << std::endl;
}

//链表冒泡排序
void list_bubbling_sort(Node* pHead) {
    if (!pHead) {
        return;
    }
    Node* pDeal = pHead;
    while (pDeal) {
        Node* pBack = pDeal ->pNext;
        while (pBack) {
            if (pDeal->data > pBack->data) {
                int iTemp = pDeal->data;
                pDeal->data = pBack->data;
                pBack->data = iTemp;
            }
            pBack = pBack->pNext;
        }
        pDeal = pDeal->pNext;
    }
}

int main() {

    Node* pHead = nullptr;
    build_list(pHead);
    show_list(pHead);
    list_bubbling_sort(pHead);
    show_list(pHead);

    return 0;
}

2.2 Reverse order

#include<iostream>

using namespace std;

struct Node {
    int data;
    Node* pNext;
};

//构建链表
void build_list(Node*& pHead) {
    pHead = new Node;
    pHead->data = 90;
    Node* pNode1 = new Node;
    pNode1->data = 18;
    pHead->pNext = pNode1;
    Node* pNode2 = new Node;
    pNode2->data = 3;
    pNode1->pNext = pNode2;
    Node* pNode3 = new Node;
    pNode3->data = 56;
    pNode2->pNext = pNode3;
    Node* pNode4 = new Node;
    pNode4->data = 32;
    pNode3->pNext = pNode4;
    Node* pNode5 = new Node;
    pNode5->data = 45;
    pNode4->pNext = pNode5;
    Node* pNode6 = new Node;
    pNode6->data = 23;
    pNode5->pNext = pNode6;
    Node* pNode7 = new Node;
    pNode7->data = 21;
    pNode6->pNext = pNode7;
    Node* pNode8 = new Node;
    pNode8->data = 9;
    pNode7->pNext = pNode8;
    Node* pNode9 = new Node;
    pNode9->data = 51;
    pNode8->pNext = pNode9;
    pNode9->pNext = nullptr;
}

//遍历链表内容
void show_list(Node* pHead) {
    Node* tmp = pHead;
    while (tmp) {
        std::cout << tmp->data << " "; 
        tmp = tmp->pNext;
    }
    std::cout << std::endl;
}

// 链表反转1: 从第一个元素循环 
void reverse_list1(Node* &pHead) {
    if (!pHead || !pHead->pNext) {
        return;
    }
    Node* pCurNode = pHead;
    Node* pNextNode = nullptr;
    Node* pPreNode = nullptr;
    while (pCurNode) {
        pNextNode = pCurNode->pNext;
        pCurNode->pNext = pPreNode;
        pPreNode = pCurNode;
        pCurNode = pNextNode; 
    }
    pHead = pPreNode;

}

// 链表反转2: 从第二个元素循环
void reverse_list2(Node** pHead) {
    if (!pHead || !(*pHead)->pNext) {
        return;
    }
    Node* pCurNode = *pHead;
    Node* pNextNode = (*pHead)->pNext;
    (*pHead)->pNext = nullptr;
    while (pNextNode) {
        Node* pTmpNode = pNextNode->pNext; 
        pNextNode->pNext = pCurNode;
        pCurNode = pNextNode;
        pNextNode = pTmpNode;        
    }
    *pHead = pCurNode;
}


int main() {

    Node* pHead = nullptr;
    build_list(pHead);
    show_list(pHead);
    //reverse_list1(pHead);
    reverse_list2(&pHead);
    show_list(pHead);

    return 0;
}

2.2 Merge

(1) Modify the merge of the original linked list

#include<iostream>

using namespace std;

struct Node {
    int data;
    Node* pNext;
};

//链表冒泡排序
void list_bubbling_sort(Node* pHead) {
    if (!pHead) {
        return;
    }
    Node* pDeal = pHead;
    while (pDeal) {
        Node* pBack = pDeal ->pNext;
        while (pBack) {
            if (pDeal->data > pBack->data) {
                int iTemp = pDeal->data;
                pDeal->data = pBack->data;
                pBack->data = iTemp;
            }
            pBack = pBack->pNext;
        }
        pDeal = pDeal->pNext;
    }
}

//构建链表
void build_list(Node*& pHead) {
    pHead = new Node;
    pHead->data = 90;
    Node* pNode1 = new Node;
    pNode1->data = 18;
    pHead->pNext = pNode1;
    Node* pNode2 = new Node;
    pNode2->data = 3;
    pNode1->pNext = pNode2;
    Node* pNode3 = new Node;
    pNode3->data = 56;
    pNode2->pNext = pNode3;
    Node* pNode4 = new Node;
    pNode4->data = 32;
    pNode3->pNext = pNode4;
    Node* pNode5 = new Node;
    pNode5->data = 45;
    pNode4->pNext = pNode5;
    Node* pNode6 = new Node;
    pNode6->data = 23;
    pNode5->pNext = pNode6;
    Node* pNode7 = new Node;
    pNode7->data = 21;
    pNode6->pNext = pNode7;
    Node* pNode8 = new Node;
    pNode8->data = 9;
    pNode7->pNext = pNode8;
    Node* pNode9 = new Node;
    pNode9->data = 51;
    pNode8->pNext = pNode9;
    pNode9->pNext = nullptr;
}

//遍历链表内容
void show_list(Node* pHead) {
    Node* tmp = pHead;
    while (tmp) {
        std::cout << tmp->data << " "; 
        tmp = tmp->pNext;
    }
    std::cout << std::endl;
}

//有序链表合并成, 修改原始链表
void merge_list1(Node* pHead1, Node* pHead2, Node* &pHead) {
    if (!pHead1 && !pHead2) {
        return;
    }

    if (!pHead1) {
        pHead = pHead2;
        return;
    }

    if (!pHead2) {
        pHead = pHead1;
        return;
    }
    if (pHead1->data < pHead2->data) {
        pHead = pHead1;
        pHead1 = pHead1->pNext;
    }
    else {
        pHead = pHead2;
        pHead2 = pHead2->pNext;
    }
    
    Node* pCurNode = pHead;
    while (pHead1 && pHead2) {
        if (pHead1->data < pHead2->data) {
            pCurNode->pNext = pHead1;
            pHead1 = pHead1->pNext;
        }
        else {
            pCurNode->pNext = pHead2;
            pHead2 = pHead2->pNext;
        }
        pCurNode = pCurNode->pNext;
    }
     
    if (!pHead1) {
        pCurNode->pNext = pHead2;
        return;
    }

    if (!pHead2) {
        pCurNode->pNext = pHead1;
        return;
    }   
}

// 修改原始列表合并的测试
void merge_list_test1() {
    Node* pHead1;
    Node* pHead2;

    //构建链表
    build_list(pHead1);
    build_list(pHead2);
    show_list(pHead1);
    show_list(pHead2);

    //排序列表
    list_bubbling_sort(pHead1);
    list_bubbling_sort(pHead2);
    show_list(pHead1);
    show_list(pHead2);

    //合并链表
     Node* pHead;
     merge_list1(pHead1, pHead2, pHead);
     show_list(pHead1);
     show_list(pHead2);
     show_list(pHead);
}


int main() {
    merge_list_test1();

    return 0;
}

(2) Merge without modifying the original linked list

#include<iostream>

using namespace std;

struct Node {
    int data;
    Node* pNext;
};

//链表冒泡排序
void list_bubbling_sort(Node* pHead) {
    if (!pHead) {
        return;
    }
    Node* pDeal = pHead;
    while (pDeal) {
        Node* pBack = pDeal ->pNext;
        while (pBack) {
            if (pDeal->data > pBack->data) {
                int iTemp = pDeal->data;
                pDeal->data = pBack->data;
                pBack->data = iTemp;
            }
            pBack = pBack->pNext;
        }
        pDeal = pDeal->pNext;
    }
}

//构建链表
void build_list(Node*& pHead) {
    pHead = new Node;
    pHead->data = 90;
    Node* pNode1 = new Node;
    pNode1->data = 18;
    pHead->pNext = pNode1;
    Node* pNode2 = new Node;
    pNode2->data = 3;
    pNode1->pNext = pNode2;
    Node* pNode3 = new Node;
    pNode3->data = 56;
    pNode2->pNext = pNode3;
    Node* pNode4 = new Node;
    pNode4->data = 32;
    pNode3->pNext = pNode4;
    Node* pNode5 = new Node;
    pNode5->data = 45;
    pNode4->pNext = pNode5;
    Node* pNode6 = new Node;
    pNode6->data = 23;
    pNode5->pNext = pNode6;
    Node* pNode7 = new Node;
    pNode7->data = 21;
    pNode6->pNext = pNode7;
    Node* pNode8 = new Node;
    pNode8->data = 9;
    pNode7->pNext = pNode8;
    Node* pNode9 = new Node;
    pNode9->data = 51;
    pNode8->pNext = pNode9;
    pNode9->pNext = nullptr;
}

//遍历链表内容
void show_list(Node* pHead) {
    Node* tmp = pHead;
    while (tmp) {
        std::cout << tmp->data << " "; 
        tmp = tmp->pNext;
    }
    std::cout << std::endl;
}

//有序链表合并成, 不修改原始链表
void merge_list2(Node* pHead1, Node* pHead2, Node* &pHead) {
    if (!pHead1 && !pHead2) {
        return;
    }
    pHead = new Node;
    Node* pCurNode = pHead;
    if (!pHead1) {
        while (pHead2) {
            pCurNode->data = pHead2->data;
            pHead2 = pHead2->pNext;
            pCurNode->pNext = new Node;
            pCurNode = pCurNode->pNext;
            pCurNode->pNext = nullptr;
        }
        return;
    }

    if (!pHead2) {
        while (pHead1) {
            pCurNode->data = pHead1->data;
            pHead1 = pHead1->pNext;
            pCurNode->pNext = new Node;
            pCurNode = pCurNode->pNext;
            pCurNode->pNext = nullptr;
        }
        return;
    }
    if (pHead1->data < pHead2->data) {
        pCurNode->data = pHead1->data;
        pHead1 = pHead1->pNext;
    }
    else {
        pCurNode->data = pHead2->data;
        pHead2 = pHead2->pNext;
    }
    
    while (pHead1 && pHead2) {
        if (pHead1->data < pHead2->data) {
            pCurNode->pNext = new Node;
            pCurNode = pCurNode->pNext ;
            pCurNode->data = pHead1->data;
            pHead1 = pHead1->pNext; 
        }
        else {
            pCurNode->pNext = new Node;
            pCurNode = pCurNode->pNext ;
            pCurNode->data = pHead2->data;
            pHead2 = pHead2->pNext;
        }
    }
     
    if (!pHead1) {
        while (pHead2) {
            pCurNode->pNext = new Node;
            pCurNode = pCurNode->pNext ;
            pCurNode->data = pHead2->data;
            pHead2 = pHead2->pNext;
        }
        pCurNode->pNext = nullptr;
        return;
    }

    if (!pHead2) {
        while (pHead1) {
            pCurNode->pNext = new Node;
            pCurNode = pCurNode->pNext ;
            pCurNode->data = pHead1->data;
            pHead1 = pHead1->pNext; 
        }
        pCurNode->pNext = nullptr;
        return;
    }   
}

// 不修改原始列表合并的测试
void merge_list_test2() {
    Node* pHead1;
    Node* pHead2;

    //构建链表
    build_list(pHead1);
    build_list(pHead2);
    show_list(pHead1);
    show_list(pHead2);

    //排序列表
    list_bubbling_sort(pHead1);
    list_bubbling_sort(pHead2);
    show_list(pHead1);
    show_list(pHead2);

    //合并链表
    Node* pHead;
    merge_list2(pHead1, pHead2, pHead);
    show_list(pHead1);
    show_list(pHead2);
    show_list(pHead);
}

int main() {
    merge_list_test2();

    return 0;
}

5.Caching

5.1 Least recently used (LRU)

#include<iostream>
#include <list>
#include <map>

using namespace std;

// std::list存放key
// std::map 存放 key -> (vaue, key在std::list中的位置)
// 存放: key存放在list头部,map中存放key,value以及key在list中的具体位置
// 取值: key 在map中找到vaue以及keystd::list的位置,位置如果不在最前面,则删除重新插入
// 删除:从list尾部进行删除

class lru_cache
{
public:
    lru_cache(size_t capacity)
        : m_capacity(capacity)
    {
    }

    ~lru_cache()
    {
    }

    size_t size() const
    {
        return m_map.size();
    }

    size_t capacity() const
    {
        return m_capacity;
    }

    bool empty() const
    {
        return m_map.empty();
    }

    bool contains(const int &key)
    {
        return m_map.find(key) != m_map.end();
    }

    // 插入新值
    void insert(const int &key, const int &value)
    {
        std::map<int, std::pair<int, std::list<int>::iterator>>::iterator i = m_map.find(key);
        if(i == m_map.end()){
            if(size() >= m_capacity){
                evict();
            }
            // 新来的数据对应key放入链表头部
            m_list.push_front(key);
            // map中存放key,value及其key在链表中的位置
            m_map[key] = std::make_pair(value, m_list.begin());
        }
    }

    // 获取key对应value
    int get(const int &key)
    {
        std::map<int, std::pair<int, std::list<int>::iterator>>::iterator i = m_map.find(key);
        if(i == m_map.end()){
            return 0;
        }

        // 根据map迭代器找到key在链表中的位置
        std::list<int>::iterator j = i->second.second;
        // 新访问的数据必须放在最开始位置
        if(j != m_list.begin()){
            // 不在最开始位置将原来的进行删除,然后将其插入,插入一定是在最开始的位置
            m_list.erase(j);
            m_list.push_front(key);

            j = m_list.begin();
            const int &value = i->second.first;
            m_map[key] = std::make_pair(value, j);

            return value;
        }
        else {
            return i->second.first;
        }
    }

    void clear()
    {
        m_map.clear();
        m_list.clear();
    }

private:
    void evict()
    {
        std::list<int>::iterator i = --m_list.end();
        m_map.erase(*i);
        m_list.erase(i);
    }

private:
    //存放key, <value, key在list中的位置>,选择map是为了方便查找,存储key在list中的位置是为了在list快速删除
    std::map<int, std::pair<int, std::list<int>::iterator>> m_map;
    //存放key,选择list是为了方便在一定容量内进行插入和删除
    std::list<int> m_list;
    size_t m_capacity;
};


int main(int argc, char *argv[])
{
   lru_cache lruCache(10);

    return 0; 
}

6. String

6.1 Point-by-point ipv4 address formatting

#include <iostream>
#include <string>
#include <cstdio>

using namespace std;

int main() {
    std::string str;

    int iData = 0, iData1, iData2, iData3;
    sscanf("123.12.34.56", "%d.%d.%d.%d", &iData, &iData1, &iData2, &iData3);
    std::cout << iData << std::endl;
    std::cout << iData1 << std::endl;
    std::cout << iData2 << std::endl;
    std::cout << iData3 << std::endl;

    char tmpBuf[1024] = {0};
    sprintf(tmpBuf, "%d.%d.%d.%d", iData, iData1, iData2, iData3);
    std::cout << tmpBuf << std::endl;

    return 0;
}

6.2 String splitting

#include <iostream>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <vector>
#include <algorithm>
#include <cstring>

using namespace std;

std::vector<std::string> split(const char* pStr, char sepor) {
    std::vector<std::string> strVec;
    if (!pStr) {
        return strVec;
    }
    int iLen = strlen(pStr);
    std::string str;
    for (int i = 0; i < iLen; i++) {
        if (sepor == *(pStr + i)) {
            if (!str.empty()) {
                strVec.emplace_back(str);
                str.clear();
            }
        }
        else {
            str.push_back(*(pStr + i));
        }
    }
}


std::vector<std::string> split(const std::string& str, char sparator) {
    if (str.empty()) {
        return std::vector<std::string>();
    }
    std::vector<std::string> strVec;
    int iCurPos = 0, iLastPos = 0;
    while (std::string::npos != (iCurPos = str.find(sparator, iLastPos))) {
        if (iLastPos != iCurPos) {
            strVec.emplace_back(str.substr(iLastPos, iCurPos - iLastPos));
        }
        iLastPos = ++iCurPos;
    }

    return strVec;
}


int main() {
    std::vector<std::string> strVec = split("A10;D20;E30;W40;;;;", ';');
    for (const auto & item : strVec) {
        std::cout << item << std::endl;
    }

    return 0;
}

6.3 Find the longest repeating substring

#include <iostream>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <vector>
#include <algorithm>
#include <cstring>
#include <map>

using namespace std;


void findMaxRepeatSubStr(const std::string &str, std::string &strMaxSub) {
    int iLen = str.size();
    if (iLen <= 1) {
        return;
    }
    std::map<std::string, int> siMap;
    std::string strSub;
    int iPos = -1;
    // 按照个数从 1 -> iLen / 2查找子串
    for (int iNum = 1; iNum <= iLen / 2; iNum++) {
        for (int i = 0; i < iLen; i++) {
            strSub = str.substr(i, iNum);
            if (strSub.length() != iNum) {
                strSub.clear();
                continue;
            }
            if (siMap.end() == siMap.find(strSub)) {
                siMap[strSub] = 1;
            } else {
                siMap[strSub]++;
            } 
        }
    } 
    //遍历查找最长重复子串
    std::map<std::string, int>::iterator iter = siMap.end();
    int iMax = 0;
    for (auto item = siMap.begin(); item != siMap.end(); item++) {
        if (item->second > 1 && item->first.length() > iMax) {
            iter = item;
            iMax = item->first.length();
        }
    }
    if (iter != siMap.end()) {
        strMaxSub = iter->first;
    }
}


int main() {
    std::string str;
    
    findMaxRepeatSubStr("abcabcdacdacda", str);
    std::cout << str << std::endl;

    return 0;
}

7.IO stream

7.1 String and file IO streams

#include <iostream>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <vector>
#include <algorithm>
#include <cstring>
#include <sstream>
#include <map>
#include <fstream>

using namespace std;

//文件输出流
void test_of() {
   std::ofstream of("test.txt", std::ios::out | std::ios::app);
   if (of) {
    of << 123 << std::endl;
    of << "hello worl" << std::endl;
   }
   of.close();
}

//文件输入流
void test_if() {
    std::ifstream ifs("test.txt", std::ios::in);
    int iData = 0;
    std::string str;
    
    // 一次读取一个单词
    /*
    while (!ifs.eof()) {
        str.clear();
        ifs >> str;
        //文件最后一行是空白行
        if (ifs.eof() && str.empty()) {
            break;
        }
        std::cout << str << std::endl;
    }
    */

    //一次读取一行
    while (std::getline(ifs, str)) {
        if (str.empty()) {
            continue;
        }
        std::cout << str << std::endl;
    }

    ifs.close();
}

//字符串io流
void test_sstream() {
    std::stringstream istr;
    istr << "hello\n" << std::endl << "qazsedc" << std::endl << "AAAAAA" << std::endl << std::endl;
    std::string str;
    istr >> str;

    while (std::getline(istr, str)) {
        if (str.empty()) {
            continue;
        }
        std::cout << str << std::endl;
    }
}

int main() {

    test_of();
    test_if();

    return 0;
}

7.2 Clear unwanted buffers

// C language

#include <cstdio.h>

while (getchar() != '\n')

// C++

#include <limits>

std::cin.ignore(std::numeric_limits<streamsize>::max(), '\n');

#include <iostream>
#include <limits>

using namespace std;

int main() {
    int num = 0, id, iBoss, iIncome;
    std::cin >> num;
    if (num <= 0) {
        return -1;
    }

    for (int i = 0; i < num; i++) {
        std::cin >> id >> iBoss >> iIncome;
        // 将丢弃输入流中的所有内容,包括换行符。
        std::cin.ignore(std::numeric_limits<streamsize>::max(), '\n');
        std::cout << "=========> " << id << " " << iBoss << " " << iIncome << std::endl;
    }

    return 0;
}

8.VC++

8.1 Mutex and critical sections

Threads that forget to release the Mutex and critical section will continue to run without deadlock.

#include "stdafx.h"
#include <iostream>
#include <string>
#include <sstream>
#include <fstream>

using namespace std;

HANDLE hMutex = NULL;

CRITICAL_SECTION g_cs;

DWORD WINAPI ThreadFun1(LPVOID lpParam)
{
	while (true) {
		WaitForSingleObject(hMutex, INFINITE);
		cout << (int)lpParam << endl;
		Sleep(1000);
		ReleaseMutex(hMutex);
	}
	
	return(0);
}

DWORD WINAPI ThreadFun2(LPVOID lpParam)
{
	while (true) {
		WaitForSingleObject(hMutex, INFINITE);
		cout << (int)lpParam << endl;
		Sleep(1000);
		//ReleaseMutex(hMutex);
	}
	
	return(0);
}

DWORD WINAPI ThreadFun3(LPVOID lpParam)
{
	while (true) {
		EnterCriticalSection(&g_cs);
		cout << (int)lpParam << endl;
		Sleep(1000);
		LeaveCriticalSection(&g_cs);
	}

	return(0);
}

DWORD WINAPI ThreadFun4(LPVOID lpParam)
{
	while (true) {
		EnterCriticalSection(&g_cs);
		cout << (int)lpParam << endl;
		Sleep(1000);
		//LeaveCriticalSection(&g_cs);
	}

	return(0);
}

void  test_mutex() {
	HANDLE hThread = NULL;
	DWORD dwThreadId;

	hMutex = CreateMutex(NULL, true, "true");
	ReleaseMutex(hMutex);
	hThread = CreateThread(NULL, 0, ThreadFun1, (LPVOID)1, 0, &dwThreadId);
	hThread = CreateThread(NULL, 0, ThreadFun2, (LPVOID)2, 0, &dwThreadId);

	getchar();
	system("pause");
	CloseHandle(hThread);
	CloseHandle(hMutex);
}

void  test_section() {
	DWORD dwThreadId;
	InitializeCriticalSection(&g_cs);
	HANDLE hThread1 = CreateThread(NULL, 0, ThreadFun3, (LPVOID)3, 0, &dwThreadId);
	HANDLE hThread2 = CreateThread(NULL, 0, ThreadFun4, (LPVOID)4, 0, &dwThreadId);



	Sleep(400000);
	//关闭线程句柄
	CloseHandle(hThread1);
	CloseHandle(hThread2);

	//关闭事件对象句柄
	DeleteCriticalSection(&g_cs);
}

Guess you like

Origin blog.csdn.net/hsy12342611/article/details/132192682