首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在C中解析带有引号分隔字段的CSV?

如何在C中解析带有引号分隔字段的CSV?
EN

Stack Overflow用户
提问于 2011-02-16 05:06:38
回答 4查看 2.4K关注 0票数 2

考虑一下这条消息:

代码语言:javascript
复制
N,8545,01/02/2011 09:15:01.815,"RASTA OPTSTK 24FEB2011 1,150.00 CE",S,8.80,250,0.00,0

这只是一个样本。其想法是,这是csv文件中的一行。现在,如果我把它分成逗号,那么1150数字就会有问题。

双引号内的字符串长度可变,但可以确定为一个“元素”(如果我可以使用该术语),其他元素由

我该如何解析它?( Ragel解析引擎除外)

索汉姆

EN

回答 4

Stack Overflow用户

发布于 2011-02-16 05:14:21

将字符串拆分为逗号分隔的字段,提供的表示逗号未嵌入到带引号的字符串中。

一种快速的方法是使用状态机。

代码语言:javascript
复制
boolean inQuote = false;
StringBuffer buffer= new StringBuffer();
// readchar() is to be implemented however you read a char
while ((char = readchar()) != -1) {
  switch (char) {

    case ',':
      if (inQuote == false) {
         // store the field in our parsedLine object for later processing.
         parsedLine.addField(buffer.toString());
         buffer.setLength(0);
      }
      break;

    case '"': 
      inQuote = !inQuote;
      // fall through to next target is deliberate.

    default:
      buffer.append(char);

  }
}

请注意,虽然这提供了一个示例,但CSV文件还有一些需要考虑的问题(比如在引号中嵌入引号,或者在示例中去掉外引号是否合适)。

票数 4
EN

Stack Overflow用户

发布于 2011-02-16 05:13:33

如果您不想添加外部库,一种快速而糟糕的解决方案是将双引号转换为\0 (字符串结束标记),然后使用sscanf分别解析这三个字符串。虽然难看,但应该能行得通。

假设输入是格式良好的(否则您将不得不添加错误处理):

代码语言:javascript
复制
for (i=0; str[i]; i++)
  if (str[i] == '"') str[i] = 0;
str += sscanf(str, "%c,%d,%d/%d/%d %d:%d:%d.%d,", &var1, &var2, ..., &var9);
var10 = str; // it may be str+1, I don't remember if sscanf consumes also the \0
sscanf(str+strlen(var10), ",%c,%f,%d,%f,%d", &var11, &var12, ..., &var15);

如果你想立即释放str,显然你必须复制一份var10

票数 1
EN

Stack Overflow用户

发布于 2011-02-16 13:17:18

这是一个函数,用于从作为FILE *提供的输入文件中获取下一个单独的CSV字段。它希望文件以文本模式打开,并支持带有内嵌引号和换行符的引号字段。比提供的缓冲区大小更长的字段将被截断。

代码语言:javascript
复制
int get_csv_field(FILE *f, char *buf, size_t size)
{
    char *p = buf;
    int c;
    enum { QS_UNQUOTED, QS_QUOTED, QS_GOTQUOTE } quotestate = QS_UNQUOTED;

    if (size < 1)
        return EOF;

    while ((c = getc(f)) != EOF)
    {
        if ((c == '\n' || c == ',') && quotestate != QS_QUOTED)
            break;

        if (c == '"')
        {
            if (quotestate == QS_UNQUOTED)
            {
                quotestate = QS_QUOTED;
                continue;
            }

            if (quotestate == QS_QUOTED)
            {
                quotestate = QS_GOTQUOTE;
                continue;
            }

            if (quotestate == QS_GOTQUOTE)
            {
                quotestate = QS_QUOTED;
            }
        }

        if (quotestate == QS_GOTQUOTE)
        {
            quotestate = QS_UNQUOTED;
        }

        if (size > 1)
        {
            *p++ = c;
            size--;
        }
    }

    *p = '\0';

    return c;
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/5009498

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档