Here's the main function ex1-1.cpp
#include <iostream>
#include "ex1-1.h"
using namespace Complex;
int main(int argc, char *argv[])
{
Cplex a={0.0,0.0}, b={0.0,0.0},c={0.0,0.0}, d={0.0,0.0};
// use struct named Cplex under namespace Complex
ReadTextFile(argv[1], a, b);// process text file
std::cout<<a.real<<std::showpos<<a.image<<std::endl;
std::cout<<b.real<<std::showpos<<b.image<<std::endl;
return 0;
}
one header ex1-1.h
#include <iostream>
#include <fstream>
namespace Complex
{
typedef struct
{
double real;
double image;
}Cplex;
Cplex ReadTextFile(char argv[],Cplex a,Cplex b);
}
and one for functions ex1-1-function.cpp
#include<iostream>
#include<fstream>
#include<iomanip>
#include "ex1-1.h"
namespace Complex
{
Cplex ReadTextFile(char argv[],Cplex a,Cplex b)
{
std::ifstream fin;
fin.open("complex.txt");
char i;
fin>>a.real>>a.image>>i;
fin>>b.real>>b.image>>i;
std::cout<<std::noshowpos<<a.real<<std::showpos<<a.image<<"i"<<std::endl;
std::cout<<std::noshowpos<<b.real<<std::showpos<<b.image<<"i"<<std::endl;
return (a,b);
};
}
the text file complex.txt looks like this
1.5+6i
-2-10i
I tried to define a type of structure called Cplex, including two members, real and image
declare Cplex a and Cplex b
then use function ReadTextFileread(argv[1],a,b) to read in two complex numbers and store in the structures a and b
then return a and b at once
But no matter how I tried the main function can only read b instead of both
How can I pass two structures to the main function at once?
Or should I use Array to contain two structures then pass it?
You can use std::pair to couple two values together:
std::pair<Cplex> ReadTextFile(char argv[])
{
Cplex a, b;
...
return { a, b };
};
Then use them like this:
#include <tuple>
...
Cplex a, b;
std::tie(a, b) = ReadTextFile(argv);
Note that std::tie is only available since C++11.
Or if you can use C++17 it will be even simpler to use structured binding:
auto [a, b] = ReadTextFile(argv);
In C & C++ you can return only one value from the function.
Instead use pass by reference to pass the structs 'a' and 'b' and then fill the values within the function.
Declaration:
void ReadTextFile(char argv[],Cplex &a,Cplex &b);
Definition:
void ReadTextFile(char argv[],Cplex& a,Cplex& b)
{
std::ifstream fin;
fin.open("complex.txt");
char i;
fin>>a.real>>a.image>>i; // values filled here can now be read in the caller i.e main.
fin>>b.real>>b.image>>i;
std::cout<<std::noshowpos<<a.real<<std::showpos<<a.image<<"i"<<std::endl;
std::cout<<std::noshowpos<<b.real<<std::showpos<<b.image<<"i"<<std::endl;
return;
};
Hope this helps.
Related
I would like to ask if it would be possible to declare 2 variables on one line like above (on the same line):
#include <iostream>
#include <string>
using namespace std;
string a, double b;
int main()
{
return 0;
}
Your declaration has the wrong syntax.
string a, double b;
should be string a; double b;.
If you want to declare two variables with a comma they need to have the same type.
Same variable types: YES
Different variable types: NO
Different variables need to be on different lines OR separated with a semicolon ; as it signals a new line e.g.
int a; double b; bool c;
Which is the same as,
int a;
double b;
bool c;
If they're the same type you can use a comma , e.g.
int a, b, c;
I have a fairly simple program. It reads a matrix from a file that looks like this
4 4
a b c d
a b c d
a b c d
a b c d
and outputs it in the console. The program is working as intended:
#include <iostream>
#include <fstream>
using namespace std;
int main() {
int n, m;
ifstream myfile;
myfile.open ("matrix.txt");
myfile >> n >> m;
char mat[n][m];
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
myfile >> mat[i][j];
}
}
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
cout << mat[i][j];
}
cout << endl;
}
return 0;
}
Now this program is going to grow a lot, so I want to start using headerfiles and declare the functions external so that my main looks more like
int main() {
readMat();
printMat();
}
My Problem is, I don't really know how to do this right. Where should I declare the matrix so that both functions can "see" it? I can't declare it globally as char mat[n][m] because I only know n and m inside readMat().
Or is my whole design flawed and there is much better way to do this?
I would be grateful for every little tip.
I have not worked with multiple files in c++ yet.
You cannot use an array like that, when not just multiple translation units, but multiple functions are involved.
Any function needs to know the exact data types it receives as parameters, and this must be declared at compile time.
Here, you don't know the type of the array until runtime. array[10] and array[15] are different types. Don't be fooled by the fact their name might be the same. It's not the name that matters, but the type, like int [10] or int [11].
You have two basic options:
Use templates.
Convert your array to a std::vector<std::vector<int>>. Then you can declare the array (now a vector) globally, and/or pass it as a parameter to your multiple functions.
Matrix.h
#ifndef MATRIX_H
#define MATRIX_H
namespace mynamespace {
template <class T>
class Matrix {
private:
int m_rows;
int m_columns;
T** m_data;
public:
Matrix(); // Default Constructor - Null or Empty Matrix
Matrix( const int rows, const int columns ); // Empty Matrix With Defined Size
Matrix( const int rows, const int columns, const T** data ); // Defined Matrix
T** getData() const;
}; // Matrix
#include "Matrix.inl"
} // mynamespace
#endif // MATRIX_H
Matrix.inl
// Matrix Constructor and Function Implementations Here
Matrix.cpp
#include "Matrix.h"
Main.cpp
#include <string>
#include <iostream>
#include <fstream>
#include "Matrix.h"
using namespace mynamespace;
void readMatrix( std::fstream& fin, const std::string& strFilename, Matrix& matrixIn );
void printMatrix( const Matrix& matrix );
int main() {
std::fstream fileIn; // Prefer to not use "using namespace std;"
std::string strFilename( "Matrix.txt" );
Matrix<type> mat(); // Default Empty Matrix To Be Filled In
readMatrix( fileIn, strFilename, mat );
printMatrix( mat );
return 0;
} // main
void readMatrix( std::fstream& fin, const std::string& strFilename, Matrix& mat ) {
// Do Work Here To Populate Matrix Object
} // readMatrix
void printMatrix( Matrix& mat ) {
// Do Work Here To Print Matrix Being Passed In
} // printMatrix
With this pseudo code, the design here allows any type of matrix to be constructed. The matrix is an object of a template type. The implementation of generating a matrix by reading in data from a file, and the implementation of displaying or printing that matrix are independent of the class itself. This allows for the matrix class to be as generic as possible without having to rely on any other libraries. The functions that do the work are stand alone functions that accept a matrix object. A modification may be needed in your text or binary file to work with this construct.
matrix.txt
type
4 4
a b c d
a b c d
a b c d
a b c d
The only problem with this, is it should already be obvious: you need to define what type of data this matrix will hold when instantiating it. Yet you do not know the type until after you read the file in. So this code does have a bug in it that would need to be address. However, the overall design method used here is to only show how to keep similar code objects contained with in their own class object while separating independent code blocks that does work on them. Now other class objects may have a file reading and print methods, but normally Vector (math & not containers) and Matrix classes usually don't.
I defined a class as well as member function. And now I would like to call the data type(x.dat) imported from outside.
How could I do that?
It would be something like this:
class abs{
private:
...
public:
...
void function(data){ //here i would like to use the external data x.dat
...
}
}
Yes, Keith is correct.
What you want is a static variable that maintains the same data across all objects of that type. You don't necessarily need a function to do this.
#include <iostream>
#include <string>
using namespace std;
class abs
{
private:
public:
static double data[3];
};
double abs::data[3]={}; //instantiate the variable
int main () {
abs::data[0]=5.0;
cout<<abs::data[0]; //outputs 5
}
Static variables are associated with the class definition, and not the instantiated objects of that type so as long as the program is active it will be stored in memory as part of the class.
Firstly, tremendous thanks to all of you, especially #Mir
I get it running now, although I don't know why does someone give me a negative!?
I would like to make a summary here, for myself, and future readers.
My question is this:
I have a stored data(double[1000]), which is a file of 'x.dat';
And I define a class 'abs' in the header file, as well as its member function 'function';
And 'function' would like to call data as a inputting parameter.
How to do these?
With the help of Mir, it's working now like this, hope it would help someone:
1.abs.h
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
class abs
{
private:
public:
static double data[1000];
double function(double xa[]){
for(int i=0;i<1000;i++){
res += xa[i] * 2.0;
}
return res;
}
};
2.abs.cpp
#include "abs.h"
double abs::data[1000]={}; //instantiate the variable
3.main.cpp
#include "abs.h"
int main () {
abs a = abs();
for(int i = 0; i < 1000, i++){
ifstream fs("x.dat")
fs >> abs::data[i];
cout << abs::data[i]; //outputs all data
}
double Value = a.function(data);
cout<< Value<<endl;
}
I want to bind a member to store a function object outside of the class instance. Howeber, in VS2012 this only works up to placeholders::_4, then it starts popping up with errors. Take this for example:
#include <iostream>
#include <functional>
using namespace std;
using namespace std::placeholders;
class A
{
public:
int method(int a,int b,int c,int d,int e)
{
return a;
}
};
int main()
{
std::function<int (int,int,int,int,int)> obj;
A a;
// error: no instance of overloaded function "std::bind" matches the argument list
obj = std::bind(&A::method,&a,_1,_2,_3,_4,_5);
std::cout << obj(1,2,3,4,5);
return 0;
}
The above code compiles fine on GCC 4.7.2 but causes the above-mentioned error in Visual Studio 2012. Are there any workarounds, is this a bug in VC++ or am I doing something dodgy here?
Since Visual Studiio does not support variadic templates this is solved by a define.
You can set a define _VARIADIC_MAX to the amount of params you need. Do this in your projects settings to that it is set before any system headers are included.
But keep in mind that setting this value to a large number will increase compile times.
One alternative would be to use a lambda instead like this:
#include <iostream>
#include <functional>
using namespace std;
using namespace std::placeholders;
class A
{
public:
int method(int a, int b, int c, int d, int e)
{
return a;
}
};
int main()
{
std::function<int(int, int, int, int, int)> obj;
A a;
obj = [&a](int b, int c, int d, int e, int f){return a.method(b,c,d,e,f); };
std::cout << obj(1, 2, 3, 4, 5);
return 0;
}
edit: it seems like this won't work either without following #mkaes answer, since apparently the definition of the std::function depends on it.
I have two simple testing lines:
cout<<(cout<<"ok"<<endl, 8)<<endl;
cout<<(int i(8), 8)<<endl;
The first line worked, but the second failed compilation with
error: expected primary-expression before 'int'
For some reason, I do need a declaration in the comma operator. To be more specific, I want to declare some variables, obtain their values, and assign them to my constant class members from the initialization list of my class constructor. Following shows my intentions. If not achievable using comma operator, any another suggestions?
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <cstdlib>
using namespace std;
void readFile(const string & fileName, int & a, int & b)
{
fstream fin(fileName.c_str());
if (!fin.good()) {cerr<<"file not found!"<<endl; exit(1);}
string line;
getline(fin, line);
stringstream ss(line);
try {ss>>a>>b;}
catch (...) {cerr<<"the first two entries in file "<<fileName<<" have to be numbers!"<<endl; exit(1);}
fin.close();
}
class A
{
private:
const int _a;
const int _b;
public:
A(const string & fileName)
:
_a((int a, int b, readFile(fileName,a,b), a)),
_b((int a, int b, readFile(fileName,a,b), b))
{
/*
int a, b;
readFile(fileName,a,b);
_a = a;_b = b;
*/
}
void show(){cout<<_a<<" "<<_b<<endl;}
};
int main()
{
A a("a.txt");
a.show();
}
Declarations are statements and not expressions. You cannot place statements inside of expressions, though you can place expressions inside of statements. Accordingly, you cannot declare a variable in the way that you're describing above. You'll need to separate it out into multiple different statements.
I would be surprised if if you actually needed to do this. If you do, there is probably something problematic about your design.
Hope this helps!
You should have a look at Boost Phoenix (which has phoenix::let to do roughly this). Bear in mind, Phoenix is an eDSL, really (embedded domain specific language).
You could do an ugly trick and abuse lambdas:
cout<< ([]->int{ int i(8); return 8; })() <<endl;
A lambda allows a declaration within an expression. So this is possible:
std::cout << ([]{ int i(8); m_i = i; }(), 8) << std::endl;
But it's really weird - I assume this will be in some #define macro that makes it appear closer to normal.
You cannot. This is unpossible in C++. The fact that you are trying to do this is also a code smell. Something's not right here.
I want to declare some variables, obtain their values, and assign them
to my constant class members from the initialization list of my class
constructor. Not sure how to achieve this.
You didn't say what you intended to do with these variables you declare after you've used the values, but I'm guessing that once you've finished with the values, you've finished with the variables. In other words, they are temporary.
Your edited example suggests that my assumption is correct. It also confirms the code smell. Based on your (intended) code, you are going to read the file twice.
I'd say the most straightforward way to do this is to use an intermediary, kind of like a factory class. This also has the benefit of being able to read the file only once, as opposed to twice as you are doing now.
void readFile (const std::string& fileName, int& a, int& b)
{
// some magic
a = 42;
b = 314;
}
class FileReader
{
public:
FileReader (const std::string fileName)
:
mFileName (fileName),
mA (42),
mB (314)
{
// something happens like reading the file
}
int GetA () const
{
return mA;
}
int GetB () const
{
return mB;
}
private:
int mA;
int mB;
std::string mFileName;
};
class A
{
private:
const int mA;
const int mB;
public:
A (const FileReader& reader)
:
mA (reader.GetA()),
mB (reader.GetB())
{
}
};
Using this FileReader is simple:
int main()
{
A myA (FileReader ("somefile.txt"));
}