将CSV格式的二维数组读入地图c++; 我是CPLEX用户,我需要把CSV文件中的数组数据转换成C++ 2D地图作为输入优化问题。数据以列的形式显示。也就是说,如果我们考虑3行(AA1、AA2、AA3)和3列(BB1、BB2、BB3)及其各自的值,则它们在CSV文件中具有以下格式:

将CSV格式的二维数组读入地图c++; 我是CPLEX用户,我需要把CSV文件中的数组数据转换成C++ 2D地图作为输入优化问题。数据以列的形式显示。也就是说,如果我们考虑3行(AA1、AA2、AA3)和3列(BB1、BB2、BB3)及其各自的值,则它们在CSV文件中具有以下格式:,c++,arrays,csv,cplex,C++,Arrays,Csv,Cplex,行、列、值 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行>>列>>值){//从文件中读取三个值。 valMap[row][col]=value;//如果单元格为 //副本:它将被覆盖。 } //关闭文件: fin.close(); //按照您描述的方式打印数据

行、列、值
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”的2D地图中,以便生成的地图按顺序排列:

行、列、值
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优化语言迁移)我比较新,而且我对文件操作不太熟悉。任何示例代码都将非常有助于我理解该过程。

由于您使用空格作为分隔符,因此您应该能够使用标准的
实现快速实现这一点:

#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;
}
#包括
#包括
#包括
#包括
int main(){
//打开文件:
std::ifstream fin(“filename.csv”);//以文本模式打开。
//打开可能会失败,请务必检查。
如果(!fin){
std::cout>行>>列>>值){//从文件中读取三个值。
valMap[row][col]=value;//如果单元格为
//副本:它将被覆盖。
}
//关闭文件:
fin.close();
//按照您描述的方式打印数据:
用于(自动和列映射:valMap){
用于(自动单元格:columnMap.second){

std::cout first/*first label*/好的,我将在第二个答案中添加这一点,因为这是解决同一问题的完全不同的方法

如果您可以有任意数量的不同分隔符,这是一个很好的选择。它最初是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();
}  
#包括
#包括
#包括
#包括
#包括
const char*DELIMS=“\t,”;//制表符、空格或逗号。
const int MAX_LINE_LENGTH=1024;//根据需要选择足够大的尺寸。
//或者将动态缓冲区与
//string和getline(istream,string&)。
int main(){
std::fstream fin(“filename.csv”);
//测试错误
//准备读取行时使用的C字符串缓冲区。
字符缓冲区[最大行长度]={};
//准备地图。
std::map>valMap;
//一次读一行。
while(fin.getline(缓冲区,最大行长度)){
//提取三个令牌:
const char*row=strtok(缓冲区,DELIMS);
const char*col=strtok(NULL,DELIMS);
const char*val=strtok(NULL,DELIMS);
//你可以在这里做额外的错误检查,
//例如,检查是否没有更多的有效令牌,
//并且所有行、列和值都不为空。
//插入元素。
valMap[std::string(row)][std::string(col)]=std::atof(val);
}      
//清理
fin.close();
}  

可以做一个<代码> STD::MAP<代码> >还是“代码> STD::配对< /代码>,谢谢……的建议。我对C++是比较新的(从OPL优化语言迁移)我对文件操作的理解非常有限。你有任何示例代码吗?谢谢。谢谢你的代码-分隔符可以是制表符或逗号。它不是空白。很抱歉,我已经编辑了它。有没有关于忽略空白字符的建议?因为初始键可能有重复项(基于给出的示例)类型为
std::multimap
valMap
会更好。如果辅助键可以是重复的,则内部
std::multimap
也会更好。@Casey如果使用内部映射,则无需使用multimap,因为每行值只需存储一次,无论i有多少列和值t(它们都在内部映射中)。谢谢大家的建议。@Stian我能够用空格分隔符实现您的代码。谢谢!但是,我的分隔符将是逗号-有没有关于如何忽略它们的建议?谢谢。@radneo在这种情况下,您要找的可能是