網(wǎng)站首頁 編程語言 正文
1、每一次只能讀取同一種數(shù)據(jù)類型,不能讀取字符串。
2、第次讀取會(huì)返回一個(gè) CSV數(shù)據(jù)結(jié)構(gòu),有源數(shù)據(jù)和二維數(shù)組,行列數(shù)信息
3、可以轉(zhuǎn)換二維數(shù)組,但總大小不能變
123.csv
Month,"CO2 (ppm) mauna loa, 1965-1980",,,CO2 (ppm) mauna loa
Jan-65,319.32,1,,,
Feb-65,320.36,2,,,
Mar-65,320.82,3,,,
Apr-65,322.06,4,,,
May-65,322.17,5,,,
Jun-65,321.95,6,,,
頭文件 read_csv_data.h
#include <stdio.h>
#include <memory.h> // for memset
#include <stdlib.h> // for malloc, free
#include <string.h> // for strtok
//fgets函數(shù)讀取的最大字節(jié)數(shù)
#define MAX_LINE_SIZE 1024
//字符串分割結(jié)構(gòu)
struct str_split
{
int count;
char *str;
char **str_array;
};
//可變數(shù)據(jù)類型
typedef union dtype_u{
long int s32;
char s8;
short int s16;
unsigned char u8;
unsigned short int u16;
unsigned long int u32;
float f32;
double f64;
} Dtype;
//CSV文件結(jié)構(gòu)
struct csv_s{
Dtype **darray; //二維數(shù)組
int drow;
int dcol;
int dnum; //總有多少個(gè)
Dtype data[];
};
enum{
S8,
S16,
S32,
U8,
U16,
U32,
F32,
F64,
DEF = S32
};
/*
釋放CSV文件結(jié)構(gòu),使用方法,查看testFile()
*/
void FreeCsvData(struct csv_s **csv_ptr);
/*
對(duì)CSV數(shù)據(jù)進(jìn)行二維轉(zhuǎn)換,生成新的二維數(shù)據(jù)。使用方法,查看testFile()
*/
int setNewArray( struct csv_s *tt, int row, int col);
/*
讀取CSV文件數(shù)據(jù),生成CSV結(jié)構(gòu)。使用方法,查看testFile()
csvFilePath:文件路徑
delimiter: 分割符
skiprows: 跳過頭N行
ColumnList:選把指定列,從0列開始,
dclass: 數(shù)據(jù)類型
*/
struct csv_s *ReadCsvData(char* csvFilePath, char delimiter, int skiprows, char *ColumnList, int dclass);
源碼 read_csv_data.c
#include "read_csv_data.h"
int str_split_func(struct str_split *split, char * src, char delimiter)
{
int count = 0;
char *pchar, **ptr;
if ( NULL != split ) {
memset(split, 0, sizeof(struct str_split));
}
if(NULL == split || NULL == src || src[0] == '\0')
{
return 0;
}
split->str = strdup(src);
if(NULL == split->str)
{
return 0;
}
count = 1;
pchar = src;
while('\0' != *pchar)
{
if (delimiter == *pchar)
{
count++;
}
pchar++;
}
split->str_array = (char **)malloc(count*sizeof(char*));
if(NULL == split->str_array)
{
return 0;
}
split->count = count;
ptr = split->str_array;
*ptr = split->str;
pchar = split->str;
while('\0' != *pchar && count > 1)
{
if (delimiter == *pchar)
{
ptr++;
*ptr = pchar+1;
*pchar = '\0';
count--;
}
pchar++;
}
return 0;
}
int str_split_free(struct str_split *split)
{
if(split == NULL)
{
return 0;
}
if(split->str!=NULL)
{
free(split->str);
split->str=NULL;
}
if(split->str_array != NULL)
{
free(split->str_array);
split->str_array=NULL;
}
return 0;
}
//計(jì)算csv文件中的總大小(字節(jié))
int GetTotalSize(FILE * fp)
{
if(fp==NULL){
return -1;
}
fseek(fp,0,SEEK_END);
return ftell(fp);
}
//計(jì)算csv文件中的總行數(shù)
int GetTotalLineCount(FILE * fp)
{
int i = 0;
char strLine[MAX_LINE_SIZE];
fseek(fp,0,SEEK_SET);
while (fgets(strLine, MAX_LINE_SIZE, fp))
i++;
fseek(fp,0,SEEK_SET);
return i;
}
//計(jì)算csv文件中的總列數(shù)(以第一行的列數(shù)為基準(zhǔn))
int GetTotalColCount(FILE * fp, char delimiter)
{
int i = 0;
char strLine[MAX_LINE_SIZE];
struct str_split tss;
fseek(fp,0,SEEK_SET);
char *str=NULL;
str = fgets(strLine, MAX_LINE_SIZE, fp);
if (str)
{
str_split_func(&tss, strLine, delimiter);
i = tss.count;
str_split_free(&tss);
}
return i;
}
// 通過指針*giCsvData給數(shù)據(jù)動(dòng)態(tài)分配內(nèi)存空間
int strToData(Dtype *d, char *str, int dtpye)
{
switch(dtpye){
case S8:
*((char *)d) =(char) strtol(str,NULL,10);
break;
case S16:
*((short int *)d) =(short int) strtol(str,NULL,10);
break;
case S32:
*((long int *)d) =(long int) strtol(str,NULL,10);
break;
case U8:
*((unsigned char *)d) =(unsigned char ) strtol(str,NULL,10);
break;
case U16:
*((unsigned short int *)d) =(unsigned short int) strtol(str,NULL,10);
break;
case U32:
*((unsigned long int *)d) =(unsigned long int) strtol(str,NULL,10);
break;
case F32:
*((float *)d) =(float) strtod(str,NULL);
break;
case F64:
*((double *)d) =(double) strtod(str,NULL);
break;
default:
printf("讀取數(shù)據(jù)類型不對(duì)\n");
return -1;
}
return 0;
}
// 對(duì)CSV結(jié)構(gòu)中的二維數(shù)組進(jìn)行轉(zhuǎn)換
int setNewArray( struct csv_s *tt, int row, int col)
{
int i;
//CSV結(jié)構(gòu)不NULL
if(tt == NULL)return -1;
//新的行列總個(gè)數(shù),與舊的數(shù)據(jù)個(gè)數(shù)不等
if(row * col != tt->dnum)return -2;
Dtype **darray=(Dtype **)malloc( sizeof(Dtype *[row]) );
//分配內(nèi)存空間失敗,出錯(cuò)的可能性不大
if(!darray)return -3;
if(tt->darray)free(tt->darray);
tt->drow = row;
tt->dcol = col;
tt->dnum = row * col;
tt->darray = darray;
for(i=0; i<row; i++){
tt->darray[i]=(Dtype *)(tt->data+i*col);
}
return 0;
}
// 釋放動(dòng)態(tài)數(shù)據(jù)內(nèi)存
void FreeCsvData(struct csv_s **csv_ptr)
{
if(*csv_ptr){
if((*csv_ptr)->darray)
free((*csv_ptr)->darray);
free(*csv_ptr);
}
*csv_ptr=NULL;
return ;
}
// 從csv文件中讀取數(shù)據(jù)
struct csv_s *ReadCsvData(char* csvFilePath, char delimiter, int skiprows, char *ColumnList, int dclass)
{
/*
delimiter:分割符
dtype:數(shù)據(jù)類型,多個(gè)數(shù)據(jù)類型使用逗號(hào)分割,從第一列到最后一列開始一一對(duì)應(yīng)。默認(rèn)其他的是float 類型。
例:有5列 dtype=“str, str, str” 則前三列為string類型,后兩列為float類型
skiprows:跳過開頭N行
ColumnList:取N列數(shù)據(jù)。
例:"2,1,3",取第 2,1,3列數(shù)據(jù)返回
*/
FILE* fCsv=NULL;
int rowTotal=0;
int colTotal=0;
struct str_split tss;
struct csv_s *temp_csv=NULL;
int cur_ptr=0;
char strLine[MAX_LINE_SIZE];
int i;
int j;
//獲取指定列
int t_column_list=0;
int *t_column_list_ptr=NULL;
if(access(csvFilePath, 0)<0){
printf("%s 文件不存在\n", csvFilePath);
goto label_error;
}
// 打開文件
fCsv = fopen( csvFilePath, "r" );
if( fCsv==NULL )
{
printf("open file %s failed",csvFilePath);
goto label_error;
}
rowTotal = GetTotalLineCount(fCsv);
colTotal = GetTotalColCount(fCsv, delimiter);
//獲取指定列
if(ColumnList==NULL){
t_column_list=colTotal;
t_column_list_ptr = malloc(sizeof(t_column_list) * t_column_list);
for(i=0;i<tss.count;i++){
t_column_list_ptr[i]=i;
}
}else{
str_split_func(&tss, ColumnList, ',');
t_column_list = tss.count;
t_column_list_ptr = malloc(sizeof(t_column_list) * t_column_list);
for(i=0;i<tss.count;i++){
t_column_list_ptr[i]=strtol(tss.str_array[i], NULL, 10);
}
str_split_free(&tss);
//檢查參數(shù)ColumnList
if (t_column_list>colTotal){
printf("[%s] 超過最大列數(shù) %d\n", ColumnList, colTotal);
goto label_error;
}
for(i=0; i<t_column_list; i++){
if(t_column_list_ptr[i] > colTotal){
printf("[%s] 超過最大列數(shù) %d\n", ColumnList, colTotal);
goto label_error;
}
}
}
//檢查是否超過,最大列數(shù)
if(rowTotal <1 || colTotal <1 || skiprows>rowTotal){
printf("數(shù)據(jù)不對(duì),有%d行,%d列\(zhòng)n", rowTotal, colTotal);
goto label_error;
}
//分配內(nèi)在空間
rowTotal = rowTotal - skiprows;
temp_csv = (struct csv_s *)malloc(sizeof(struct csv_s) + (rowTotal * t_column_list)*sizeof(Dtype));
if(!temp_csv){
printf("分配內(nèi)存失敗 \n");
goto label_error;
}
// 讀取數(shù)據(jù)
i = skiprows;
fseek(fCsv, 0, SEEK_SET);
//跳過開頭N行
while(i>0 && fgets(strLine,MAX_LINE_SIZE,fCsv) )i--;
i = rowTotal;
while( i>=0 && fgets(strLine,MAX_LINE_SIZE,fCsv)){
//printf("%d %s\n", i, strLine);
i--;
str_split_func(&tss, strLine, delimiter);
if(t_column_list > tss.count){
printf("read error\n");
goto label_error;
}
int t_res = 0;
for(j=0; j<t_column_list; j++){
t_res = strToData(temp_csv->data+cur_ptr, tss.str_array[t_column_list_ptr[j]], dclass);
if(t_res < 0){
printf("str to data error\n");
goto label_error;
}
cur_ptr++;
}
str_split_free(&tss);
}
temp_csv->drow = rowTotal;
temp_csv->dcol = t_column_list;
temp_csv->dnum = rowTotal * t_column_list;
//printf("%d %d %d\n", i, rowTotal, t_column_list);
//for(i=0;i<temp_csv->dnum; i++)
// printf("%d ", temp_csv->data[i].s32);
//temp_csv->dtype = dtype;
temp_csv->darray=NULL;
setNewArray(temp_csv,temp_csv->drow, temp_csv->dcol);
// 關(guān)閉文件
fclose(fCsv);
free(t_column_list_ptr);
return temp_csv;
label_error:
if(fCsv)fclose(fCsv);
if(temp_csv)free(temp_csv);
if(t_column_list_ptr)free(t_column_list_ptr);
return NULL;
}
int testData()
{
int size=1000;
//分配內(nèi)存空間
struct csv_s *stdata=(struct csv_s *)malloc(sizeof(struct csv_s) + size*sizeof(Dtype));
int i;
//初始化數(shù)據(jù)
for(i=900; i<size; i++){
// *((long int *)(stdata->data+i)) = i;
*((double *)(stdata->data+i)) = i*1.0;
}
//隨機(jī)測試 初始化數(shù)據(jù)
*((double *)(stdata->data+1)) = 10*1.0;
printf("%f asdfasfasdf\n", *((double *)(stdata->data+1)));
//初始化結(jié)構(gòu)
int row = 500;
int col = 2;
stdata->drow= row;
stdata->dcol = col;
//stdata->dtype = sizeof(Dtype);
stdata->dnum = row * col;
int j=0;
j = setNewArray(stdata,row, col);
if(j<0){
printf("setNewArray %d error\n", j);
return 0;
}
//顯示結(jié)構(gòu)數(shù)據(jù)
printf("顯示定義結(jié)構(gòu)最后一行數(shù)據(jù) \n");
for(j=0; j<col; j++){
printf("%f\n", stdata->darray[row-1][j].f64);
}
//結(jié)構(gòu)轉(zhuǎn)換
row = 100;
col = 10;
j = setNewArray(stdata,row, col);
if(j<0){
printf("setNewArray 轉(zhuǎn)換 %d error\n", j);
return 0;
}
printf("顯示結(jié)構(gòu)轉(zhuǎn)換最后一行數(shù)據(jù) \n");
//顯示結(jié)構(gòu)數(shù)據(jù)
for(j=0; j<col; j++){
printf("%f\n", stdata->darray[row-1][j].f64);
}
return 0;
}
//測試浮點(diǎn)數(shù)
void testFile()
{
struct csv_s *stdata;
//stdata = ReadCsvData("123.csv", ',', 1, "1,2", F32);
stdata = ReadCsvData("123.csv", ',', 1, "2,1", F32);
printf("testFile row %d col %d\n", stdata->drow, stdata->dcol);
int i, j;
//單獨(dú)以Dtype顯示數(shù)據(jù),是一個(gè)二維數(shù)組,以stdata->drow, stdata->dcol為行,列:Dtype show[stdata->drow][stdata->dcol]
Dtype ** show = stdata->darray;
printf("顯示最后一行數(shù)據(jù) \n");
for(j=0; j<stdata->dcol; j++){
printf("%f\n", show[stdata->drow-1][j].f32);
}
//結(jié)構(gòu)轉(zhuǎn)換
int row = 3;
int col = 4;
j = setNewArray(stdata,row, col);
if(j<0){
printf("setNewArray 轉(zhuǎn)換 %d error\n", j);
}else{
//顯示結(jié)構(gòu)數(shù)據(jù)
printf("顯示結(jié)構(gòu)轉(zhuǎn)換最后一行數(shù)據(jù) \n");
for(j=0; j<col; j++){
printf("%f\n", stdata->darray[row-1][j].f32);
}
}
printf("轉(zhuǎn)換失敗測試\n");
//結(jié)構(gòu)轉(zhuǎn)換
row = 3;
col = 2;
j = setNewArray(stdata,row, col);
if(j<0){
printf("setNewArray 轉(zhuǎn)換 %d error\n", j);
}
//釋放內(nèi)存
FreeCsvData(&stdata);
if(stdata==NULL)
printf("ok t is null\n");
else
printf("ok t is not null\n");
}
//測試整數(shù)類型
void testFile2()
{
struct csv_s *stdata;
//stdata = ReadCsvData("123.csv", ',', 1, "1,2", F32);
stdata = ReadCsvData("123.csv", ',', 1, "2,1", DEF);
printf("testFile row %d col %d\n", stdata->drow, stdata->dcol);
int i, j;
//單獨(dú)以Dtype顯示數(shù)據(jù),是一個(gè)二維數(shù)組,以stdata->drow, stdata->dcol為行,列:Dtype show[stdata->drow][stdata->dcol]
//注意:這個(gè)默認(rèn)long int 數(shù)據(jù)類型
Dtype ** show = stdata->darray;
printf("顯示最后一行數(shù)據(jù) \n");
for(j=0; j<stdata->dcol; j++){
printf("%d\n", show[stdata->drow-1][j]);
}
//結(jié)構(gòu)轉(zhuǎn)換
int row = 3;
int col = 4;
j = setNewArray(stdata,row, col);
if(j<0){
printf("setNewArray 轉(zhuǎn)換 %d error\n", j);
}else{
//顯示結(jié)構(gòu)數(shù)據(jù)
printf("顯示結(jié)構(gòu)轉(zhuǎn)換最后一行數(shù)據(jù) \n");
for(j=0; j<col; j++){
printf("%d\n", stdata->darray[row-1][j]);
}
}
printf("轉(zhuǎn)換失敗測試\n");
//結(jié)構(gòu)轉(zhuǎn)換
row = 3;
col = 2;
j = setNewArray(stdata,row, col);
if(j<0){
printf("setNewArray 轉(zhuǎn)換 %d error\n", j);
}
//釋放內(nèi)存
FreeCsvData(&stdata);
if(stdata==NULL)
printf("ok t is null\n");
else
printf("ok t is not null\n");
}
int main(int args, char *argv)
{
// testData();
testFile();
testFile2();
return 0;
}
原文鏈接:https://blog.csdn.net/liuzhuchen/article/details/78602851
相關(guān)推薦
- 2022-09-21 Shell自動(dòng)化配置SSH免密登錄和取消SSH免密配置腳本_linux shell
- 2022-12-08 用C語言求解一元二次方程的簡單實(shí)現(xiàn)_C 語言
- 2022-07-21 微信小程序--動(dòng)態(tài)設(shè)置導(dǎo)航欄顏色
- 2022-06-18 使用OpenGL創(chuàng)建窗口的示例詳解_C 語言
- 2022-05-21 C#對(duì)DataTable中的某列進(jìn)行分組_C#教程
- 2022-08-15 oracle數(shù)據(jù)庫表實(shí)現(xiàn)自增主鍵的方法實(shí)例_oracle
- 2022-05-19 python?字典常用方法超詳細(xì)梳理總結(jié)_python
- 2023-06-18 Python實(shí)現(xiàn)將內(nèi)容轉(zhuǎn)為base64編碼與解碼_python
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細(xì)win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運(yùn)行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲(chǔ)小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運(yùn)算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認(rèn)證信息的處理
- Spring Security之認(rèn)證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯(cuò)誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實(shí)現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡單動(dòng)態(tài)字符串(SD
- arthas操作spring被代理目標(biāo)對(duì)象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊(duì)列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠(yuǎn)程分支