欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C語言實(shí)現(xiàn)讀取CSV文件的方法詳解

 更新時(shí)間:2022年12月21日 14:35:35   作者:Brickie-liu  
這篇文章主要為大家詳細(xì)介紹了C語言如何實(shí)現(xiàn)讀取CSV文件,文中的示例代碼講解詳細(xì),具有一定的借鑒價(jià)值,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下

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ī)測(cè)試 初始化數(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;

}

//測(cè)試浮點(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)換失敗測(cè)試\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");   
}

//測(cè)試整數(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)換失敗測(cè)試\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;
}

到此這篇關(guān)于C語言實(shí)現(xiàn)讀取CSV文件的方法詳解的文章就介紹到這了,更多相關(guān)C語言讀取CSV內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • OpenCV選擇圖像中矩形區(qū)域并保存

    OpenCV選擇圖像中矩形區(qū)域并保存

    這篇文章主要為大家詳細(xì)介紹了OpenCV選擇圖像中矩形區(qū)域并保存的方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-01-01
  • C++ 流插入和流提取運(yùn)算符的重載的實(shí)現(xiàn)

    C++ 流插入和流提取運(yùn)算符的重載的實(shí)現(xiàn)

    這篇文章主要介紹了C++ 流插入和流提取運(yùn)算符的重載的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-12-12
  • 數(shù)據(jù)結(jié)構(gòu)之歸并排序的實(shí)例詳解

    數(shù)據(jù)結(jié)構(gòu)之歸并排序的實(shí)例詳解

    這篇文章主要介紹了數(shù)據(jù)結(jié)構(gòu)之歸并排序的實(shí)例詳解的相關(guān)資料,這里對(duì)歸并排序進(jìn)行詳細(xì)介紹,需要的朋友可以參考下
    2017-08-08
  • C語言中實(shí)現(xiàn)KMP算法的實(shí)例講解

    C語言中實(shí)現(xiàn)KMP算法的實(shí)例講解

    KMP算法即字符串匹配算法,C語言中KMP可以避免指針回溯從而達(dá)到高效,接下來就來總結(jié)一下C語言中實(shí)現(xiàn)KMP算法的實(shí)例講解
    2016-06-06
  • C++基礎(chǔ)學(xué)習(xí)之利用兩個(gè)棧實(shí)現(xiàn)一個(gè)隊(duì)列

    C++基礎(chǔ)學(xué)習(xí)之利用兩個(gè)棧實(shí)現(xiàn)一個(gè)隊(duì)列

    這篇文章主要給大家介紹了關(guān)于C++基礎(chǔ)學(xué)習(xí)之利用兩個(gè)棧實(shí)現(xiàn)一個(gè)隊(duì)列的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用C++具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-05-05
  • C++封裝靜態(tài)鏈接庫和使用的詳細(xì)步驟

    C++封裝靜態(tài)鏈接庫和使用的詳細(xì)步驟

    這篇文章主要介紹了C++封裝靜態(tài)鏈接庫和使用,本文描述了怎么去把一個(gè)C++程序封裝成一個(gè)靜態(tài)庫并且如何去使用這些靜態(tài)庫,需要的朋友可以參考下
    2022-08-08
  • 詳情介紹C++之命名空間

    詳情介紹C++之命名空間

    這篇文章主要詳情介紹了C++命名空間,命名空間的出現(xiàn)就是為了解決名稱沖突問題,對(duì)此感興趣的朋友可以參考下面文章
    2021-09-09
  • c++基礎(chǔ)語法:構(gòu)造函數(shù)初始化列表

    c++基礎(chǔ)語法:構(gòu)造函數(shù)初始化列表

    構(gòu)造函數(shù)需要初始化的數(shù)據(jù)成員,不論是否顯示的出現(xiàn)在構(gòu)造函數(shù)的成員初始化列表中,都會(huì)在該處完成初始化,并且初始化的順序和其在聲明時(shí)的順序是一致的,與列表的先后順序無關(guān)
    2013-09-09
  • C++重載的奧義之函數(shù)重載詳解

    C++重載的奧義之函數(shù)重載詳解

    函數(shù)重載是C++多態(tài)(靜態(tài)多態(tài))的特征體現(xiàn),它可以允許重復(fù)使用同一個(gè)函數(shù)名(籃子)的函數(shù),但是函數(shù)的參數(shù)列表(籃子裝的東西)是可以不一樣的。下面就簡(jiǎn)單講講C++中函數(shù)重載的相關(guān)應(yīng)用吧
    2023-04-04
  • C++使用Kruskal和Prim算法實(shí)現(xiàn)最小生成樹

    C++使用Kruskal和Prim算法實(shí)現(xiàn)最小生成樹

    這篇文章主要介紹了C++使用Kruskal和Prim算法實(shí)現(xiàn)最小生成樹,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-01-01

最新評(píng)論