我想添加两个String类型的矩阵。用户将不会输入行数或列数。用户将仅输入数组

时间:2019-05-08 19:12:53

标签: c++

如何添加两个String类型的矩阵?用户将不会输入行数或列数。用户将仅输入阵列。例如,对于输入[5 4-1; 2 1 4] + [3 -5 2.5; 1 2 3],输出应为[8 -1 1.5; 3 3 7] 什么是stof函数和添加错误? 这是我的代码:

//define a stm fucntion to convert string to matrix
vector <vector <float> > stm(string mat1)
{
    //now let us build the matrix1 by iterating over the string mat1
    //we will break the string over the point where we ";"
    vector <vector <float> > matrix1;
    int index1 = 0;
    for (float i = 0; i < mat1.length(); i++)
    {
        string temp = " ";
        while (mat1[i] != ';')
        {
            temp += mat1[i];
            //now the temp string contains the elements of first row
            //now we will break this at point where we get " " (spaces)
            for (float j = 0; j < temp.length(); j++)
            {
                string num1;
                int index2 = 0;
                while (temp[j] != ' ')
                {
                    num1 += temp[j];
                    //ntf is number to be filled at that position
                    j++;
                }
                float ntf = stof(num1);
                matrix1[index1][index2] = ntf;
                index2++;
            }
            i++;
        }
        index1++;
    }
    return matrix1;
}

