C/C++基本功 - 常见笔试题

      俗话说的好,根基不稳,地动山摇,作为一名C/C++开发人员,基本功的扎实程度决定了职业高度,本篇将C/C++常见笔试题进行整理。

目录

1.STL

1.1 vector中push_back和emplace_back的区别

1.2 vector清除内存

1.3 std::array

2.排序

2.1 冒泡排序

2.2 快速排序

2.3 堆排序

3.内存

3.1 实现memset函数

4.链表

2.1 冒泡排序

2.2 逆序

2.2 合并

(1)修改原始链表的合并

(2)不修改原始链表的合并

5.缓存

5.1 最近最少使用(LRU)

6.字符串

6.1 点分ipv4地址格式化处理

6.2 字符串拆分

6.3 查找最长重复子串

7.IO流

7.1 字符串和文件IO流

7.2 清空不想要的缓冲区

8.VC++

8.1 Mutex和临界区


1.STL

1.1 vector中push_back和emplace_back的区别

        emplace_back() 函数是 C++11 新增加的,其功能和push_back()相同, emplace_back可以直接通过参数构建容器元素,省去了一次拷贝构造的调

#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清除内存

#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是在栈上分配内存

#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.排序

2.1 冒泡排序

#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 快速排序

#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 堆排序

#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.内存

3.1 实现memset函数

#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.链表

2.1 冒泡排序

#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 逆序

#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 合并

(1)修改原始链表的合并

#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)不修改原始链表的合并

#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.缓存

5.1 最近最少使用(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.字符串

6.1 点分ipv4地址格式化处理

#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 字符串拆分

#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 查找最长重复子串

#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流

7.1 字符串和文件IO流

#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 清空不想要的缓冲区

// C语言

#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和临界区

忘记释放Mutex和临界区的线程会一直运行,并不会出现死锁

#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);
}

猜你喜欢

转载自blog.csdn.net/hsy12342611/article/details/132192682