Aseeker 发表于 2021-2-6 00:02:00

怎么将csv数据导入c或c++中的数组中,希望给实例

怎么将csv数据导入c或c++中的数组中,希望给实例

wp231957 发表于 2021-2-6 06:44:05

网上使用 c调用csv源码几乎没有
一定要用c.的话,就得自己想办法了

xieglt 发表于 2021-2-6 09:02:52

csv 文件是纯文本文件,用逗号,换行符分割的纯文本文件,逗号分割列,换行符号分割行,处理起来非常简单。
C 的话用链表处理比较方便,因为行、列未知,需动态分配内存。

typedefstruct tagCSVFile
{
   char *context;   //字符串指针存储内容
   intflag;            //换行标志
   struct tagCSVFile * next;      
}CSV,*LPCSV;


c++ 的话用vector<vector<string> >array;存储非常方便。
简单流程如下
读入一段字符,查找逗号',' 和回车换行 \n\r,
如果找到逗号,则把逗号之前的字符串作为数组的一个元素。
继续查找下一个逗号和回车换行,找到回车换行则把回车换行符之前的字符串作为数组的一个元素,并对数组做换行处理。
处理完毕,继续读取下一段字符,重复之前的动作,直到文件结束。

赚小钱 发表于 2021-2-6 09:33:32

csv 文件不就是使用 "," 做列分割,使用 "\n" 做行分割的 txt 文件吗
所以,先写一个
char** split(const char* str, const char* sep)
来切分字符串,然后

const char * input = "";
char** lines = split(input, "\n")
for (char* line = *lines; line != NULL; line++) {
    char** colunms = split(line, ",")
}

FYI:
https://github.com/p-ranav/csv2
https://github.com/ben-strasser/fast-cpp-csv-parser
https://github.com/vincentlaucsb/csv-parser
https://github.com/rgamble/libcsv

PC_ 发表于 2021-2-7 09:50:26

先上代码测试, 然后再解释{:10_257:}

/*
      used: UTF-8
*/
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <string.h>

