提问者:小点点

C从具有多个分隔符的文件中读取矩阵[重复]


所以我得到了一个包含十个矩阵的文件,我想从文件中读取这些矩阵并将它们保存到向量/数组中,其中每个矩阵都存储在向量或数组中。然而,这些矩阵的格式使我很难读取数据(我不擅长从输入文件中读取)。

该文件具有以下格式。每个矩阵的元素用 "," . 每行用“;”分隔,每个矩阵用“|”分隔。例如三个2 x 2矩阵如下。

1,2;3,4|0,1;1,0|5,3;3,1|

我只想将矩阵保存到三个不同的向量中,但我不确定如何做到这一点。

我试过了

    while(getline(inFile,line)){
        stringstream linestream(line);
        string value;
        while(getline(linestream, value, ','){
               //save into vector
        }
    }

但这显然是非常粗糙的,并且只通过逗号来分隔数据。有没有办法用多个分隔符来分隔数据?

谢谢你!


共3个答案

匿名用户

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;                    
            }
    }
}

使用上面的代码,您可以构建存储单个元素的逻辑。

匿名用户

我使用这个自己的函数将字符串拆分为字符串向量:

/**
 * \brief   Split a string in substrings
 * \param   sep  Symbol separating the parts
 * \param   str  String to be splitted
 * \return  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;
}

然后,假设你有一个类矩阵,你可以做这样的事情:

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);
    }
  }
}

或者,压缩代码:

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);
    }
  }
}

匿名用户

您可以使用有限状态机概念。您需要为每个步骤定义状态。读取一个字符,然后决定它是什么(数字或分隔符)。

这是你可以做到的概念。如需更多阅读,请在Internet上查看此内容。文本解析有限状态机词法分析器形式语法

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;
}