Reading a matrix created using an operator - c++

Hello stackoverflow community. I need some help with a bit of code (I am a new to C++ so be gentle). I am trying to use operator() to create a matrix, store data from an input file, then write to an output file. The below code has been simplified a bit. The header file is as follows:
//Data Header File
#ifndef Data_h
#define Data_h
#include <iostream>
using namespace std;
class Data
{
private:
int d_elems;
int rows_, cols_;
int dataRows;
int *p;
public:
//Constructor
femData();
femData(int Row, int Col);
//Copy Constructor
//femData(const int d_elems);
//Destructor
virtual ~femData();
//Operator
int& operator() (int Rows, int Cols);
//Functions
void readData(istream &inp); //Read Data from Input File
void writeData(ostream &out); //Write Data from Output File
};
#endif
Any my .cpp file:
//.cpp file
#include "stdafx.h"
#include "Data.h"
#include <fstream>
#include <string>
#include <iostream>
#include <iomanip>
using namespace std;
Data::Data() {} //Blanket Constructor
Data::Data(int Row, int Col) //Matrix Constructor
: rows_ (Row), cols_ (Col)
{
if (Row == 0 || Col == 0)
{
cout << "\nMatrix is Zero..." << endl;
system("pause");
exit(0);
}
p = new int[Row * Col];
}
int& Data::operator()(int Rows, int Cols) //Operator for Matrix
{
if (Rows >= rows_ || Cols >= cols_)
{
cout << "\nMatrix subscript out of bounds\n";
system("pause");
exit(0);
}
return p[cols_ * Rows + Cols];
}
Data::~Data() { /*delete[] p;*/} //Destructor
void Data::readData(istream &inp)
{
inp >> dataRows;
int e_id;
//Data (dataRows, 10); //How would I call this constructor?
rows_ = dataRows;
cols_ = 10;
for (int i = 0; i < dataRows; i++)
{
inp >> e_id;
if ((e_id - 1) != i)
{
cout << "\nError Reading Data..." << endl;
cout << "Program Will End\n!" << endl;
system("pause");
exit(0);
}
(*this)(i, 0) = d_eid;
for (int j = 1; j < 10; j++)
{
inp >> (*this)(i, j);
}
}
void femData::writeData(ostream & out)
{
//Output Info
out << setfill('-') << setw(90) << "-" << endl;
out << setfill(' ') << setw(34) << " Matrix Information " << endl;
out << setfill('-') << setw(90) << "-" << "\n\n" << endl;
out << setfill(' ');
out << setw(10) << "ID";
out << setw(10) << "Data 1";
out << setw(10) << "Data 2";
out << setw(10) << "Data 3";
out << setw(10) << "Data 4";
out << setw(10) << "Data 5";
out << setw(10) << "Data 6";
out << setw(10) << "Data 7";
out << setw(10) << "Data 8" << endl;
for (int i = 0; i < dataRows; i++)
{
out << setw(7) << ((p + i) + 0);
out << setw(10) << ((p + i) + 1);
out << setw(10) << ((p + i) + 2);
out << setw(10) << ((p + i) + 3);
out << setw(10) << ((p + i) + 4);
out << setw(10) << ((p + i) + 5);
out << setw(10) << ((p + i) + 6);
out << setw(10) << ((p + i) + 7);
out << setw(10) << ((p + i) + 8) << endl;
//Note ((p + i) + 8) is omitted
}
}
The issue I am having is with the output. When the WriteData function is called, it writes to an output file, but does not write the data it read. Instead all that is written is {0 1 2 3 4 5 6 7 8} {1 2 3 4 5 6 7 8 9} {etc.} where {is used here to denote different rows}
Additionally, if I try to output d_elems(i,0) instead of ((d_elems + i) + 0) the compiler tells me I need a pointer to function type.
Any help would be much appreciated, thanks.

Your readData is wrong. You read data in a local object, Data d_data(dataRows,10); which is then destroyed at the end of the function. You are not filling in the data on your current instance. You need to read directly into `p'
inp >> p[i * rows_ + j];
or use the operator() you defined on the current instance, like
inp >> (*this)(i,j); // this is preferable
Side issue: you are missing the declaration of p in the class header file, int *p;.
Side issue 2: Your int& Data::operator()(int Rows, int Cols) is confusing, try using int& Data::operator()(int i, int j), and return p[i * _cols + j]; as it makes it much easier to read.

Related

Quicksort not sorting one element in the list of strings

Could anyone tell me what is wrong with my code:
int Partition(vector<string>& userIDs, int i, int k) {
int pivot = (i + (k - i) / 2);
string temp;
while(i<k) {
cout << "pivot:" << pivot << endl;
while (userIDs.at(i).compare(userIDs.at(pivot))<0) {
cout << "1. i:"<<i<<" UserIDs.at(i):" << userIDs.at(i) << " UserID.at(pivot): " << userIDs.at(pivot) << endl;
i += 1;
}
while (userIDs.at(pivot).compare(userIDs.at(k))<0) {
cout << "2. k:" << k << " UserIDs.at(k):" << userIDs.at(k) << " UserID.at(pivot): " << userIDs.at(pivot) << endl;
k -= 1;
}
if(i<k){
cout << "3. i:" << i << " k:"<<k<<" UserIDs.at(i):" << userIDs.at(i) << " UserID.at(k) : " << userIDs.at(k) << endl;
temp = userIDs.at(i);
userIDs.at(i) = userIDs.at(k);
userIDs.at(k) = temp;
i++;
k--;
}
cout << "4. i:" << i << " k:" << k << endl;
}
cout << " 5. k:" << k << endl;
return k;
}
void Quicksort(vector<string>& userIDs, int i, int k) {
cout << "Quicksort i:" << i << " k:" << k << endl;
if (i >= k) {
return;
}
int lowEndIndex = Partition(userIDs, i, k);
cout << "Quicksort lowEndIndex:" << lowEndIndex << endl;
Quicksort(userIDs, i, lowEndIndex);
Quicksort(userIDs, lowEndIndex+1, k);
}
When I input this list:
BigBen
GardenHeart
GreyMare
TeenPunch
WhiteSand
LifeRacer
Doom
AlienBrain
I get:
AlienBrain
BigBen
GreyMare
GardenHeart
Doom
LifeRacer
TeenPunch
WhiteSand
Why is Doom not in the correct place?
#include <bits/stdc++.h>
using namespace std;
int Partition(vector<string>& userIDs, int i, int k) {
int pivot = i;
string pivotValue = userIDs[pivot];
string temp;
int leftIndex = i;
int rightIndex = k;
while(i<k) {
while (userIDs[i].compare(pivotValue)<=0) {
i++;
if(i >= rightIndex) break;
}
while (pivotValue.compare(userIDs[k])<=0) {;
k--;
if(k <= leftIndex) break;
}
if(i<k){
temp = userIDs[i];
userIDs[i] = userIDs[k];
userIDs[k] = temp;
}
}
// swap
userIDs[pivot] = userIDs[k];
userIDs[k] = pivotValue;
return k;
}
void Quicksort(vector<string>& userIDs, int i, int k) {
if (i >= k) {
return;
}
int lowEndIndex = Partition(userIDs, i, k);
Quicksort(userIDs, i, lowEndIndex - 1);
Quicksort(userIDs, lowEndIndex + 1, k);
}
int main() {
vector<string> userIDs = {"BigBen", "GardenHeart", "GreyMare", "TeenPunch",
"WhiteSand", "LifeRacer", "Doom", "AlienBrain" };
Quicksort(userIDs, 0, userIDs.size() - 1);
for(auto& c: userIDs) cout << c << " ";
cout << endl;
return 0;
}
Fixed the code and tested. Now it works. What were the problems?
As far as I noticed, firstly you didn't put break() statements within the while loops in case i or k exceeds the boundaries of the vector. I've changed the pivot from middle element to first element, but it's just my preference, you can implement the quicksort algorithm with your pivot in the middle, not a big deal. I've called first Quicksort() with lowEndIndex - 1 rather than lowEndIndex. I've used [] operator rather than at(), but again it's my preference. I guess the main problems were that break stuff and calling the quicksort method with lowEndIndex rather than lowEndIndex - 1.
Output:
AlienBrain BigBen Doom GardenHeart GreyMare LifeRacer TeenPunch WhiteSand

How to format output like this

My code is like this so far :
void matrix::print(int colWidth) const
{
cout << getRows() << " x " << getCols() << endl;
cout << "-";
for (unsigned int d = 0; d < getCols(); d++) {
cout << "--------";
}
cout << endl;
for (unsigned x = 0; x < getRows(); x++) {
cout << "|";
for (unsigned y = 0; y < getCols(); y++) {
cout << setw(colWidth) << at(x, y) << " |";
}
cout << endl;
}
cout << "-";
for (unsigned int d = 0; d < getCols(); d++) {
cout << "--------";
}
cout << endl;
}
But the output depends on the colWidth which will be the space between each number printed. So how can I adjust my dashes to be printed like the following no matter the colWidth it should align.
One output should look like this:
Second output is like this:
If the column width is a parameter, you're almost done with your code. Just turn the cout<<"--------" into:
std::cout << std::string(getCols()*(colWidth + 2) + 1, '-');
That code prints a string of dashes, which width is: number of matrix columns, times column width plus 2, plus 1:
Plus 2 because you are appending a " |" to each column.
Plus 1 because you are adding a '|' at the beginning of each row.
You may want to check for empty matrices at the beginning of your print method.
[Demo]
#include <initializer_list>
#include <iomanip> // setw
#include <iostream> // cout
#include <vector>
class matrix
{
public:
matrix(std::initializer_list<std::vector<int>> l) : v{l} {}
size_t getRows() const { return v.size(); }
size_t getCols() const { if (v.size()) { return v[0].size(); } return 0; }
int at(size_t x, size_t y) const { return v.at(x).at(y); }
void print(int colWidth) const
{
std::cout << "Matrix: " << getRows() << " x " << getCols() << "\n";
// +2 due to " |", +1 due to initial '|'
std::cout << std::string(getCols()*(colWidth + 2) + 1, '-') << "\n";
for (unsigned x = 0; x < getRows(); x++) {
std::cout << "|";
for (unsigned y = 0; y < getCols(); y++) {
std::cout << std::setw(colWidth) << at(x, y) << " |";
}
std::cout << "\n";
}
std::cout << std::string(getCols()*(colWidth + 2) + 1, '-') << "\n";
}
private:
std::vector<std::vector<int>> v{};
};
int main()
{
matrix m{{1, 2}, {-8'000, 100'000}, {400, 500}};
m.print(10);
}
// Outputs
//
// Matrix: 3 x 2
// -------------------------
// | 1 | 2 |
// | -8000 | 100000 |
// | 400 | 500 |
// -------------------------

error: overloaded function with no contextual type information usinf LEMON-graph-library

So I am implementing a Benders procedure using lazy constraints from GUROBI. As part of the subproblem procedure I need to process a graph using Breadth First Search, for which I am using LEMON. I am trying to implement use a visitor for the BFS search. However when I try to access the map of reached nodes using bfs.reached() I get a compiler (I suppose) error.
Here is the callback class implementation so far:
typedef ListDigraph::Node Node;
typedef ListDigraph::Arc Arc;
typedef ListDigraph::ArcMap<double> ArcDou;
typedef ListDigraph::NodeMap<double> NodeDou;
typedef ListDigraph::ArcMap<int> ArcInt;
typedef ListDigraph::ArcMap<bool> ArcBool;
typedef ListDigraph::NodeMap<int> NodeInt;
typedef ListDigraph::NodeIt NodeIt;
typedef ReverseDigraph<ListDigraph>::NodeIt NodeIt_rev;
typedef ListDigraph::ArcIt ArcIt;
class BendersSub: public GRBCallback
{
public:
const Instance_data &ins;
const vec4GRBVar &X;
const vec1GRBvar &u;
vec2GRBVar &p;
GRBModel &modelSubD;
BendersSub(const Instance_data &ins, const vec4GRBVar &X, const vec1GRBvar &u, vec2GRBVar &p, GRBModel &modelSubD)
:ins(ins), X(X), u(u), p(p),modelSubD(modelSubD){
//cout << "\n\tI:" << ins.I << " J:" << ins.J << " T:" << ins.T << " V:" << ins.V << flush;
}
protected:
void callback() {
try {
if (where == GRB_CB_MIPSOL) {
cout << "\n -- Entering Callback -- " << flush;
string var_name;
int I = ins.I , J = ins.I , T = ins.T , V = ins.V,i,j,k,t,v;
ListDigraph grafo;
Node x;
for( int t(0); t < ins.T+1; t++)
for ( int i(0); i < ins.I; i++)
x = grafo.addNode();
Arc arco;
int count( 0 );
for(t = 0; t < ins.T; ++t){
for(i = 0; i < ins.I; ++i){
for(j = 0; j < ins.J; ++j){
if ( i == j ){
arco = grafo.addArc(grafo.nodeFromId(i + ins.I * t),grafo.nodeFromId(j + (ins.I * (t+1))));
}else if ( (t + ins.tau.at(i).at(j)) <= ins.T-1 ){
arco = grafo.addArc(grafo.nodeFromId(i + ins.I * t),grafo.nodeFromId(j + ins.I * (t + ins.tau.at(i).at(j))));
}
else if ( (t + ins.tau.at(i).at(j)) > ins.T-1 ){
arco = grafo.addArc(grafo.nodeFromId(i + ins.I * t),grafo.nodeFromId(((ins.I*(ins.T+1)+1))-1-(ins.I)+j)) ;
}
}
}
}
NodeDou divergence (grafo);
ArcDou costo (grafo);
ArcBool filter (grafo, true);
NodeDou potential (grafo);
ReverseDigraph<ListDigraph> grafo_r(grafo);
using Visitor = Visitor_AcSup<NodeDou>;
for ( int v(0); v < V; v++){
double sum_sup(0.0);
Visitor visitor(grafo_r, divergence, sum_sup);
cout << "\nsum_sup: " << sum_sup << flush;
for (t = 0; t < T; t++){
for(i = 0; i < I ; i++){
if(divergence[grafo.nodeFromId(flat_ixt(ins,t,i))] < -EPS3){
BfsVisit<ReverseDigraph<ListDigraph>, Visitor> bfs(grafo_r,visitor);
bfs.run(grafo.nodeFromId(flat_ixt(ins,t,i)));
if( (sum_sup-fabs(divergence[grafo.nodeFromId(flat_ixt(ins,t,i))])) < -EPS4 ){
cout << "\nBuild Ray" << flush;
}
}
}
}
for (NodeIt_rev u(grafo_r); u != INVALID; ++u){
/*The error does not show when I comment this line.*/
cout << "\nId: " << grafo.id(u) << setw(10) << bfs.reached(u) << flush;
}
cout << "\nsum_sup: " << sum_sup << flush;
.
/* Remaining code */
.
.
}/*end_if v*/
//cout << "\n -- Exiting Callback -- " << flush;
}
}catch (GRBException e) {
cout << "Error number: " << e.getErrorCode() << endl;
cout << e.getMessage() << endl;
exit(EXIT_FAILURE);
}catch (const exception &exc){
cerr << "\nCallback - " << exc.what() << flush;
exit(EXIT_FAILURE);
}catch (...) {
cout << "Error during callback" << endl;
exit(EXIT_FAILURE);
}
}
};
Here is the (incomplete visitor) implementation.
template <typename DivMap >
class Visitor_AcSup : public BfsVisitor< const ReverseDigraph<ListDigraph> > {
public:
Visitor_AcSup(const ReverseDigraph<ListDigraph>& _graph, DivMap& _dirMap, double& _sum_sup)
: graph(_graph), dirMap(_dirMap), sum_sup(_sum_sup){
cout << "\n --Calling constructor of Visitor_AcSup -- " << endl;
sum_sup = 0.0;
}
void start (const Node &node){
//cout << "\nstart Node: " << graph.id(node) << flush;
sum_sup -= dirMap[node];
}
void reach (const Node &node){
//cout << "\nReach Node: " << graph.id(node) << flush;
}
void process (const Node &node){
//cout << "\nProcess Node: " << graph.id(node) << setw(5) << dirMap[node] << flush;
sum_sup += dirMap[node];
}
void discover(const Arc& arc) {
//cout << "\tDiscover Arc: " << graph.id(arc) << flush;
}
void examine(const Arc& arc) {
//cout << "\tExamine Arc: " << graph.id(arc) << flush;
}
private:
const ReverseDigraph<ListDigraph>& graph;
DivMap& dirMap;
double& sum_sup;
The error looks like this
functions.cpp:1845:59: error: overloaded function with no contextual type information
cout << "\nId: " << grafo.id(u) << setw(10) << bfs.reached(u) << flush;
^~~~~~~
Makefile:27: recipe for target 'VAP' failed
I am clueless about what is happening as the only error that comes up to my mind is conflict of keywords between namespaces
using namespace lemon;
using namespace lemon::concepts;
using namespace std;
but have found no resolution to this. I am a newbie in C++, so that I am asking you guys where this could possibly come from.

cargo transportation system we are not sure how to display the last part of our task

Here is our code for the task we are almost finishing just the last part we are stuck at
"Fastest: 3 trips (1 Van, 3 Mini-lorry, $645) "
we are not sure how to display the values in the bracket we only able to display 3 trips.
Is there a way to also display the values in the bracket stated as well?
we use
int min = *min_element(vTrips.begin(), vTrips.end());
cout << "Fastest: " << min << " trips" << endl;
but this only display the 3 trips.
#include <iostream>
#include <vector>
#include <iterator>
#include <fstream>
#include<algorithm>
using namespace std;
class CTS //cargo transport system
{
int i;
int cargo, lorryprice, vanprice, lorrysize, vansize, allOps;
public:
void set_cargo(int);
void set_lorryprice(int);
void set_vanprice(int);
void set_lorrysize(int);
void set_vansize(int);
};
void CTS::set_cargo(int total_cargo) {
cargo = total_cargo;
}
void CTS::set_lorryprice(int lorryP) {
lorryprice = lorryP;
}
void CTS::set_vanprice(int vanP) {
vanprice = vanP;
}
void CTS::set_lorrysize(int lorryS) {
lorrysize = lorryS;
}
void CTS::set_vansize(int vanS)
{
vansize = vanS;
}
int main()
{
int cargo, lorryprice, vanprice, lorrysize, vansize, options, i, no_lorry, no_van, cost, trips;
ifstream infile;
infile.open("size.txt");
if (infile.is_open()) {
infile >> cargo;
infile >> lorryprice;
infile >> vanprice;
infile >> lorrysize;
infile >> vansize;
}
CTS run;
run.set_cargo(cargo);
run.set_lorryprice(lorryprice);
run.set_vanprice(vanprice);
run.set_lorrysize(lorrysize);
run.set_vansize(vansize);
infile.close();
options = (cargo / lorrysize) + 1;
no_lorry = (cargo / lorrysize);
no_van = (cargo / vansize) + 3;
if (cargo % lorrysize == 0) {
no_van = -3;
}
if (cargo % lorrysize != 0) {
no_van = ((cargo % lorrysize) / 10) - 3;
}
/*it = numbervan.begin();
for (auto ir = numbervan.rbegin(); ir != numbervan.rend(); ++ir) {
cout << *ir << endl;
}*/
vector<int> vCost, vVan, vTrips, vLorry;
vector <int>::iterator it;
for (i = 1; i < options + 1; i++)
{
int numberlorry = no_lorry;
cout << "Option " << i << ":" << endl;
cout << "Number of Mini-Lorries : " << no_lorry-- << endl;
if (no_van >= -3) {
no_van += 3;
}
cout << "Number of Vans : " << no_van << endl;
int numbervan = no_van;
if (numberlorry > numbervan) {
trips = numberlorry;
}
else {
trips = numbervan;
}
cout << "Trips Needed : " << trips << endl;
cost = (numberlorry * lorryprice) + (no_van * vanprice);
cout << "Total Cost : $" << cost << endl;
vCost.push_back(cost);
vLorry.push_back(numberlorry);
vVan.push_back(numbervan);
vTrips.push_back(trips);
}
int counter = vCost.size() - 1;
//std::vector<int>::reverse_iterator ir = vCost.rbegin();
for (i = 1; i < 4; i++) {
//cout << "Lowest #" << i << ": "<<cost<<endl;
cout << "Lowest #" << i << ": $" << vCost[counter] << "(" << vVan[counter] << " Vans, " << vLorry[counter] << " Mini-Lorry, " << vTrips[counter] << " Trips)" << endl;
counter--;
}
int min = *min_element(vTrips.begin(), vTrips.end()); // this line of code we figured out how to
cout << "Fastest: " << min << " trips" << endl; //display the number of trips using algorithm
return 0;
}
Your design is awkward; you create an instance of CTS run; and never use it.
Assuming that you do your calculations right, you need to know at what index you found min. If you store the iterator returned by min_element(), you can get an index by subtracting vTrips.begin() from it. Then the corresponding elements in your vCost, vLorry and vVan vectors will contain the data you want.
However, it would be easier if you define a struct containing your pre-calculated values, and push that into some vector. In that case, all related data is kept together.

Printing floats with setw and setprecision - output doesn't line up

I'm trying to print matrix in C++ using std::cout, but I have no idea how to do this correct.
I tried such variants as setw() and setprecision(), but still not achived desired appearance(You can see it on the bottom of this question).
Matrix.cpp
template<class T>
class Matrix
{
public:
...
void print(int precision=5);
...
private:
size_t rows;
size_t cols;
std::vector<T> data;
};
template<class T>
void Matrix<T>::print(int precision)
{
for (int i = 0; i < (int)this->rows; i++) {
for (int j = 0; j < (int)this->cols; j++) {
//cout << ... << " ";
}
cout << endl;
}
cout << endl;
}
Main.cpp
...
int main()
{
...
matrix.print(4);
...
}
Some attempts:
cout << data.at(i*cols + j) << " ";
Output:
-21.4269 -11.9088 -14.8804 -11.1715 3.77597
16.1763 10.68 7.99879 -0.849034 -11.9758
15.7518 -19.1033 6.27838 -3.86534 21.4716
cout << fixed << data.at(i*cols + j) << " ";
Output:
-21.426937 -11.908819 -14.880438 -11.171500 3.775967
16.176332 10.679954 7.998794 -0.849034 -11.975848
15.751815 -19.103265 6.278383 -3.865339 21.471623
Here I'm trying to use setprecision()
cout << setprecision(precision) << data.at(i*cols + j) << " ";
Output:
-21.43 -11.91 -14.88 -11.17 3.776
16.18 10.68 7.999 -0.849 -11.98
15.75 -19.1 6.278 -3.865 21.47
cout << setprecision(precision) << fixed << data.at(i*cols + j) << " ";
Output:
-21.4269 -11.9088 -14.8804 -11.1715 3.7760
16.1763 10.6800 7.9988 -0.8490 -11.9758
15.7518 -19.1033 6.2784 -3.8653 21.4716
And here I'm using setw()
cout << setw(precision) << data.at(i*cols + j) << " ";
Output:
-21.4269 -11.9088 -14.8804 -11.1715 3.77597
16.1763 10.68 7.99879 -0.849034 -11.9758
15.7518 -19.1033 6.27838 -3.86534 21.4716
cout << setw(precision) << fixed << data.at(i*cols + j) << " ";
Output:
-21.426937 -11.908819 -14.880438 -11.171500 3.775967
16.176332 10.679954 7.998794 -0.849034 -11.975848
15.751815 -19.103265 6.278383 -3.865339 21.471623
And what I really need:
-21.42 -11.91 -14.88 -11.17 3.7760
16.176 10.680 7.9988 -0.849 -11.98
15.752 -19.10 6.2784 -3.865 21.472
It turns that I just need to call function with bigger argument:
cout << setw(10) << fixed << data.at(i*cols + j) << " ";
Output:
-21.426937 -11.908819 -14.880438 -11.171500 3.775967
16.176332 10.679954 7.998794 -0.849034 -11.975848
15.751815 -19.103265 6.278383 -3.865339 21.471623
And yes, answer under link that provided #Andy is even better because it more customizable.