我是CPLEX用户,我需要将CSV文件中的数组数据转换为c++ 2D Map作为输入到我的优化问题。数据以列的形式呈现。也就是说,如果我们考虑3行(AA1, AA2, AA3)和3列(BB1, BB2, BB3)及其各自的值,它们在CSV文件中具有以下格式:
ROW, COL, VALUE
AA1, BB1, 0.3
AA2, BB1, 0.5
AA1, BB2, 0.6
AA1, BB3, 0.7
AA2, BB2, 0.9
AA3, BB2, 0.5
AA3, BB1, 0.6
AA2, BB3, 0.4
AA3, BB3, 0.6
可以看到,数据既没有按行排序,也没有按列排序。我希望将数据读取为格式为" Map <字符串,map><string,>>"使得结果映射是有序的:
ROW, COL, VALUE
AA1, BB1, 0.3
AA1, BB2, 0.6
AA1, BB3, 0.7
AA2, BB1, 0.5
AA2, BB2, 0.9
AA2, BB3, 0.4
AA3, BB1, 0.6
AA3, BB2, 0.5
AA3, BB3, 0.6
任何帮助将非常感激!谢谢你!
[EDIT]行和列的数量是预先知道的-不需要计数。我对c++比较陌生(从OPL优化语言迁移过来),对文件操作也不是很熟悉。
由于您正在使用空白作为分隔字符,因此您应该能够使用标准<ifstream>
实现相当快地实现这一点:
#include <ifstream>
#include <string>
#include <map>
#include <iostream>
int main() {
// Open file:
std::ifstream fin("filename.csv"); // Open in text-mode.
// Opening may fail, always check.
if (!fin) {
std::cout << "Error, could not open file." << std::endl;
return -1;
}
// Construct your map.
std::map< std::string, std::map<std::sting, float> > valMap;
// Read the file and load the data:
std::string row, column;
float value;
while ( fin >> row >> column >> value ) { // Reads three values from file.
valMap[row][col] = value; // Adding the values to the map, if the cell is
// a duplicate: It will be overwritten.
}
// Close the file:
fin.close();
// Printing out the data like you described:
for ( auto & columnMap : valMap ) {
for ( auto cell : columnMap.second ) {
std::cout << columnMap->first /*First label*/ << " "
<< cell->first /*Second label*/ << " "
<< cell->second /* Value */ << std::endl;
}
}
return 0;
}
好的,我将在第二个答案中添加这个,因为它是解决相同问题的完全不同的方法。
如果可以使用任意数量的分隔符,那么strtok是一个很好的选择。它最初是C语言的,所以你需要花点功夫,但这是值得的。
char * strtok ( char * str, const char * delimiters );
接受两个参数,第一个是我们要分析的字符串,第二个是包含我们想要用作分隔符的所有不同字符的字符串。
对于您的特殊用例,我建议如下:
#include <cstring>
#include <cstdlib>
#include <string>
#include <fstream>
#include <iostream>
const char * DELIMS = "t ,"; // Tab, space or comma.
const int MAX_LINE_LENGTH = 1024; // Choose this large enough for your need.
// Or use a dynamic buffer together with
// std::string and getline(istream, string&).
int main() {
std::fstream fin("filename.csv");
// Test for errors
// Prepare a C-string buffer to be used when reading lines.
char buffer[MAX_LINE_LENGTH] = {};
// Prepare map.
std::map< std::string, std::map< std::string, float>> valMap;
// Read one line at a time.
while ( fin.getline(buffer, MAX_LINE_LENGTH) ) {
// Extract the three tokens:
const char * row = strtok( buffer, DELIMS );
const char * col = strtok( NULL, DELIMS );
const char * val = strtok( NULL, DELIMS );
// You could do additional errorchecking here,
// as for instance checking that there are no more valid tokens,
// and that all row, col and val are non-NULL.
// Insert elements.
valMap[std::string(row)][std::string(col)] = std::atof(val);
}
// Cleanup
fin.close();
}