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

C++中CLISTCTRL读写CSV异常:索引11后重复截断问题排查

C++中CLISTCTRL加载CSV时索引11后重复覆盖问题排查与修复

问题场景

将CLISTCTRL内容保存为.csv文件后重新加载,索引0到10显示正常,但从索引11开始出现重复输出(覆盖索引10内容)且字符截断的情况。

原始代码

struct DATA 
{
    CString strName;
    CString strEmail;
    CString strTel;
    CString strGroup;
};

//Code to initialize CLISTCTRL
//CLISTCTRL control name = L_viewctrl

    FILE* file = NULL;
    DATA* indexData = new DATA;

    USES_CONVERSION;

    fopen_s(&file, path_str, "r");
    if (file)
    {
        char szContent[2048];

        memset(szContent, NULL, sizeof(szContent));

        CString strRstring;
        int nFileline(0);
        int nSubString(0);
        while (fgets(szContent, 2048, file))
        {
            //File Read
            CString strFile;
            strFile = szContent;

            bool bfileLineRet = TRUE;
            while (bfileLineRet)
            {
                AfxExtractSubString(strRstring, strFile, nSubString++, ',');
                if (nSubString == 2)indexData->strName = strRstring;

                if (nSubString == 3)indexData->strEmail = strRstring;

                if (nSubString == 4)indexData->strTel = strRstring;

                if (nSubString == 5) 
                {
                    indexData->strGroup = strRstring;
                    nSubString = 0;
                    bfileLineRet = FALSE;
                }
            }

            //LIST INDEX DATA SET;
            UpdateData(TRUE);
            CString strCount;
            strCount.Format(_T("%d"), nFileline);
            L_viewctrl.InsertItem(nFileline, strCount);
            L_viewctrl.SetItem(nFileline, 1, LVIF_TEXT, indexData->strName, 0, 0, 0, 0);
            L_viewctrl.SetItem(nFileline, 2, LVIF_TEXT, indexData->strEmail, 0, 0, 0, 0);
            L_viewctrl.SetItem(nFileline, 3, LVIF_TEXT, indexData->strTel, 0, 0, 0, 0);
            L_viewctrl.SetItem(nFileline, 4, LVIF_TEXT, indexData->strGroup, 0, 0, 0, 0);
            nFileline++;
        }
    }
    fclose(file);

问题排查

  • nSubString初始化位置错误:该变量定义在循环外部,若某一行解析失败(字段不足5个),nSubString不会被重置,导致下一行解析时索引错位,数据赋值混乱。
  • DATA对象复用未清空:仅创建一个全局DATA对象,解析出错时旧数据残留,直接复用导致后续行显示重复内容。
  • 换行符未处理:fgets会将换行符\n读入缓冲区,污染最后一个字段内容,引发显示截断或异常。
  • 无效的UpdateData(TRUE)调用:循环内每次插入行都调用该函数,强制同步控件数据到变量,干扰控件正常更新逻辑。

修正方案

struct DATA 
{
    CString strName;
    CString strEmail;
    CString strTel;
    CString strGroup;
};

//Code to initialize CLISTCTRL
//CLISTCTRL control name = L_viewctrl

FILE* file = NULL;

USES_CONVERSION;

fopen_s(&file, path_str, "r");
if (file)
{
    char szContent[2048];

    int nFileline(0);
    while (fgets(szContent, 2048, file))
    {
        // 每行解析创建局部DATA对象,自动清空旧数据
        DATA indexData;
        // 移除换行符,避免污染字段内容
        size_t len = strlen(szContent);
        if (len > 0 && szContent[len-1] == '\n')
        {
            szContent[len-1] = '\0';
            if (len > 1 && szContent[len-2] == '\r')
            {
                szContent[len-2] = '\0';
            }
        }

        CString strFile = szContent;
        CString strRstring;
        // 每次解析新行时重置子字符串索引
        int nSubString = 0;
        
        // 按顺序提取字段,增加提取成功判断
        if (AfxExtractSubString(strRstring, strFile, nSubString++, ','))
            indexData.strName = strRstring;
        if (AfxExtractSubString(strRstring, strFile, nSubString++, ','))
            indexData.strEmail = strRstring;
        if (AfxExtractSubString(strRstring, strFile, nSubString++, ','))
            indexData.strTel = strRstring;
        if (AfxExtractSubString(strRstring, strFile, nSubString++, ','))
            indexData.strGroup = strRstring;

        // 插入数据到列表控件
        CString strCount;
        strCount.Format(_T("%d"), nFileline);
        L_viewctrl.InsertItem(nFileline, strCount);
        L_viewctrl.SetItem(nFileline, 1, LVIF_TEXT, indexData.strName, 0, 0, 0, 0);
        L_viewctrl.SetItem(nFileline, 2, LVIF_TEXT, indexData.strEmail, 0, 0, 0, 0);
        L_viewctrl.SetItem(nFileline, 3, LVIF_TEXT, indexData.strTel, 0, 0, 0, 0);
        L_viewctrl.SetItem(nFileline, 4, LVIF_TEXT, indexData.strGroup, 0, 0, 0, 0);
        nFileline++;
    }
    fclose(file);
}

关键修复点说明

  1. 将nSubString移至循环内部:每次解析新行都从0开始索引,避免字段错位。
  2. 使用局部DATA对象:每行解析创建新的栈对象,自动清空旧数据,无需手动重置。
  3. 处理换行符:移除fgets读取的\n和\r,保证字段内容干净。
  4. 移除UpdateData(TRUE):直接操作控件即可,无需同步变量,避免干扰更新逻辑。
  5. 增加字段提取判断:通过AfxExtractSubString的返回值判断提取是否成功,防止索引越界。

内容的提问来源于stack exchange,提问作者포스제이

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 15:33:26