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
}

 

posted @ 2013-04-04 18:37 CodeMeals 阅读(...) 评论(...) 编辑 收藏
reliable statistics
Visitors