【问题标题】:Import a CSV of strings into a multi-dimensional array in C将字符串的 CSV 导入 C 中的多维数组
【发布时间】:2017-02-16 19:55:12
【问题描述】:

我正在尝试将格式与 CSV 类似的文本文件输入到多维数组中,其中数组的每个元素都是每行的单词数组。任何帮助将不胜感激!

例如,文件 input.txt 可能包含:

Carrot, Potato, Beetroot, Courgette, Broccoli
Dad's oranges, Apple, Banana, Cherry
Pasta, Pizza, Bread, Butter

我希望从中得到的输出数组的结构是:

[[Carrot, Potato, Beetroot, Courgette, Broccoli], [Dad's oranges, Apple, Banana, Cherry], [Pasta, Pizza, Bread, Butter]]

所以你就行了:

printf("%s", inputArray[1][0]);

将打印:

Dad's oranges

【问题讨论】:

  • 我建议strtok 的分隔符字符串应该是", \t\r\n",但“爸爸的橙子”包含一个空格。因此,您必须将该空格从分隔符中删除,并在获取每个标记后去掉任何前导空格。
  • 您正在观察什么输出?你期望的输出是什么?
  • @rootkea 目前我正在观察我无法解释的奇怪输出。对于printf("%s", inputArray[0]);,我会回复Pasta。我期待第一项,Carrot
  • @hardanger 是的!那是因为您没有分配内存来存储以前的令牌。但由于inputArray[0] 指向line[0],它现在包含Pasta,它覆盖了之前的CarrotDad's oranges,请参阅我的答案了解更多详情。
  • 您在ptrmalloc 之间使用了== 而不是=。请参阅我的答案中的更新代码。

标签: c arrays csv


【解决方案1】:

我不确定这里的问题是什么。但是,查看您的问题陈述和代码,我发现很少有问题(请注意,我没有运行代码,这是为了给您一个想法):

  1. 您的 varCount 将从 1 开始,在您输入第一个单词之前递增。
  2. 您将固有的二维数据存储到一维数组中。这通常很好,但是您需要对行的开始位置和结束位置进行编码。那是缺失的。如果一切正常,您将获得一系列单词,不知道行的开始/结束位置。处理它的一种方法是创建一个二维数组。另一种是在行之间插入一个指向已知单词的指针。下面是显示插入分隔符的代码 sn-p

    char *knownWord = "anyword";
    ...
    while (fgets(line, maxLineLength, inputFile))
    {
        token = strtok(&line[0], ",");
        while (token) {
            inputArray[varCount] = token;
            varCount++;
            token = strtok(NULL, ",");
        }
        inputArray[varCount] = knownWord;
        varCount ++;
    }
    

为此,打印会发生类似的事情

    bool atKnownWord = 0;
    printf("[");
    for (i = 0; i < maxWords; i++) {
            if (inputArray[i] == NULL) {
                    break;
            }
            if (inputArray[i] == knownWord) {
                    atKnownWord = 1;
                    printf("]");
                    continue;
            }
            if (atKnownWord) {
                    atKnownWord = 0;
                    printf(", [");
            }
            printf("%s", inputArray[i]);
    }
    printf("]");

【讨论】:

  • 非常感谢@virtually-real 我把它放进去后更近了,但仍然不太正确。 (我不是想用括号打印出数组的表示,但你的代码仍然有帮助)。为了争论,按照你的建议打印出来我得到[PastaPizzareader], [PastaBreadButter Cherry], [Pasta Pizza Bread Butter]]。请问有什么想法吗?
  • @hardanger replace "printf("%s", inputArray[i]);"使用“printf(”%s“, inputArray[i]);”。注意 %s 后的空格
  • 非常感谢,但我认为问题更深一些,我奇怪地在错误的行中得到了 Cheery 例如输出,这就是我现在得到的:[Pasta Pizza read er -NEWLINE- ], [Pasta Bread Butter Cherry -NEWLINE-], [Pasta Pizza Bread Butter ]]
  • @hardanger 您的问题是多方面的。 1.您需要删除'\n'字符。检查stackoverflow.com/questions/2693776/…。 2. strtok() 对原始缓冲区进行操作,从而改变其原始输入。我建议您使用 strcpy() 或 strdup() 来复制“行”。当然,您需要释放新创建的缓冲区,但这是一个单独的主题。
  • 谢谢@virtually-real - 虽然这个改变肯定不会影响输出文本不正确的更广泛的问题,例如在我的问题中,输出应该开始[[Carrot, Potato, Beetroot,...而是开始[Pasta Pizza read er。请问有什么想法吗?
【解决方案2】:

您还没有分配内存来存储token
此外,您应该在将token 存储在数组中之后增加varCount

代码可以写成:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define maxLineLength 1000  //Maximum length of a line
#define wordsPerLine 200    //Maximum words in a line
#define maxLines 200        //Maximum lines in an input

int main(int argc, char *argv[])
{
    char line[maxLineLength] = {0};
    char *inputArray[maxLines][wordsPerLine] = {};
    char *ptr, *token;
    int i, j, lines, maxWords = 0;

    FILE *inputFile = fopen("input.txt", "r");

    if (inputFile)
    {
        i = j = 0;
        while (fgets(line, maxLineLength, inputFile))
        {
            token = strtok(&line[0], ",\n");
            while(token)
            {
                if(ptr = malloc(sizeof(char) * (strlen(token)+1))) //whether malloc succeeded
                {
                    if(token[0] == ' ')
                        strcpy(ptr, token+1);
                    else
                        strcpy(ptr, token);

                    inputArray[i][j++] = ptr;
                    token = strtok(NULL, ",\n");
                }
                else
                {
                    printf("malloc failed!\n");
                    exit(1);
                }
            }
            if(maxWords < j)
                maxWords = j;
            i++;
            j = 0;          
        } 
        lines = i;
        fclose(inputFile);

        for(i = 0; i < lines; i++)
        {
            for(j = 0; (j < maxWords) && inputArray[i][j]; j++)
                printf("%s | ", inputArray[i][j]);
            printf("\n");
        }
    }
    return 0;
}  

【讨论】:

  • 嗨@rootkea - 非常感谢您的回答。我试图实现这一点,但只是让你的后卫 malloc 失败!打印出。请问有什么我可能出错的地方吗?
  • @hardanger 你能用你试过的代码更新问题吗?
猜你喜欢
  • 2017-12-23
  • 1970-01-01
  • 2014-04-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-08-22
相关资源
最近更新 更多