edgarmtze
edgarmtze

Reputation: 25048

How to make a complete matrix with 2 loops in c++

I have a string in c++ and it represents an upper triangular matrix, What I want to do is meake a complete matrix from this string

    std::string input = "1,2,1,3,6,1,4,7,9,1";
    //this represents


 //1  2  3 4
 //2  1  6 7
 //3  6  1 9
 //4  7  9 1

std::replace(input.begin(), input.end(), ',', ' ');
std::vector<double> Matrix;
std::istringstream inputStream(input);
double value;
int rowNum = 0;
int colNum = 0; 

while (inputStream >> value){
    for (colNum = 0; colNum < 2; colNum++){
        if (colNum >= rowNum){
            Matrix.push_back( value ); 
        }
        else{
            Matrix.push_back( Matrix[colNum * 2 + rowNum]); 
        }
    }

    rowNum++;
}
inputStream >> std::ws;

Instead of getting

 1  2  3 4
 2  1  6 7
 3  6  1 9
 4  7  9 1

But I am getting

   1.0000   1.0000   1.0000   2.0000
   1.0000   1.0000   2.0000   1.0000
   1.0000   2.0000   1.0000   1.0000
   2.0000   1.0000   1.0000   2.0000

What is it my error? I can not see it...

Upvotes: 1

Views: 315

Answers (2)

CapelliC
CapelliC

Reputation: 60024

You should show the indexing scheme used for printing the output (i.e. how do you expect the indexes works): your choice of using a vector instead of a matrix make hard to correct the code. For sure, I see the following points that have no clear connection with the input pattern:

1) each number you read you increment the rowNum index. The row should be incremented instead at 'steps' 1, 1+2, 1+2+3,...

2) colNum should range from 0 to current rowNum, instead assumes just 0,1

3) there is no chance to fill a row (say the first) before you read (say the last). You could do if the input would be 1 2 3 4 1 6 7 1 9 1

all these points are related, and origin from the wrong data representation, that make difficult a trivial task.

In C++, a very effective way to tackle these problems is data hiding: consider how easily we can write a class that gives the correct logical representation and doesn't waste space:

#include <iostream>
#include <sstream>
#include <string>
#include <vector>
#include <algorithm>

template <class T = double>
class upper_triangular_matrix
{
    std::vector<T> Matrix;

public:

    upper_triangular_matrix(std::string input)
    {
        // trade time for space: store the values, compute indexing
        std::replace(input.begin(), input.end(), ',', ' ');
        std::istringstream inputStream(input);
        T value;
        while (inputStream >> value)
            Matrix.push_back(value);

        // validate size: ok 1,1+2,1+2+3 etc
    }

    T operator()(int r, int c) const
    {
        // compute indexing accounting for miss duplicated
        if (c > r)
            std::swap(c, r);
        int p = 0, n = 1;
        while (r > 0)
        {
            p += n++;
            r--;
        }
        return Matrix[p + c];
    }
};

int main()
{
    upper_triangular_matrix<> m("1,2,1,3,6,1,4,7,9,1");
    for (int r = 0; r < 4; ++r)
    {
        for (int c = 0; c < 4; ++c)
            std::cout << m(r, c) << ' ';
        std::cout << std::endl;
    }
}

when run, this prints

1 2 3 4 
2 1 6 7 
3 6 1 9 
4 7 9 1 

Upvotes: 1

Dietmar K&#252;hl
Dietmar K&#252;hl

Reputation: 153840

It is hard to tell exactly where the error is but here is where it starts:

std::vector<double> Matrix;

Yes, a non-empty std::vector<double> with n elements is a matrix: either a 1xn or a nx1 matrix (or both). In your context this view is, however, utterly unhelpful.

Let's look at the for-loop when you read the first element:

  1. colNum == 0, rowNum == 0 => (1, 1) = Matrix[0] = 1
  2. colNum == 1, rowNum == 0 => (2, 1) = Matrix[1] = 1

This start is clearly wrong. After this rowNum becomes 1:

  1. colNum == 0, rowNum == 1 => (3, 1) = Matrix[2] = Matrix[colNum * 2 + rowNum] = Matrix[1] = 1
  2. colNum == 1, rowNum == 1 => (4, 1) = Matrix[3] = 2

Well, I guess you can write the remainder up yourself. Of course, I could quickly write the code to solve your problem but I think this little exercise is for you. The way to do it is to fill the first row columns (where row is the current row being processed, using conventional index starting with 0) with the values from the transposed matrix and then read the remaining n - row columns (where n is the size of the matrix) from the file.

Upvotes: 0

Related Questions