C++ Read matrices from file with multiple delimiters
所以我得到了一个包含十个矩阵的文件,我想从文件中读取这些矩阵,并将它们保存到向量/数组中,每个矩阵都存储在向量或数组中。但是,这些矩阵的格式使我很难读取数据(我不擅长从输入文件中读取)。
文件的格式如下。每个矩阵的元素用","分隔。每一行用";"分隔,每一个矩阵用""分隔。例如,三个2乘2矩阵如下。
1,2;3,4 0,1;1,0 5,3;3,1|
我只想把矩阵保存到三个不同的向量中,但我不知道该怎么做。
我试过
1 2 3 4 5 6 7 | while(getline(inFile,line)){ stringstream linestream(line); string value; while(getline(linestream, value, ','){ //save into vector } } |
但这显然非常粗糙,只能用逗号分隔数据。有没有办法用多个分隔符来分隔数据?
谢谢您!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | string line; while(getline(infile, line, '|')) { stringstream rowstream(line); string row; while(getline(rowstream, row, ';')) { stringstream elementstream(row); string element; while(getline(elementstream, element, ',')) { cout << element << endl; } } } |
使用上述代码,您可以根据自己的喜好构建逻辑来存储单个
我使用这个函数将一个字符串拆分为一个字符串向量:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | /** * \brief Split a string in substrings * \param sep Symbol separating the parts * \param str String to be splitted * eturn Vector containing the splitted parts * \pre The separator can not be 0 * \details Example : * \code * std::string str ="abc.def.ghi..jkl."; * std::vector<std::string> split_str = split('.', str); // the vector is ["abc","def","ghi","","jkl",""] * \endcode */ std::vector<std::string> split(char sep, const std::string& str); std::vector<std::string> split(char sep, const std::string& str) { assert(sep != 0 &&"PRE: the separator is null"); std::vector<std::string> s; unsigned long int i = 0; for(unsigned long int j = 0; j < str.length(); ++j) { if(str[j] == sep) { s.push_back(str.substr(i, j - i)); i = j + 1; } } s.push_back(str.substr(i, str.size() - i)); return s; } |
然后,期望你有一个类矩阵,你可以做如下的事情:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | std::string matrices_str; std::ifstream matrix_file(matrix_file_name.c_str()); matrix_file >> matrices_str; const std::vector<std::string> matrices = split('|', matrices_str); std::vector<Matrix<double> > M(matrices.size()); for(unsigned long int i = 0; i < matrices.size(); ++i) { const std::string& matrix = matrices[i]; const std::vector<std::string> rows = split(';', matrix); for(unsigned long int j = 0; j < rows.size(); ++j) { const std::string& row = matrix[i]; const std::vector<std::string> elements = split(',', row); for(unsigned long int k = 0; k < elements.size(); ++k) { const std::string& element = elements[k]; if(j == 0 && k == 0) M[i].resize(rows.size(), elements.size()); std::istringstream iss(element); iss >> M[i](j,k); } } } |
或者,压缩代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | std::string matrices_str; std::ifstream matrix_file(matrix_file_name.c_str()); matrix_file >> matrices_str; const std::vector<std::string> matrices = split('|', matrices_str); std::vector<Matrix<double> > M(matrices.size()); for(unsigned long int i = 0; i < matrices.size(); ++i) { const std::vector<std::string> rows = split(';', matrices[i]); for(unsigned long int j = 0; j < rows.size(); ++j) { const std::vector<std::string> elements = split(',', matrix[i]); for(unsigned long int k = 0; k < elements.size(); ++k) { if(j == 0 && k == 0) M[i].resize(rows.size(), elements[k].size()); std::istringstream iss(elements[k]); iss >> M[i](j,k); } } } |
您所拥有的示例实际上映射到一个非常简单的字节机。
从一个零矩阵开始,并跟踪你写的矩阵的位置。一次读一个字符。如果字符是数字,则将矩阵中的当前数字乘以10,然后将数字相加;如果字符是逗号,则前进到行中的下一个数字;如果字符是分号,则转到下一行;如果字符是管道,则启动新矩阵。
如果数字是浮点数,您可能不想这样做。我将它们保存在一个缓冲区中,并使用一种标准的方法来解析浮点数。但除此之外,您实际上不需要保持非常复杂的状态或构建大型的解析器。您可能希望在以后的阶段添加错误处理,但即使在那里,错误处理也非常简单,并且只取决于您正在扫描的当前字符。
您可以使用
以下是你如何做到这一点的概念。欲了解更多信息,请访问互联网。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 | enum State { DECIMAL_NUMBER, COMMA_D, SEMICOLON_D, PIPE_D, ERROR_STATE, }; char GetChar() { // implement proper reading from file static char* input ="1,2;3,4|0,1;1,0|5,3;3,1|"; static int index = 0; return input[index++]; } State GetState(char c) { if ( isdigit(c) ) { return DECIMAL_NUMBER; } else if ( c == ',' ) { return COMMA_D; } else if ( c == ';' ) { return SEMICOLON_D; } else if ( c == '|' ) { return PIPE_D; } return ERROR_STATE; } int main(char* argv[], int argc) { char c; while ( c = GetChar() ) { State s = GetState(c); switch ( c ) { case DECIMAL_NUMBER: // read numbers break; case COMMA_D: // append into row break; case SEMICOLON_D: // next row break; case PIPE_D: // finish one matrix break; case ERROR_STATE: // syntax error break; default: break; } } return 0; } |