C++ Read matrices from file with multiple delimiters

This question already has an answer here:

  • Parse (split) a string in C++ using string delimiter (standard C++) [duplicate] 11 answers
  • The most elegant way to iterate the words of a string [closed] 74 answers

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

    使用上面的代码,你可以建立逻辑来存储个人element只要你喜欢。


    I use this own function to split a string to a vector of strings :

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

    Then, expecting you have a class Matrix, you can do something like :

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

    Or, compressed code :

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

    You can use finite state machine concept. You need define states for each step. Read one char and then decide what it is (number or delimiter).

    Here is concept how you could do it. For more reading check this on internet. text parsing , finite state machine , lexical analyzer , formal grammar

    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;
    }
    
    链接地址: http://www.djcxy.com/p/19582.html

    上一篇: c ++:按分隔符分割字符串

    下一篇: C ++从具有多个分隔符的文件中读取矩阵