You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++ WinAPI疫苗卡程序中HeapSort功能异常排查求助

疫苗卡管理程序HeapSort功能异常排查

我在Visual Studio中使用C++和WinAPI开发一款疫苗卡管理程序,所有人员及疫苗数据均存储在名为CARNET的双向链表中。程序需实现两个按钮功能:

  • 按钮1:使用QuickSort按人员姓名排序ListBox中的信息
  • 按钮2:使用HeapSort按人员ID排序ListBox中的信息

每个按钮的逻辑统一为:清空ListBox→计算链表长度→创建数组复制链表数据→调用对应排序算法→将排序后的数组内容显示到ListBox。目前QuickSort功能正常,但点击HeapSort按钮后,实际呈现的却是QuickSort的排序效果,已确认两个按钮的ID正确且绑定对应事件,恳请帮忙排查问题原因。

相关代码

struct CARDS {

    //疫苗数据
    wchar_t no_dose[20]{};
    wchar_t price[20]{};
    wchar_t brand[40]{};

    //人员数据
    wchar_t name[60]{};
    wchar_t surname[30]{};
    wchar_t marital_status[40]{};
    wchar_t sex[40]{};
    wchar_t date_birth[40]{};
    wchar_t city[30];
    wchar_t state[30];
    wchar_t tel[20]{};
    

    //接种数据
    SYSTEMTIME date_dosage{};
    wchar_t no_dosage[10]{};
    wchar_t place_vacc[100]{};
    
    //疫苗卡ID
    int id{};

    CARDS* next{};
    CARDS* prev{};
};

CARDS* Lstart = NULL; //指向链表头部
CARDS* Lend = NULL; //指向链表尾部
//-----------------------------------------------------
//快速排序(QuickSort)
void change(CARDS* a, CARDS* b) {
    
    //疫苗数据
    swap(a->no_dose, b->no_dose);
    swap(a->price, b->price);
    swap(a->brand, b->brand);
    
    //人员数据
    swap(a->name, b->name);
    swap(a->surname, b->surname);
    swap(a->marital_status, b->marital_status);
    swap(a->sex, b->sex);
    swap(a->date_birth, b->date_birth);
    swap(a->city, b->city);
    swap(a->state, b->state);
    swap(a->tel, b->tel);
    

    //接种数据
    swap(a->date_dosage, b->date_dosage);
    swap(a->no_dose, b->no_dose);
    swap(a->place_vacc, b->place_vacc);
    
    //疫苗卡ID
    swap(a->id, b->id);
}

int partition(CARDS* arr, int start, int end) {
    wstring pivot = arr[end].name;
    int i = start - 1;

    for (int j = start; j < end; j++) {
        if (arr[j].name<=pivot) {
            i++;
            change(&arr[i], &arr[j]);
        }
    }

    change(&arr[i + 1], &arr[end]);
    return i + 1;
}

void quicksort(CARDS* arr, int start, int end) {
    if (start < end) {
        int index_pivot = partition(arr, start, end);
        quicksort(arr, start, index_pivot - 1);
        quicksort(arr, index_pivot + 1, end);
    }
}


//堆排序(HeapSort)
void heapify(CARDS* arr, int n, int i)
{
    int largest = i; 
    int l = 2 * i + 1; 
    int r = 2 * i + 2; 

    
    if (l<n && arr[l].id>arr[largest].id)
        largest = l;

    
    if (r<n && arr[r].id > arr[largest].id)
        largest = r;


    if (largest != i) {
        swap(arr[i], arr[largest]);
        
        heapify(arr, n, largest);
    }
}

void heapSort(CARDS* arr, int n)
{
    
    for (int i = n / 2 - 1; i >= 0; i--)
        heapify(arr, n, i);

    
    for (int i = n - 1; i > 0; i--) {
        
        swap(arr[0], arr[i]);
        
        
        heapify(arr, i, 0);
    }
}