int main()
{
    string mat1; cin >> mat1;
    string mat2; cin >> mat2;
    vector <vector <float> > matrix1, matrix2;
    matrix1 = stm(mat1);
    matrix2 = stm(mat2);
    //now let us write a code to add the two matrices;
    vector <float> add;
    for (float i = 0; i < matrix1.size(); i++)
    {
        for (float j = 0; j < matrix1[0].size(); j++)
        {
            add[i][j] = matrix1[i][j] + matrix2[i][j];
        }
    }
    for (float i = 0; i < add.size(); i++)
    {
        for (float j = 0; j < add[0].size(); j++)
        {
            cout << add[i][j] << " ";
        }
        cout << endl;
    }
    return 0;

这是一个例子 输入

 [5 4 -1;3 2 1]+[1 2 3;5 4 8]

输出

[6 6 2;8 6 9]

1 个答案:

答案 0 :(得分:1)

我将提出一种可能的解决方案(在4,200万个选项中:-)

想法是使用面向对象的方法。因此,具有数据和方法的类。

数据是float矢量的必需矢量。并且方法是提取和添加。出于调试目的,还会覆盖插入操作符。

请注意:棘手的部分是解析输入字符串。特别是在可能无处不在的空白处。为了易于使用,我为浮点值定义了一个正则表达式。 regex_token_iterator将提取子匹配项并将其复制到列中。直到下一个“;”。看起来很复杂,但最终还是很容易理解。

我在代码中添加了很多注释,这使它有些冗长。无论如何,这将有助于更好地理解。

然后,main函数看起来非常简单。 。

编辑:

基于David C. Rankin的推荐,我更新了源代码:

  • 修改变量名以使其更具可读性
  • 将基本数据类型从float更改为double
  • 添加更多的空格和换行符以改善文本结构
  • 添加更多评论
  • 用于加法运算符的新大小检查
#include <iostream>
#include <sstream>
#include <string>
#include <algorithm>
#include <regex>

// Our test data (raw string) . We could of course also read from a file or from std::cin or any istream
std::istringstream testData(
R"#(   [   1 2    3 ; 4 5 6 7  ]
[   7  8   9;    10  11 12]
)#");


struct Matrix
{
    // The data of our matrix
    std::vector<std::vector<double>> data{};

    // Overloading the extractor operator >> for our Matrix class
    friend std::istream& operator >> (std::istream& is, Matrix& m) {
        // Read a complete line
        std::string line; 
        getline(is, line);

        // Define a regex that matches any double number
        std::regex re("([-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?)");

        // Set iterators. 
        // "Start" will be set to begin() or one past the end of the next semicolon 
        std::string::iterator start = line.begin(); 
        // Position of semincolon or end()
        std::string::iterator posSemicolon{};

        // Read all rows and columns
        do {
            // Set the end iterator for this loop run to the position of the semicolon (or end() )
            posSemicolon = std::find(start, line.end(), ';');

            // Add a new row
            m.data.emplace_back(std::vector<double>());

            // Read a complete line with doubles and put that as column values in the current row
            std::transform(
                std::sregex_token_iterator(start, posSemicolon, re, 1), // Search for text that matches the regex
                std::sregex_token_iterator(),                           // Search until the end (posSemicolon)
                std::back_inserter(*(std::prev(m.data.end()))),         // Put this data into the columns of the current row 
                // Convert the string matched by the regex, into a double
                [](const std::string& stringAsDouble) -> double { return stod(stringAsDouble); }
            );   

            // In case there is more input, 
            if (posSemicolon != line.end()) {
                // then continue tokenizing in the next loop run past the semicolon 
                start = posSemicolon + 1;
            }
        } while (posSemicolon != line.end());
        return is;
    }

    // For debug output purposes. Copy the data of the matrix to std::cout
    friend std::ostream& operator << (std::ostream & os, const Matrix & m) {
        std::for_each(
            m.data.begin(),                           // Iterate over all rows
            m.data.end(), 
            [&os](const std::vector<double> & row) {  // Do for all rows 
                std::copy(                            // Copy data to ostream (print)
                    row.begin(),                      // Iterate ove all columns for this row  
                    row.end(), 
                    std::ostream_iterator<double>(os, " ")); // Print
                std::cout << '\n';                    // Line break after printing a row
            }  
        );
        return os;
    }

    // Overload of the addition operator
    friend Matrix operator +(Matrix & m1, Matrix & m2) {
        // Define an empty matrix
        Matrix result{};

        // To be on the safe side, we will resize the destination matrix size 
        // to maximum values of both matrices
        // Get the max number of rows ofrom both m1 and m2
        const size_t maxRowSize = std::max(m1.data.size(), m2.data.size());

        // Set number of rows in resulting Matrix
        result.data.resize(maxRowSize);

        // Get the maximum number of columns in any of the 2 metrices m1 or m2
        const size_t maxColumnSize = std::max(
            std::max_element(
                m1.data.begin(),    // Iterate over all rows of Matrix m1
                m1.data.end(), 
                [](const std::vector<double> & dv1_1, const std::vector<double> & dv1_2) {
                    return dv1_1.size() < dv1_2.size(); 
                }
            )->size(),
            std::max_element(
                m2.data.begin(),   // Iterate over all rows of Matrix m1
                m2.data.end(), 
                [](const std::vector<double> & dv2_1, const std::vector<double> & dv2_2) {
                    return dv2_1.size() < dv2_2.size(); 
                }
            )->size()
        );

        // Iterate over all matrix elements
        // For all rows 
        for (size_t row = 0; row < maxRowSize; ++row) {

            // Resize the the number of columns in the target matrix
            result.data[row].resize(maxColumnSize);

            // Now iterate over all columns in that row
            for (size_t col = 0; col < maxColumnSize; ++col) {

                // And add the values. First check for valid row and column indices
                double m1Value = ((row < m1.data.size()) && (col < m1.data[row].size())) ? m1.data[row][col] : 0.0;
                double m2Value = ((row < m2.data.size()) && (col < m2.data[row].size())) ? m2.data[row][col] : 0.0;
                result.data[row][col] = m1Value + m2Value;
            }
        }
        return result;
    }
};

int main()
{
    // Define some matrices
    Matrix m1, m2, m3;

    // Read the test data. You can also read from std::cin or from a file
    testData >> m1 >> m2;

    // Add the Matrices
    m3 = m1 + m2;

    // Show result
    std::cout << "Matrix 1:\n" << m1 << "\nMatrix 2:\n" << m2 << "\nMatrix3 = Matrix1 + Matrix2:\n" << m3;

    return 0;
}