I have this code below which parses a for statement, but I am not sure how to put any value into the ostream when calling the method write(...). What can I do? (e.g write("for (........."))
#include <ostream>
#include <iostream>
using namespace std;
//I cut out the declaration bit here
typedef const string type;
private:
type *initializer;
type *condition;
type *increment;
type *body;
public:
void write(ostream& stream) const {
stream
<< "for ("
<< *initializer << "; "
<< *condition << "; "
<< *increment << ")\n{\n"
<< *body
<< "}";
}
I guess you try to learn using ostream as an input in a function. But it seems that you mixing things that how to use classs and methods.
Maybe this is no avail but i can give you a little snippet to give you some opinion.
#include <iostream>
#include <string>
using namespace std;
typedef const string type;
type *init;
type *cond;
type *incr;
type *body;
void write(ostream& stream) {
stream
<< "for ("
<< *init << "; "
<< *cond << "; "
<< *incr << ")\n{\n"
<< *body
<< "\n}";
}
int main(int argc, char* argv[])
{
const string ini = "int i = 0";
const string con = "i < 10";
const string inc = "i++";
const string bod = "cout << i << endl;";
init = &ini;
cond = &con;
incr = &inc;
body = &bod;
write(cout);
return 0;
}
Try this code, examine and read more for more details.
Related
This is an assignment of mine that I picked to do but I am not sure how to fix the error message I am getting at cout << contact.getInformation() << endl;without changing the Void function to a different type or changing the main function (which I am trying to avoid). I think my lack of understanding is in how cout and void functions work together. I tried to remove the cout from the function but that did not work and the only way I could make the code run was when I replaced cout << contact.getInformation() << endl; with contact.getInformation() which I am trying to avoid. I just want the inside of the void function to print when I call cout << contact.getInformation() << endl;
Any help is welcome! Thank you!
#include <stdio.h>
#include <iostream>
#include <string>
using namespace std;
class Contact{
public:
Contact(int id, string name, string telephone, int age)
: _id{ id }, _name{ name }, _telephone{ telephone }, _age{ age } {}
int id() { return _id; }
string name() { return _name; }
string telephone() { return _telephone; }
int age() { return _age; }
void getInformation() {
cout << "ID: " + to_string(_id) + "\n" +
"NAME: " + _name + "\n" +
"TEL: " + _telephone + "\n" +
"AGE: " + to_string(_age) + "\n";
}
private:
int _id;
string _name;
string _telephone;
int _age;
};
int main() {
Contact contact{1, "Michael", "555-555-5555", 15};
cout << contact.getInformation() << endl;
}.
EDIT: Thanks all! I see now that it is impossible to do with those restrictions.
The code you've provided have many issues. You can avoid them if you read some good C++ book, my advice is Scott Meyers Effective C++: 55 Specific Ways to Improve Your Programs and Designs.
don't use using directive unless really necessary. In most cases for std namespace - it is not.
Pass function arguments of non primitive type by reference/const reference rather by value or pointer
Understand const keyword and it usage
Understand constructor static initialization bocks
Understand c++ streams
This is how you code should looks like:
#include <iostream>
#include <string>
class Contact {
public:
Contact(int id,const std::string& name,const std::string& telephone, int age):
_id( id ),
_name( name ),
_telephone( telephone ),
_age( age )
{}
int id() const {
return _id;
}
std::string name() const {
return _name;
}
std::string telephone() const {
return _telephone;
}
int age() const {
return _age;
}
private:
int _id;
std::string _name;
std::string _telephone;
int _age;
};
std::ostream& operator<<(std::ostream& to,const Contact& c)
{
to << "ID: " << c.id() << '\n';
to << "NAME: " << c.name() << '\n';
to << "TEL: " << c.telephone() << '\n';
to << "AGE: " << c.age() << '\n';
to.flush();
return to;
}
int main(int argc, const char** argv)
{
Contact contact = {1, "Michael", "555-555-5555", 15};
std::cout << contact << std::endl;
return 0;
}
What you are asking is not possible. The two conditions you have set (i.e. 1. Do not change the void function to another type, and 2. Do not alter the main method) make it impossible to change your code in some other way so as for the main function to produce the intended outcome.
You can either alter your void function to one that returns something 'printable', e.g. a string, or you can keep your void function printing to cout directly, but then change the main function to call this on its own, outside the context of a cout << construct.
(Or, preferably, as has also been pointed in the comments, instead of void, overload the << operator to make cout work with your specific object type)
The name getInformation suggests it should, well, get the information and not print it.
Therefore you probably want this:
string getInformation() {
return "ID: " + to_string(_id) + "\n" +
"NAME: " + _name + "\n" +
"TEL: " + _telephone + "\n" +
"AGE: " + to_string(_age) + "\n";
}
Instead of this:
void getInformation() {
cout << "ID: " + to_string(_id) + "\n" +
"NAME: " + _name + "\n" +
"TEL: " + _telephone + "\n" +
"AGE: " + to_string(_age) + "\n";
}
Not changing main nor getInformation is not possible.
I am beginning to teach myself C++ and have come across an error for which I believe is quite simple but not catching it. I created the following header file named EmployeeT.h
#ifndef EMPLOYEET_H_INCLUDED
#define EMPLOYEET_H_INCLUDED
typedef struct
{
char firstInitial;
char middleInitial;
char lastInitial;
int employeeNumber;
int salary;
} EmployeeT
#endif // EMPLOYEET_H_INCLUDED
with the main as
#include <iostream>
#inclide <Employee.h>
using namespace std;
int main()
{
EmployeeT anEmployee;
anEmployee.firstInitial = 'M';
anEmployee.middleInitial = 'R';
anEmployee.lastInitial = 'G';
anEmployee.employeeNumber = 42;
anEmployee.salary = 80000;
cout << "Employee: " << anEmployee.firstInitial <<
anEmployee.middleInitial <<
anEmployee.lastInitial << endl;
cout << "Number: " << anEmployee.employeeNumber << endl;
cout << "Salary: " << anEmployee.salary <<endl;
return 0;
}
You missed semicolon:
typedef struct
{
char firstInitial;
char middleInitial;
char lastInitial;
int employeeNumber;
int salary;
} EmployeeT;
//^^Must not miss this ;
Meanwhile:
#inclide <Employee.h>
//^^typo
should be:
#include "Employee.h"
Last point: you may initialize your struct as follows:
anEmployee = {'M','R','G',42, 80000};
//It will assign values to field in automatic way
If you are curious, you may also take a look at uniform initialization which is introduced since C++11.
In main don't you want to #include "EmployeeT.h" instead of #include <Employee.h>?
I am getting a linker error undefined reference to Person::Person when trying to implement my program. The three parts are below. I have been working on fixing it for a few hours now. I know it's probably something simple that I am just not seeing. But I have looked around on the internet and still have not found my answer. So any help would be appreciated.
#ifndef PERSON0_H_
#define PERSON0_H_
#include <string>
class Person // class declaration
{
private:
static const int LIMIT = 25;
std::string lname;
char fname[LIMIT];
public:
Person() {lname = ""; fname[0] = '\0';}
Person(const std::string & ln, const char * fn = "Hay you");
void Show() const;
void FormalShow() const;
};
#endif
#include <iostream>
#include <string>
#include "person0.h"
void Person::Show() const
{
using namespace std;
std::cout << fname << " " << lname << '\n';
}
void Person::FormalShow() const
{
using std::cout;
std::cout << lname << ", " << fname << '\n';
}
#include <iostream>
#include <string>
#include "person0.h"
int main()
{
using namespace std;
Person one;
Person two("Smythecraft");
Person three("Dimwiddy", "Sam");
one.Show();
cout << endl;
one.FormalShow();
cout << endl;
two.Show();
cout << endl;
two.FormalShow();
cout << endl;
three.Show();
cout << endl;
three.FormalShow();
cin.get();
cin.get();
return 0;
}
I am not really a C++ person, so the terminology might be wrong, but I would say that the implementation of the
Person::Person(const std::string & ln, const char * fn)
constructor is missing.
I need to find a better solution to pass the data type into boost::variant so that the function can retrieve the stored variate type elegantly. I have put up an implementation that works for me but I am concern there is a better way out there.
// file name: p192.cpp
#include <iostream>
#include <iomanip>
#include <string>
#include <map>
#include <boost/variant.hpp>
using namespace std;
enum TypePassIn
{
INT_TYPE,
DOUBLE_TYPE,
STRING_TYPE,
PERSON_TYPE,
LAST_TYPE = PERSON_TYPE
};
struct Person
{
Person(int _age, string _name) : age(_age), name(_name) {}
int age;
string name;
};
void PrintVariant(map<string, boost::variant<int, double, string, Person> > _mapValues, TypePassIn tpi)
{
switch(tpi)
{
case INT_TYPE:
cout << boost::get<int>(_mapValues["int"]) << endl;
break;
case DOUBLE_TYPE:
cout << setprecision (15) << boost::get<double>(_mapValues["double"]) << endl;
break;
case STRING_TYPE:
cout << boost::get<string>(_mapValues["string"]) << endl;
break;
case PERSON_TYPE:
cout << "Age: " << (boost::get<Person>(_mapValues["Person"])).age;
cout << ", Name: " << (boost::get<Person>(_mapValues["Person"])).name << endl;
break;
default:
break;
}
}
int main(void)
{ map<string, boost::variant<int, double, string, Person> > mapValues;
mapValues["int"] = 10;
PrintVariant(mapValues, INT_TYPE);
mapValues["double"] = 100.99;
PrintVariant(mapValues, DOUBLE_TYPE);
mapValues["string"] = "Hello world";
PrintVariant(mapValues, STRING_TYPE);
mapValues["Person"] = Person(10, "Tom");
PrintVariant(mapValues, PERSON_TYPE);
}
~/Documents/C++/boost $ ./p192
10
100.99
Hello world
Age: 10, Name: Tom
As you can see from the code above, the implemented method can handle both native type and customized data type. In the ideal case, we can do it without introducing the enum TypePassIn
You can use the (static) visitor pattern, as shown in the tutorial of Boost.Variant.
struct VariantPrinter : boost::static_visitor<void>
{
void operator()(int int_val)
{
std::cout << int_val << std::endl;
}
void operator()(double double_val)
{
std::cout << std::setprecision(15) << double_val << std::endl;
}
// etc.
};
void PrintVariant(const boost::variant<...>& the_variant)
{
boost::apply_visitor(VariantPrinter(), the_variant);
}
int main()
{
std::map<std::string, boost::variant<...> > mapValues;
mapValues["int"] = 10;
PrintVariant(mapValues["int"]);
}
Is anyone aware of an online resource where I can find out how to write a simple expression parser using Boost::Spirit?.
I do not necessarily need to evaluate the expression, but I need to parse it and be able to return a boolean to indicate whether the expression is parsable or not (e.g. brackets not matching etc).
I need the parser to be able recognise function names (e.g. foo and foobar), so this would also be a useful example to help me learn writing BNF notation.
The expressions will be normal arithmetic equations, i.e. comprising of the following symbols:
opening/closing brackets
arithmetic operators
recognized function names, and check for their required arguments
Here's some old Spirit prototype code I had laying around:
#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
#include <exception>
#include <iterator>
#include <sstream>
#include <list>
#include <boost/spirit.hpp>
#include <boost/shared_ptr.hpp>
using namespace std;
using namespace boost::spirit;
using namespace boost;
void g(unsigned int i)
{
cout << "row: " << i << endl;
}
struct u
{
u(const char* c): s(c) {}
void operator()(const char* first, const char* last) const
{
cout << s << ": " << string(first, last) << endl;
}
private:
string s;
};
struct Exp
{
};
struct Range: public Exp
{
};
struct Index: public Exp
{
};
struct String: public Exp
{
};
struct Op
{
virtual ~Op() = 0;
virtual string name() = 0;
};
Op::~Op() {}
struct CountIf: public Op
{
string name() { return "CountIf"; }
};
struct Sum: public Op
{
string name() { return "Sum"; }
};
struct Statement
{
virtual ~Statement() = 0;
virtual void print() = 0;
};
Statement::~Statement() {}
struct Formula: public Statement
{
Formula(const char* first, const char* last): s(first, last), op(new CountIf)
{
typedef rule<phrase_scanner_t> r_t;
r_t r_index = (+alpha_p)[u("col")] >> uint_p[&g];
r_t r_range = r_index >> ':' >> r_index;
r_t r_string = ch_p('\"') >> *alnum_p >> '\"';
r_t r_exp = r_range | r_index | r_string; // will invoke actions for index twice due to range
r_t r_list = !(r_exp[u("arg")] % ',');
r_t r_op = as_lower_d["countif"] | as_lower_d["sum"];
r_t r_formula = r_op >> '(' >> r_list >> ')';
cout << s << ": matched: " << boolalpha << parse(s.c_str(), r_formula, space_p).full << endl;
}
void print() { cout << "Formula: " << s << " / " << op->name() << endl; }
private:
string s;
shared_ptr<Op> op;
list<shared_ptr<Exp> > exp_list;
};
struct Comment: public Statement
{
Comment(const char* first, const char* last): comment(first, last) {}
void print() {cout << "Comment: " << comment << endl; }
private:
string comment;
};
struct MakeFormula
{
MakeFormula(list<shared_ptr<Statement> >& list_): list(list_) {}
void operator()(const char* first, const char* last) const
{
cout << "MakeFormula: " << string(first, last) << endl;
list.push_back(shared_ptr<Statement>(new Formula(first, last)));
}
private:
list<shared_ptr<Statement> >& list;
};
struct MakeComment
{
MakeComment(list<shared_ptr<Statement> >& list_): list(list_) {}
void operator()(const char* first, const char* last) const
{
cout << "MakeComment: " << string(first, last) << endl;
list.push_back(shared_ptr<Statement>(new Comment(first, last)));
}
private:
list<shared_ptr<Statement> >& list;
};
int main(int argc, char* argv[])
try
{
//typedef vector<string> v_t;
//v_t v(argv + 1, argv + argc);
// copy(v.begin(), v.end(), ostream_iterator<v_t::value_type>(cout, "\n"));
string s;
getline(cin, s);
// =COUNTIF(J2:J36, "Abc")
typedef list<shared_ptr<Statement> > list_t;
list_t list;
typedef rule<phrase_scanner_t> r_t;
r_t r_index = (+alpha_p)[u("col")] >> uint_p[&g];
r_t r_range = r_index >> ':' >> r_index;
r_t r_string = ch_p('\"') >> *alnum_p >> '\"';
r_t r_exp = r_range | r_index | r_string; // will invoke actions for index twice due to range
r_t r_list = !(r_exp[u("arg")] % ',');
r_t r_op = as_lower_d["countif"] | as_lower_d["sum"];
r_t r_formula = r_op >> '(' >> r_list >> ')';
r_t r_statement = (ch_p('=') >> r_formula [MakeFormula(list)])
| (ch_p('\'') >> (*anychar_p)[MakeComment(list)])
;
cout << s << ": matched: " << boolalpha << parse(s.c_str(), r_statement, space_p).full << endl;
for (list_t::const_iterator it = list.begin(); it != list.end(); ++it)
{
(*it)->print();
}
}
catch(const exception& ex)
{
cerr << "Error: " << ex.what() << endl;
}
Try running it and entering a line like:
=COUNTIF(J2:J36, "Abc")
The current version of Spirit (V2.x) contains a whole series of calculator examples from the very simple to a full fledged mini-c interpreter. You should have a look there as those are a perfect starting point for writing your own expression parser.
I'm not sure if this qualifies as simple either, but I've used this uri-grammar available at http://code.google.com/p/uri-grammar/source/browse/trunk/src/uri/grammar.hpp. It may not be trivial, but at least its parsing something that you probably understand already (URIs). When reading these grammars, its best to read from the bottom up, since that's where the most generic tokens tend to be defined.