BOOL CALLBACK Quicksort_call(HWND window, UINT message, WPARAM wParam, LPARAM lParam) {
    int select = NULL;
    wchar_t fe[50]{};
    wchar_t idString;
    int id;
    wstring ageString;
    switch (message) {

    case WM_COMMAND: {
        long opc = LOWORD(wParam);
        BAR_MENU(window, opc);
        switch (LOWORD(wParam)) {
        
        case IDC_BUTTON1: {
            SendDlgItemMessage(window, IDC_LIST2, LB_RESETCONTENT, NULL, 0);

            int size = 0;
            for (CARDS* aux = Lstart; aux != nullptr; aux = aux->next) {
                size++;
            }

            CARDS* arr = new CARDS[size];
            int index = 0;
            for (CARDS* aux = Lstart; aux != nullptr; aux = aux->next) {
                arr[index] = *aux;
                index++;
            }
            quicksort(arr, 0, size - 1);
            for (int i = 0; i < size; i++) {

                wchar_t full_name[150] = L"";
                wchar_t idStr[20];
                wcscat_s(full_name, sizeof(full_name) / sizeof(wchar_t), arr[i].name);
                wcscat_s(full_name, sizeof(full_name) / sizeof(wchar_t), L" ");
                wcscat_s(full_name, sizeof(full_name) / sizeof(wchar_t), arr[i].surname);
                swprintf(idStr, sizeof(idStr) / sizeof(wchar_t), L"%d", arr[i].id);
                wcscat_s(full_name, sizeof(full_name) / sizeof(wchar_t), L" ");
                wcscat_s(full_name, sizeof(full_name) / sizeof(wchar_t), idStr);



                SendDlgItemMessage(window, IDC_LIST2, LB_ADDSTRING, NULL, (LPARAM)full_name);
            }
            delete[]arr;
            break;
        }
        case IDC_BUTTON2: {
            SendDlgItemMessage(window, IDC_LIST2, LB_RESETCONTENT, NULL, 0);

            int size2 = 0;
            for (CARDS* aux = Lstart; aux != nullptr; aux = aux->next) {
                size2++;
            }

            CARDS* arr2 = new CARDS[size2];
            int index = 0;
            for (CARDS* aux = Lstart; aux != nullptr; aux = aux->next) {
                arr2[index] = *aux;
                index++;
            }

            
            
            heapSort(arr2, size2);
            for (int i = 0; i < size2; i++) {

                wchar_t full_name[150] = L"";
                wchar_t idStr[20];
                wcscat_s(full_name, sizeof(full_name) / sizeof(wchar_t), arr[i].name);
                wcscat_s(full_name, sizeof(full_name) / sizeof(wchar_t), L" ");
                wcscat_s(full_name, sizeof(full_name) / sizeof(wchar_t), arr[i].surname);
                swprintf(idStr, sizeof(idStr) / sizeof(wchar_t), L"%d", arr[i].id);
                wcscat_s(full_name, sizeof(full_name) / sizeof(wchar_t), L" ");
                wcscat_s(full_name, sizeof(full_name) / sizeof(wchar_t), idStr);

                SendDlgItemMessage(window, IDC_LIST2, LB_ADDSTRING, NULL, (LPARAM)full_name);
            }



            delete[] arr2;
            break;
        }
}

        break;
    }
    case WM_INITDIALOG:
    {
        
        

        break;
    }
    }
    return false;
}

问题原因与修复

核心问题

在IDC_BUTTON2的显示逻辑中,错误使用了arr[i]访问数据,但实际存储HeapSort排序结果的数组是arr2。arr是IDC_BUTTON1中的局部变量,在IDC_BUTTON2作用域内未定义,此时访问arr[i]属于未定义行为,大概率读取了之前arr占用的未被覆盖的内存空间,导致显示QuickSort排序后的旧数据。

修复代码

将IDC_BUTTON2循环中的所有arr[i]替换为arr2[i]:

case IDC_BUTTON2: {
    SendDlgItemMessage(window, IDC_LIST2, LB_RESETCONTENT, NULL, 0);

    int size2 = 0;
    for (CARDS* aux = Lstart; aux != nullptr; aux = aux->next) {
        size2++;
    }

    CARDS* arr2 = new CARDS[size2];
    int index = 0;
    for (CARDS* aux = Lstart; aux != nullptr; aux = aux->next) {
        arr2[index] = *aux;
        index++;
    }

    heapSort(arr2, size2);
    for (int i = 0; i < size2; i++) {

        wchar_t full_name[150] = L"";
        wchar_t idStr[20];
        wcscat_s(full_name, sizeof(full_name) / sizeof(wchar_t), arr2[i].name);
        wcscat_s(full_name, sizeof(full_name) / sizeof(wchar_t), L" ");
        wcscat_s(full_name, sizeof(full_name) / sizeof(wchar_t), arr2[i].surname);
        swprintf(idStr, sizeof(idStr) / sizeof(wchar_t), L"%d", arr2[i].id);
        wcscat_s(full_name, sizeof(full_name) / sizeof(wchar_t), L" ");
        wcscat_s(full_name, sizeof(full_name) / sizeof(wchar_t), idStr);

        SendDlgItemMessage(window, IDC_LIST2, LB_ADDSTRING, NULL, (LPARAM)full_name);
    }

    delete[] arr2;
    break;
}

额外注意事项

  • HeapSort使用std::swap直接交换CARDS实例,QuickSort使用自定义change函数,两者效果一致(CARDS是值类型,std::swap会逐成员拷贝交换),但建议保持逻辑统一,避免后续维护混淆。
  • 局部变量命名尽量规范,比如两个按钮的数组可都用arr(各自作用域内的局部变量),减少变量名写错的概率。

内容的提问来源于stack exchange,提问作者Angel Gonzalez

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 13:17:01