【问题标题】:Losing last character in string when reading a value from a line in a CSV从 CSV 中的一行读取值时丢失字符串中的最后一个字符
【发布时间】:2018-11-16 19:48:52
【问题描述】:

我正在尝试解析 CSV 文件的一行并提取我想要的所需值。但是,我的函数正在切断字符串中的最后一个字符,我不知道为什么。我认为这与我分配空终止符的位置有关,但改变它并没有帮助。任何帮助,将不胜感激。谢谢!

char* findKey(char lineBuffer[], int columnNumber ){
    char tempArray[strlen(lineBuffer)+2];
    int commasCounted = 0;
    int i =0;

    for(i = 0; i < strlen(lineBuffer) - 1; i++){
        if (commasCounted == columnNumber){
            commasCounted = i;
            break;
        }

        if (lineBuffer[i] == '\"'){
            i++;
            while(lineBuffer[i] && lineBuffer[i] != '\"'){
                i++;
            }
        }

        if (lineBuffer[i] == ','){
            commasCounted++;
        }
    }

    if(lineBuffer[commasCounted] == ','){
        tempArray[0] = '0';
        tempArray[1] = '0';
        tempArray[2] = '0';
        tempArray[3] = '0';
        tempArray[4] = '\0';
    }else{
        int j = 0;
        for(i = commasCounted; i < strlen(lineBuffer) - 1; i++){
            if(lineBuffer[i] == '\"'){
                i++;
                while(lineBuffer[i] && lineBuffer[i] != '\"'){
                    tempArray[j] = lineBuffer[i];
                    i++;
                    j++;
                }
                break;
            }else if(lineBuffer[i] == ','){
                break;
            }else
                tempArray[j] = lineBuffer[i];
                j++;
        }
        tempArray[j] = '\0';
    }

    char* tempString = strtok(tempArray, "\n");
    //printf("tempString before returning in findKey: %s\n", tempString); //testing
    return tempString;
}

CSV 文件中的某些列可以用引号括起来,这就是为什么要在其中检查引号的原因。这将传递要检查的字符串以及包含信息的列。因此,例如: 为 lineBuffer 传入这个:

30,beforeyoustartedgackinyouusedtohaveabrainbutnowyoudontgeteventhesimpliesofthingsdrawalittlepictureevenusemyhandstrytoexplainbutyoujustdontunderstandoh

列编号为 1

返回结果:

beforeyoustartedgackinyouusedtohaveabrainbutnowyoudontgeteventhesimpliesofthingsdrawalittlepictureevenusemyhandstrytoexplainbutyoujustdontunderstando

【问题讨论】:

  • 您正在从临时/本地字符串中返回一个标记化的字符串:这是未定义的行为
  • 您这样做是为了学习,还是实际应用的一部分?对于后者,您最好使用预先编写的 CSV 库。
  • @Barmar 学习
  • 您是否尝试过复制该行:char* tempString = strdup(strtok(tempArray, "\n"));
  • 我以为这是 python,我现在删除的第一条评论是“你不能使用 csv 模块吗?哈哈……这里可能有很好的例子。研究它们。跨度>

标签: c arrays string char


【解决方案1】:

您永远不会复制该行的最后一个字符,因为您在for 循环条件中有i &lt; strlen(lineBuffer) - 1。将其更改为 i &lt; strlen(lineBuffer)

在返回之前还需要对字符串进行复制,不能在C中返回本地数组:

return strdup(tempString);

这也意味着调用者在处理完这个字符串后需要释放它,因为strdup() 动态分配内存。或者,您可以首先使用malloc() 分配tempArray(),而不是声明一个本地数组。

【讨论】:

  • 就是这样,for循环条件。非常感谢。一些进一步的问题:我认为 strlen(lineBuffer) 是指字符串中的最后一个空格,即空终止符?不是这样吗?另外:strdup 是否在后台动态分配内存?
  • 是的,strlen() 返回空终止符的索引。这就是为什么你在条件中使用&lt; 来停止之前的字符,这是最后一个真正的字符。如果您使用的是&lt;=,那么减 1 是正确的。
  • 是的,strdup() 动态分配内存。这就是你需要释放它的原因。
  • 啊,明白了。谢谢你。最后一件事:似乎代码在不使用strdup 的情况下运行良好。如果它是未定义的行为,在这种情况下不应该破坏吗?
  • @Locke 未定义行为的行为未定义。
猜你喜欢
  • 1970-01-01
  • 2013-09-06
  • 1970-01-01
  • 2019-04-23
  • 1970-01-01
  • 2013-03-17
  • 2018-03-23
  • 2012-04-08
  • 2013-06-27
相关资源
最近更新 更多