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

双向链表分页输出函数异常:回退跳页/循环问题求助

双向链表达页输出异常修复方案

问题概述

实现了双向链表的分页输出函数ShowList,每页展示count/2(即5条)数据,末尾不足一页的数据单独处理。当前存在两个异常:

  • 翻到末尾后回退会跳过一页
  • 按分页大小回退时,会循环到最后一页及末尾数据
    修改逻辑后仍存在末尾循环问题,原代码及尝试修改如下:

原代码

void ShowList(hwnd* hwnd){
    int id = 0, count = 10, CountElementstInEnd;
    node* temp;
    node* head = hwnd->head;
    node* UpLimit = hwnd->head;
    node* LwLimit = hwnd->tail;

    if(!head) return;
    for(int i = 0; i < count/2 ; i++)
        UpLimit = UpLimit->next;
    CountElementstInEnd = hwnd->size % (count/2) - 1;
    for(int i = 0; i < CountElementstInEnd; i++)
        LwLimit = LwLimit->prev;
    temp = LwLimit;
    char c;

    do
    {
        system("cls");
        puts      (" ID      NAME          SEX        SPORT          BORN    GROWTH ");
        for(int i = 0; i < count/2 ; i++, id++){
            ///Output the records at the end (their number may not be a multiple of count/2)
            if(head == LwLimit){
                for(int i = 0; i < CountElementstInEnd; i++, id++){
                    printf(" %-2.2d   %-12.12s    %-6.6s   %-16.16s  %-4.4d      %-3.3d  \n", id, temp->data->name, temp->data->sex, temp->data->sport, temp->data->born, temp->data->growth);
                    temp = temp->next;
                }
                temp = LwLimit;
                id-=CountElementstInEnd;
                break;
            }
            ///normal output
            printf(" %-2.2d   %-12.12s    %-6.6s   %-16.16s  %-4.4d      %-3.3d  \n", id, head->data->name, head->data->sex, head->data->sport, head->data->born, head->data->growth);
            head = head->next;
        }
        ///users input 1 - next, 2 - prev
         while(1){
            c = getch();
            if (c == 0x31 && (head == LwLimit)){
                for(int i = 0; i < count; i++)
                    head = head->prev;
                id -= count;
                break;
            }
            if (c == 0x31 && (head != UpLimit)){
                for(int i = 0; i < count; i++)
                    head = head->prev;
                id -= count;
                break;
            }
            else if(c == 0x32 || c == 27)
                break;
        }
        
    }
    while(c != 27);
}

尝试的修改代码

if (c == 0x31 && (head == hwnd->tail)){
        head = head->prev->prev;
        break;
    }

问题根源

  1. 边界计算错误:CountElementstInEnd = hwnd->size % (count/2) - 1未考虑整除场景,余数为0时会得到负数,导致LwLimit定位错误。
  2. 翻页步长错误:翻页时移动了count(10个)节点,但每页仅展示5个,步长不匹配导致跳页。
  3. 边界判断混乱:UpLimit/LwLimit的定位逻辑不清晰,无法正确识别分页边界状态。
  4. ID计数不同步:ID未根据当前页起始位置重新计算,导致翻页后ID混乱。

修复后的完整代码

#include <conio.h> // 确保getch()可用

// 辅助函数:获取节点在链表中的索引(从0开始)
int get_node_index(hwnd* hwnd, node* target){
    int index = 0;
    node* temp = hwnd->head;
    while(temp != target){
        index++;
        temp = temp->next;
    }
    return index;
}

void ShowList(hwnd* hwnd){
    const int PAGE_SIZE = 5; // 每页固定展示5条数据
    int current_id;
    node* current_page_start = hwnd->head;
    char c;

    if(!current_page_start) return;

    // 预计算分页关键参数
    int total_elements = hwnd->size;
    int total_pages = (total_elements + PAGE_SIZE - 1) / PAGE_SIZE; // 向上取整计算总页数
    int last_page_count = total_elements % PAGE_SIZE;
    if(last_page_count == 0) last_page_count = PAGE_SIZE; // 整除时最后一页也是PAGE_SIZE条

    do
    {
        system("cls");
        puts(" ID      NAME          SEX        SPORT          BORN    GROWTH ");
        
        // 计算当前页的起始ID(从1开始)
        current_id = get_node_index(hwnd, current_page_start) + 1;
        node* temp = current_page_start;
        
        // 判断当前是否为最后一页,确定要展示的条数
        int current_page_num = (get_node_index(hwnd, current_page_start) / PAGE_SIZE) + 1;
        int display_count = (current_page_num == total_pages) ? last_page_count : PAGE_SIZE;

        // 输出当前页数据
        for(int i = 0; i < display_count; i++, current_id++){
            printf(" %-2.2d   %-12.12s    %-6.6s   %-16.16s  %-4.4d      %-3.3d  \n", 
                   current_id, temp->data->name, temp->data->sex, temp->data->sport, 
                   temp->data->born, temp->data->growth);
            temp = temp->next;
        }

        // 处理用户输入:1=下一页,2=上一页,ESC=退出
        while(1){
            c = getch();
            if(c == '1'){
                // 下一页:仅当前页不是最后一页时允许翻页
                if(current_page_num < total_pages){
                    // 移动到下一页起始位置
                    for(int i = 0; i < PAGE_SIZE; i++){
                        current_page_start = current_page_start->next;
                    }
                }
                break;
            }
            else if(c == '2'){
                // 上一页:仅当前页不是第一页时允许翻页
                if(current_page_num > 1){
                    // 回退到上一页起始位置
                    for(int i = 0; i < PAGE_SIZE; i++){
                        current_page_start = current_page_start->prev;
                    }
                }
                break;
            }
            else if(c == 27){ // ESC键ASCII码
                break;
            }
        }
        
    } while(c != 27);
}

关键修改说明

  1. 固定分页参数:用常量PAGE_SIZE替代count/2,避免重复计算,代码更易维护。
  2. 正确计算分页边界:通过向上取整计算总页数,处理整除场景下的最后一页条数。
  3. 索引化分页定位:新增get_node_index辅助函数,准确计算当前页的页码和起始ID,解决ID混乱问题。
  4. 清晰的翻页逻辑:
    • 下一页:仅当不是最后一页时,向前移动PAGE_SIZE个节点
    • 上一页:仅当不是第一页时,向后移动PAGE_SIZE个节点
    • 彻底避免了边界循环和跳页问题
  5. 简化输出逻辑:通过页码判断是否为最后一页,直接输出对应条数的数据,删除了原代码中混乱的LwLimit/UpLimit判断。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 09:31:02