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
相关产品推荐
相关产品推荐

