c++ 讀取數值文件到數組中


  做數據處理時經常會用讀這樣的文本文件:

1,10,1,11,1,13,1,12,1,1,9
2,11,2,13,2,10,2,12,2,1,9
3,12,3,11,3,13,3,10,3,1,9
4,10,4,11,4,1,4,13,4,12,9
4,1,4,13,4,12,4,11,4,10,9
1,2,1,4,1,5,1,3,1,6,8
1,9,1,12,1,10,1,11,1,13,8
2,1,2,2,2,3,2,4,2,5,8
3,5,3,6,3,9,3,7,3,8,8
4,1,4,4,4,2,4,3,4,5,8 

  有時候每一行的數據個數也不是確定的,但我們想按行保存在數組或vector(list)中,這么久以來用習慣了java的readLine()和split(","),突然用c++,感覺到寸步難行,於是自己寫了一個函數,用c++讀取數值文件。

/*
*讀取絕對路徑為filePath的文件,文件中每行中的數值以tag字符分開
*返回vector<vector<string>>格式的數據
*/
vector<vector<string>> readFile(char tag,string filePath){
    ifstream fileReader;
    fileReader.open(filePath,ios::in);//以只讀方式打開
    vector<vector<string>> data;//以2維向量的形勢保持整個文件
    while(!fileReader.eof()){//未到文件末尾    
        string linestring;
        getline(fileReader,linestring);//讀取一行
        vector<string> line = split(linestring,tag);//分割每行,並放在line向量中    
        data.push_back(line);
    }    
    return data;    
}
readFile()函數讀取文件,其中調用了一個split()函數,用於將一個string類型的字符串分割為字符串向量,實現如下:
/*
*對字符串inputString按tag字符分割
*返回vector<string>格式的一維向量
*/
vector<string> split(string inputString,char tag){
    int length = inputString.length();
    int start=0;//數值起始下標
    vector<string> line;
    for(int i=0;i<length;i++){
        if(inputString[i] == tag){//遇到tag字符
            string sub = inputString.substr(start,i-start);    //取inputString[start]-inputString[i]子串
            line.push_back(sub);//壓入向量中
            start =  i+1;            
        }else if(i==length-1){
            string sub = inputString.substr(start,i-start+1);//最后一個字符沒有標點,需單獨處理
            line.push_back(sub);//壓入向量中
        }
    }
    return line;
}

  調用readFile()函數就可以將文件以vector<vector<string>>類型讀入內存。但既然是數值,我們肯定要進行計算,字符串數組對我們還是沒有,需要轉化為數值類型vector<vector<int或double或float>>,這里寫了一個轉行函數:

/*
*將inputString轉化成數值型,利用模板,實現復用
*/
template <typename T>
void transToNum(string inputString,T *result){    
    const char *p = inputString.c_str();
    char * type = getType(*result);
    if(type== "int")
        *result =  atoi(p);
    else if(type== "double")
        *result =   atof(p);
    else if(type== "float")
        *result =   atof(p);
}

這里利用模板實現了復用,為了能在運行時知道變量的值,c++里面沒有getClass(),所有只有自己寫了,這里寫了一個getType()函數:

char * getType(int x){//返回整數類型    
    return "int";    
}
char * getType(double x){//返回double類型    
    return "double";
}
char * getType(float x){//返回float類型    
    return "float";
}

這樣最終能得到vector<vector<int或double或float>>類型的數據,進行你想要的處理。

以下測試部分和完整代碼:

#include <iostream>
#include <vector>
#include <fstream>
#include <string>
#include <ctime>
using namespace std;
vector<vector<string>> readFile(char tag,string filePath);
vector<string> split(string inputString,char tag);
template <typename T>
void transToNum(string inputString,T *result);

/*
*讀取絕對路徑為filePath的文件,文件中每行中的數值以tag字符分開
*返回vector<vector<string>>格式的數據
*/
vector<vector<string>> readFile(char tag,string filePath){
    ifstream fileReader;
    fileReader.open(filePath,ios::in);//以只讀方式打開
    vector<vector<string>> data;//以2維向量的形勢保持整個文件
    while(!fileReader.eof()){//未到文件末尾    
        string linestring;
        getline(fileReader,linestring);//讀取一行
        vector<string> line = split(linestring,tag);//分割每行,並放在line向量中    
        data.push_back(line);
    }    
    return data;    
}
/*
*對字符串inputString按tag字符分割
*返回vector<string>格式的一維向量
*/
vector<string> split(string inputString,char tag){
    int length = inputString.length();
    int start=0;//數值起始下標
    vector<string> line;
    for(int i=0;i<length;i++){
        if(inputString[i] == tag){//遇到tag字符
            string sub = inputString.substr(start,i-start);    //取inputString[start]-inputString[i]子串
            line.push_back(sub);//壓入向量中
            start =  i+1;            
        }else if(i==length-1){
            string sub = inputString.substr(start,i-start+1);//最后一個字符沒有標點,需單獨處理
            line.push_back(sub);//壓入向量中
        }
    }
    return line;
}

char * getType(int x){//返回整數類型    
    return "int";    
}
char * getType(double x){//返回double類型    
    return "double";
}
char * getType(float x){//返回float類型    
    return "float";
}
/*
*將inputString轉化成數值型,利用模板,實現復用
*/
template <typename T>
void transToNum(string inputString,T *result){    
    const char *p = inputString.c_str();
    char * type = getType(*result);
    if(type== "int")
        *result =  atoi(p);
    else if(type== "double")
        *result =   atof(p);
    else if(type== "float")
        *result =   atof(p);
}

int main(){
    string filePath ="E:\\學習\\機器學習\\Poker_hand\\train.data";
    time_t now;
    now = time(NULL);//設置開始時間
    cout<<now<<endl;
    vector<vector<string>> data = readFile(',',filePath);//讀文件
    now = time(NULL);//讀完時間
    cout<<now<<endl;
    //////////////////將讀到的vector<vector<string>>轉化為vector<vector<int>>或vector<vector<double>>///////////
    vector<vector<int>> intdata;
    vector<vector<string>>::iterator iter =  data.begin();
    for(;iter != data.end();iter++){
        vector<string> line = *iter;
        vector<string>::iterator lineiter =  line.begin();
        vector<int> intline;
        for(;lineiter != line.end();lineiter++){
            int result;
            transToNum(*lineiter,&result);
            intline.push_back(result);    
        }
        intdata.push_back(intline);
    }
    ////////////////遍歷intdata,輸出數值化的數據////////////////////////////////////////////
    vector<vector<int>>::iterator intIter =  intdata.begin();
    for(;intIter != intdata.end();intIter++){
        vector<int> line = *intIter;
        vector<int>::iterator lineiter =  line.begin();        
        for(;lineiter != line.end();lineiter++){            
            cout<<*lineiter<<" ";            
        }        
        cout<<endl;
    }    
    return 1;//main
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM