Reputation: 25048
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
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
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:
This start is clearly wrong. After this rowNum
becomes 1:
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