我是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<字符串,地图< string,float>> "这样就得到了生成的地图:
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
任何帮助将不胜感激!谢谢。
[编辑] 行数和列数事先知道 - 无需计算。我对C ++相对较新(从OPL优化语言迁移),我对文件操作不是很熟悉。任何示例代码对我理解程序都非常有帮助。
答案 0 :(得分:1)
由于您使用空格作为分隔符,因此您应该能够使用标准<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;
}
答案 1 :(得分: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();
}