int main(void)
{
      char ***data = NULL;                //储存所读取的数据---实际上可以翻译为:(*data)[][], 即储存字符串的二维数组
      FILE *fp;                                        //要读取的文件指针
      int i, j, k = 0;                        //计数器
      int temp;                                        //临时数据
      char gets_test = '\0';                //读取的字符
      int lines = 1;                              //被读取文件的行数

      //打开文件
      if ((fp = fopen("test.csv", "r")) == NULL)
      {
                return -1;
      }

      //读取文件的行数
      while (!feof(fp))
      {
                gets_test = fgetc(fp);
                if (gets_test == '\n')
                {
                        lines++;
                }
      }
      gets_test = '\0';                        //将字符清空, 以便后面的判断
      rewind(fp);                                        //回到文件开始位置

      int num;                              //文件中每行数据的个数
      //初始化
      for (i = 0; i < lines; i++)
      {
                num = 1;
      }

      //读取文件中每行数据的个数
      for (i = 0; i < lines; i++)
      {
                while (gets_test != '\n')
                {
                        gets_test = fgetc(fp);
                        if (gets_test == ',')
                        {
                              num++;
                        }
                        if (gets_test == EOF)
                        {
                              goto exits;                        //如果读取到文件末, 则直接跳转到exits继续进行下一步
                        }
                }
                gets_test = '\0';                        //对读取到的字符进行重置, 避免因读到'\n'而导致无法读取下一行
      }
exits:
      rewind(fp);                                       //回到文件开始位置

      int num_max;                                        //文件中, 在所有行中, 每行数据个数最多的值
      int temp_num;                        //每行数据个数的临时数据

      //将数据复制到临时数据中, 以便进行
      memcpy(temp_num, num, sizeof(int) * lines);

      //当文件行数超过一行时, 对数据个数进行排序, 得出最大值[此处使用降序]
      if (lines > 1)
      {
                for (i = 1; i <= lines; i++)
                {
                        for (j = 0; j < lines; j++)
                        {
                              if (temp_num < temp_num)
                              {
                                        temp = temp_num;
                                        temp_num = temp_num;
                                        temp_num = temp;
                              }
                        }
                }

                num_max = temp_num;
      }
      else
      {
                num_max = num;                              //当文件只有一行时, 最大值就是当前行的数据个数
      }

      //每行每个数据的具体大小, 这里直接设置每行数据个数的最大值
      //当然, 这里设置成指针再进行其他操作也行, 不过复杂度就相对较高了
      int test;

      //对数组进行初始化
      for (i = 0; i < lines; i++)
      {
                for (j = 0; j < num_max; j++)
                {
                        test = 0;
                }
      }

      //读取数据
      for (i = 0; i < lines; i++)
      {
                gets_test = ' ';
                for (j = 0; (gets_test != '\n' && gets_test != EOF);j++)
                {
                        gets_test = fgetc(fp);
                        if (gets_test == ',' || gets_test == '\n' || gets_test == EOF)
                        {
                              test = j;
                              j = -1;                                                      //这里之所以为-1是因为for循环会多加一个1
                              if (k < (num - 1))                        //这里防止数组越界
                              {
                                        k++;
                              }
                        }
                }
                k = 0;                                                                        //当i发生变化时, 需要对k进行重置, 否则将无法读取下一行与当前数据同样位置的数据z
      }
      rewind(fp);

      //对data进行动态申请内存, 以尽量不浪费内存
      data = (char ***)malloc(sizeof(char ***) * lines);
      for (i = 0; i < lines; i++)
      {
                data = (char **)malloc(sizeof(char **) * num);
                for (j = 0; j < num; j++)
                {
                        data = (char *)malloc(sizeof(char *) * (test));
                }
      }

      //对申请的内存进行初始化, 以防乱码等情况
      for (i = 0; i < lines; i++)
      {
                for (j = 0; j < num; j++)
                {
                        for (k = 0; k < test; k++)
                        {
                              memset(data, 0, sizeof(char *) * (test));
                        }
                }
      }

      //读取信息并储存到data中
      for (i = 0; i < lines; i++)
      {
                //将num作为临时数据
                temp = num;
                //对读取到的数据个数进行判断后再读取
                for (j = 0; temp > 0; j++)
                {
                        //重置k以免因特殊字符而导致多读取或少读取的情况
                        k = 0;
                        for (k = 0; k < test; k++)
                        {
                              gets_test = fgetc(fp);
                              if (gets_test != ',' && gets_test != '\n')
                              {
                                        data = gets_test;
                              }
                              else
                              {
                                        //当读取到的数据为特殊字符时, 对k进行赋值
                                        //这里之所以是-1也是因为for循环的问题, 循环结束后会执行k++, 易导致读取的数据不完整
                                        k = -1;
                              }
                        }
                        //当前行当前个数的数据读取完之后, 进行赋值, 以便判断, 防止造成数组越界等情况
                        temp--;
                }
      }
      
      //打印读取到的数据并确认
      for (i = 0; i < lines; i++)
      {
                for (j = 0; j < num; j++)
                {
                        printf("%s ", data);
                }
                putchar(10);
      }

      fclose(fp);                //关闭文件
      free(data);                //释放data

      getch();
      return 0;
}
实例如下:
第一次调试:
1,2,3,4,5,6,7,8,9,10,11,12
q,w,e,r,t,y,u,i,o,p,a,[,]
"?????","it's too dificult!!!","make it isn't so easy!"
输出:
1 2 3 4 5 6 7 8 9 10 11 12
q w e r t y u i o p a [ ]
"?????" "it's too dificult!!!" "make it isn't so easy!"
原谅我等级不够没法上传图片{:10_266:}备注:GCC 4.8.1编译通过, 汉字会出现乱码, 因为汉字是占两个字节的, 而本程序是一个字节一个字节读的

吐槽一下:这个东西是真的难写{:10_277:}, 倒不是说逻辑上有多难, 那个三级指针就调试了挺久的

永恒的蓝色梦想 发表于 2021-2-8 14:13:23

fopen 然后 fscanf 不就行了
页: [1]
查看完整版本: 怎么将csv数据导入c或c++中的数组中,希望给实例