怎么将csv数据导入c或c++中的数组中,希望给实例
怎么将csv数据导入c或c++中的数组中,希望给实例 网上使用 c调用csv源码几乎没有一定要用c.的话,就得自己想办法了 csv 文件是纯文本文件,用逗号,换行符分割的纯文本文件,逗号分割列,换行符号分割行,处理起来非常简单。
C 的话用链表处理比较方便,因为行、列未知,需动态分配内存。
typedefstruct tagCSVFile
{
char *context; //字符串指针存储内容
intflag; //换行标志
struct tagCSVFile * next;
}CSV,*LPCSV;
c++ 的话用vector<vector<string> >array;存储非常方便。
简单流程如下
读入一段字符,查找逗号',' 和回车换行 \n\r,
如果找到逗号,则把逗号之前的字符串作为数组的一个元素。
继续查找下一个逗号和回车换行,找到回车换行则把回车换行符之前的字符串作为数组的一个元素,并对数组做换行处理。
处理完毕,继续读取下一段字符,重复之前的动作,直到文件结束。 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
先上代码测试, 然后再解释{: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:}, 倒不是说逻辑上有多难, 那个三级指针就调试了挺久的
fopen 然后 fscanf 不就行了
页:
[1]