I've been searching around for the answer to this but so far nothing has worked.
I have two files that were provided to me for a Parser assignment, lex.h and parse.h. The lex.h file was used in a previous assignment and works fine, the parse.h file is giving me issues. The parse.h file looks like this:
#ifndef PARSE_H_
#define PARSE_H_
#include <iostream>
#include <map>
using namespace std;
#include "lex.h"
//using std::map;
map<string, bool> defVar;
namespace Parser {
bool pushed_back = false;
LexItem pushed_token;
static LexItem GetNextToken(istream& in, int& line) {
if( pushed_back ) {
pushed_back = false;
return pushed_token;
}
return getNextToken(in, line);
}
static void PushBackToken(LexItem & t) {
if( pushed_back ) {
abort();
}
pushed_back = true;
pushed_token = t;
}
}
static int error_count = 0;
void ParseError(int line, string msg)
{
++error_count;
cout << line << ": " << msg << endl;
}
extern bool Prog(istream& in, int& line);
extern bool StmtList(istream& in, int& line);
extern bool Stmt(istream& in, int& line);
extern bool PrintStmt(istream& in, int& line);
extern bool IfStmt(istream& in, int& line);
extern bool Var(istream& in, int& line);
extern bool AssignStmt(istream& in, int& line);
extern bool ExprList(istream& in, int& line);
extern bool Expr(istream& in, int& line);
extern bool Term(istream& in, int& line);
extern bool Factor(istream& in, int& line);
#endif /* PARSE_H_ */
Analyzer Class
#include <regex>
#include "lex.h"
/**
* Relates token type to string
*/
static std::map<Token, std::string> tokenPrint {
// Code not provided for readability
};
/**
* Operator overloading << for Token object
*/
ostream& operator<<(ostream& out, const LexItem& tok) {
// Code not provided for readability
}
/**
* Current token is used to set previous token before returned
* Previous token is used to compare to the current token and check
* for invalid arangment such as no begin token.
*/
LexItem currentToken;
LexItem previousToken;
/**
* Return the next token within a file
*/
LexItem getNextToken(istream& in, int& linenum) {
enum TokenState { START, INID, INSTRING, ININT, INREAL, INCOMMENT, SIGN} lexstate = START;
std::string lexeme;
char character;
// Code not provided for readability
}
Parse.cpp
#include "parse.h"
bool Prog(istream& in, int& line) {
return false;
}
bool StmtList(istream& in, int& line) {
return false;
}
// All the rest return false too
Tester.cpp
#include <iostream>
#include <fstream>
#include <vector>
#include <sstream>
#include <map>
#include "parse.h"
int main(int argc, char** argv) {
// Reads file and handles errors
// Code not provided for readability
while (true) {
Parse::getNextToken(file, lineNumber);
}
}
I have an Analyzer.cpp file that uses lex.h as a header for the Analyzer and I have a Parse.cpp that uses parse.h for the Parser. In the main program I use the parse.h header file.
I keep getting a multiple definition error with defVar, Parse::pushed_back, Parser::pushed_token, and ParseError(...). I cannot edit lex.h or parse.h as they are given to me and can only change the contents of Analyzer.cpp, Parser.cpp, and Tester.cpp. I can post all the code if necessary.
I'm fairly new to c++ but all the header files have the header guards and none of the functions are ever defined twice. I have looked at other problems but nothing seems to be working. Any help is greatly appreciated.
Related
So, I have a header file and a class file. But when I compile puzzle.cpp, I keep getting get_solution was not declared in this scope. I don't get why that error occurs since its inside the same class so I can call any function inside the same class. Can anyone please help me on this? Thanks!
puzzle.h
#ifndef PUZZLE_H
#define PUZZLE_H
#include<iostream>
#include <string>
#include <vector>
class puzzle{
private:
std::string _solution;
std::vector<bool> _guesses;
public:
puzzle(std::string solution);
std::string get_solution(){return _solution;}
bool guess(char c);
bool solve(std::string proposed_solution);
std::string to_string();
};
#endif
puzzle.cpp
#include <iostream>
#include "puzzle.h"
#include <string>
#include <vector>
using namespace std;
puzzle::puzzle(std::string solution) {
_solution = solution;
for(int i = 0; i < 256; i++)
_guesses.push_back(false);
}
bool puzzle::guess(char c){
int num = c;
if(c<='z' || c>='a')
if(_guesses.at(c) == false){
_guesses.at(c) == true;
return true;
}
return false;
}
bool solve(string proposed_solution){
string test = get_solution();
if(proposed_solution.compare(test) == 0)
return true;
return false;
}
string to_string(){
int len = get_solution().length();
return "";
}
It looks like you've forgotten to make solve and to_string member functions:
Change
string to_string(){ ...
bool solve(string proposed_solution){ ...
^^^
To
string puzzle::to_string(){ ...
bool puzzle::solve(string proposed_solution){ ...
Your function bool solve(string proposed_solution) does not define a member function of puzzle but a "plain" function; Hence, get_solution(); within its body is not recognized as a member of puzzle, too. You'll have to write bool puzzle::solve(string proposed_solution) { ... and it should work.
solve and to_string are supposed to be methods, so you need to prefix them with the class' name followed by two colons (i.e., puzzle::):
bool puzzle::solve(string proposed_solution){
// Code ...
}
string puzzle::to_string(){
// Code ...
}
I got these 2 files for now and anytime I want to compile I get the error
string does not name a type
in Bestellung.h on the line with std::string name;.
Why?
main.cpp
#include "Bestellung.h"
#include <iostream>
using namespace std;
int main()
{
Bestellung();
cout << Bestellung{"maki"} << endl;// [maki,10€]
}
Bestellung.cpp
#include "Bestellung.h"
Bestellung(string bestellV, double preisV = 10){
name = "bestell V";
preis = "preis V";
};
string get_name const(Bestellung v) {
return Bestellung.name;
};
double get_preis const(Bestellung v){
return Bestellung.preis;
};
ostream& print(ostream&) const {
};
Bestellung.h
#ifndef BESTELLUNG_H
#define BESTELLUNG_H
#include <string>
#include <iostream>
class Bestellung{
std::string name;
std::double preis;
public:
Bestellung(string, double = 10);
string get_name const {
};
double get_preis const {
};
ostream& print(ostream&) const {
};
};
#endif
You have to use a namespace qualifier. You have:
Bestellung(string,double=10);
You should have:
Bestellung(std::string,double=10);
You also have:
string get_name const {
You should have:
std::string get_name const {
If you don't want to specify the std namespace every time you use a string, you can do this near the beginning:
using std::string;
Doing that in header files is bad practice though, so I would just use the full qualifications like I said to first.
After correcting this error, you need to do the same thing to that ostream you have too.
Read more about namespaces here.
At the moment I am using a rather large piece of code to analyse data.
In this code apart from the analysis itself, I include some functions that will be used in the analysis, some function that are related to objects and some global variables. My code has the following structure
#include "header1.h"
#include "header2.h"
...
#define global_variable_1 1
#define global_variable_2 3
...
double function1(){
<code>
{
double function2(){
<code>
{
...
main(){
<code>
}
At the moment I want to make my code a bit more elegant, sophisticated and programmable correct. I am thinking of making a header file that will include the headers that I am using and some functions, a second header file with the rest of the functions and a last header file that will contain the global parameters that I use.
So I will have something like
#include "headers.h"
#include "functions.h"
#include "variables.h"
main(){
<code>
}
My question is whether it is programably proper to do so and if there is another and perhaps better way to include the global variables.
If you are trying to use variables that are global and you know that they are a constant value such as PI I would refrain from using both local globals and #define macros. This is a matter of preference but over time I've learned that it is better practice and more elegant to declare them as static const type name; in the header file and set the value accordingly in the cpp file. I also do not prefer to have a bunch of dangling values or basic methods hanging around so I usually will group similar types of values and methods and contain them in a class declaring them to be static. Here is an example:
Utility.h
#ifndef UTILITY_H
#define UTILITY_H
#include <iostream>
#include <string>
#include <stdio.h>
class Utility {
public:
static void pressAnyKeyToQuit();
static std::string& toUpper( std::string& str );
static std::string& toLower( std::string& str );
private:
Utility(); // Not Implemented - This class is not an object and can not be declared.
Utility( const Utility& c ); // Copy Constructor - Not Implemented
Utility& operator=( const Utility&c ); Assignment Operator - Not Implemented
}; // Utility
#endif // UTILITY_H
Utility.cpp
#include "Utility.h"
// -------------------------------------------------------------------------
// pressAnyKeyToQuit()
void Utility::pressAnyKeyToQuit() {
std::cout << "Press any key to quit" << std::endl;
_getch();
} // pressAnyKeyToQuit
// -------------------------------------------------------------------------
// toUpper()
std::string& Utility::toUper( std::string& str ) {
std::transform( str.begin(), str.end(), str.begin(), ::toupper );
return str;
} // toUpper
// -------------------------------------------------------------------------
// toLower()
std::string& Utility::toLower( std::string& str ) {
std::transform( str.begin(), str.end(), str.begin(), ::tolower );
return str;
} // toLower
To use these functions here is an example:
main.cpp
#include <iostream>
#include <string>
#include "Utility.h"
int main() {
std::string strHello( "Hello World!" );
std::cout << strHello << std::endl;
std::cout << Utility::toLower( strHello ) << std::endl;
std::cout << Utility::toUpper( strHello ) << std::endl;
Utility::pressAnyKeyToQuit();
return 0;
} // main
With this type of containment it is illegal to do this:
int main() {
Utility util;
util.pressAnyKeyToQuit();
} // main
This will fail because the Utility default constructor is private or inaccessible, however any type of function or variable that is declared as being static can be called through the scope resolution operator. Here is an example of const variables that would be considered globals.
GeneralMath.h
#ifndef GENERAL_MATH_H
#define GENERAL_MATH_H
class Math {
public:
static const float PI;
static const float PI_HAVLES;
static const float PI_2;
static const float ZERO;
inline static bool isZero( float fValue );
template<typename T>
inline static void swap( T& value1, T& value2 );
private:
Math();
Math( const Math& c ); // Not Implemented
Math& operator( const Math& c ); // Not Implemented
}; // Math
#include "GeneralMath.inl"
void dummy(); // does nothing used to have a method in the *.cpp file
#endif // GENERAL_MATH_H
GeneralMath.inl
// -------------------------------------------------------------------------
// isZero()
inline bool Math::isZero( float fValue ) {
if ( (fValue > -ZERO) && (fValue < ZERO) ) {
return true;
}
return false;
} // isZero
// -------------------------------------------------------------------------
// swap()
template<class T>
inline void Math::swap( T& value1, T& value2 ) {
T temp;
temp = value1;
value1 = value2;
value2 = temp;
} // swap
GeneralMath.cpp
#include "GeneralMath.h"
const float Math::PI = 4.0f * atan(1.0f); // tan(pi/4) = 1
const float Math::PI_HALVES = 0.5f * Math::PI;
const float Math::PI_2 = 2.0f * Math::PI;
const float Math::ZERO = static_cast<float>( 1e-7 );
void dummy(){return;}
Using it in an example:
main.cpp
#include <iostream>
#include "Utility.h"
#include "GeneralMath.h"
int main() {
float value = 3.14957;
if ( Math::isZero( value - Math::PI ) ) {
std::cout << "true" << std::endl;
} else {
std::cout << "false" << std::endl;
}
Utility::pressAnyKeyToQuit();
return 0;
} // main
I prefer this approach so that when common stand alone methods and constant variables are frequently used in multiple files and have a similar grouping you do not have a bunch of #defines or global's declared everywhere.
Now on the other hand if a specific class object that you are creating depends on a specific constant value that is unique to it then you can have a global in its *.h or *.cpp file but again I would still declare it as a static const type name;
The simplicity of this is to include the *.h file where it is needed and use the class name with the scope resolution operator followed by the const variable or static method where it is needed.
You can also do a similar approach without using a class and not declaring them as static by containing them in a namespace, but this could cause problems because other developers might have the same name space and this could create conflicts to resolve names. This is why I prefer the class approach and declaring them as static members.
Remember these classes are not Objects and they can not be constructed and all members have to be static!
Having issues compiling this header file provided by Bjourne Stroustrup and edited by my professor. I'm compiling on OS X 10.10.2 using command line tools. My compile command is " gcc -std=C++11 *cpp" and there is something about this code it just doesn't like. I ran this on Linux and my university's Unix server without issues. Any help is greatly appreciated.
I'll include the header file and then the error.
/*std_lib_facilities_4.h
Minimally revised for C++11 features of GCC 4.6.3 or later
Walter C. Daugherity June 10, 2012 and January 9, 2014
*/
/*
simple "Programming: Principles and Practice using C++" course header to
be used for the first few weeks.
It provides the most common standard headers (in the global namespace)
and minimal exception/error support.
Students: please don't try to understand the details of headers just yet.
All will be explained. This header is primarily used so that you don't have
to understand every concept all at once.
Revised April 25, 2010: simple_error() added
*/
#ifndef H112
#define H112 201401L
#define GCC_VERSION (__GNUC__*10000 + __GNUC_MINOR__*100 + __GNUC_PATCHLEVEL__)
#if GCC_VERSION >= 40603
//New C++11 headers in GCC 4.6.3 or later
#include <array>
#include <regex>
#include <thread>
#include <mutex>
#include <forward_list>
#include <ratio>
#include <tuple>
#include <chrono>
#include <random>
#endif
#include<iostream>
#include<fstream>
#include<sstream>
#include<cmath>
#include<cstdlib>
#include<string>
#include<list>
#include<vector>
#include<algorithm>
#include<stdexcept>
//------------------------------------------------------------------------------
#if GCC_VERSION >= 40603
#include <unordered_map>
#include <unordered_set>
#else
#define unordered_map hash_map
#ifdef _MSC_VER
#include <hash_map>
using stdext::hash_map;
#else
#include <ext/hash_map>
using __gnu_cxx::hash_map;
namespace __gnu_cxx {
template<> struct hash<std::string>
{
size_t operator()(const std::string& s) const
{
return hash<char*>()(s.c_str());
}
};
} // of namespace __gnu_cxx
#endif //_MSC_VER
#endif //GCC_VERSION >= 40603
//------------------------------------------------------------------------------
typedef long Unicode;
//------------------------------------------------------------------------------
using namespace std;
template<class T> string to_string(const T& t)
{
ostringstream os;
os << t;
return os.str();
}
struct Range_error : out_of_range { // enhanced vector range error reporting
int index;
Range_error(int i) :out_of_range("Range error: " + to_string(i)), index(i) { }
};
// trivially range-checked vector (no iterator checking):
template< class T> struct Vector : public std::vector<T> {
typedef typename std::vector<T>::size_type size_type;
Vector() { }
explicit Vector(size_type n) :std::vector<T>(n) {}
Vector(size_type n, const T& v) :std::vector<T>(n, v) {}
template <class I>
Vector(I first, I last) : std::vector<T>(first, last) {}
#if GCC_VERSION >= 40603
Vector(initializer_list<T> list) : std::vector<T>(list) {}
#endif
T& operator[](unsigned int i) // rather than return at(i);
{
if (this->size() <= i) throw Range_error(i);
return std::vector<T>::operator[](i);
}
const T& operator[](unsigned int i) const
{
if (this->size() <= i) throw Range_error(i);
return std::vector<T>::operator[](i);
}
};
// disgusting macro hack to get a range checked vector:
#define vector Vector
// trivially range-checked string (no iterator checking):
struct String : std::string {
String() { }
String(const char* p) :std::string(p) {}
String(const string& s) :std::string(s) {}
template<class S> String(S s) : std::string(s) {}
String(int sz, char val) :std::string(sz, val) {}
template<class Iter> String(Iter p1, Iter p2) : std::string(p1, p2) { }
char& operator[](unsigned int i) // rather than return at(i);
{
if (size() <= i) throw Range_error(i);
return std::string::operator[](i);
}
const char& operator[](unsigned int i) const
{
if (size() <= i) throw Range_error(i);
return std::string::operator[](i);
}
};
#ifndef _MSC_VER
#if GCC_VERSION >= 40603
namespace std {
template<> struct hash<String>
{
size_t operator()(const String& s) const
{
return hash<std::string>()(s);
}
};
} // of namespace std
#else
namespace __gnu_cxx {
template<> struct hash<String>
{
size_t operator()(const String& s) const
{
return hash<std::string>()(s);
}
};
} // of namespace __gnu_cxx
#endif //GCC_VERSION >= 40603
#endif //_MSC_VER
struct Exit : runtime_error {
Exit() : runtime_error("Exit") {}
};
// error() simply disguises throws:
inline void error(const string& s)
{
throw runtime_error(s);
}
inline void error(const string& s, const string& s2)
{
error(s + s2);
}
inline void error(const string& s, int i)
{
ostringstream os;
os << s << ": " << i;
error(os.str());
}
#if _MSC_VER<1500
// disgusting macro hack to get a range checked string:
#define string String
// MS C++ 9.0 have a built-in assert for string range check
// and uses "std::string" in several places so that macro substitution fails
#endif
template<class T> char* as_bytes(T& i) // needed for binary I/O
{
void* addr = &i; // get the address of the first byte
// of memory used to store the object
return static_cast<char*>(addr); // treat that memory as bytes
}
inline void keep_window_open()
{
cin.clear();
cout << "Please enter a character to exit\n";
char ch;
cin >> ch;
return;
}
inline void keep_window_open(string s)
{
if (s == "") return;
cin.clear();
cin.ignore(120, '\n');
for (;;) {
cout << "Please enter " << s << " to exit\n";
string ss;
while (cin >> ss && ss != s)
cout << "Please enter " << s << " to exit\n";
return;
}
}
// error function to be used (only) until error() is introduced in Chapter 5:
inline void simple_error(string s) // write ``error: s and exit program
{
cerr << "error: " << s << '\n';
keep_window_open(); // for some Windows environments
exit(1);
}
// make std::min() and std::max() accessible:
#undef min
#undef max
#include<iomanip>
inline ios_base& general(ios_base& b) // to augment fixed and scientific
{
b.setf(ios_base::fmtflags(0), ios_base::floatfield);
return b;
}
// run-time checked narrowing cast (type conversion):
template<class R, class A> R narrow_cast(const A& a)
{
R r = R(a);
if (A(r) != a) error(string("info loss"));
return r;
}
inline int randint(int max) { return rand() % max; }
inline int randint(int min, int max) { return randint(max - min) + min; }
inline double sqrt(int x) { return sqrt(double(x)); } // to match C++0x
#endif //H112
Below is the Error
./std_lib_facilities.h:43:20: error: no matching function for call to object of
type 'hash<char *>'
return hash<char*>()(s.c_str());
By way of an explanation for the odd-ball file names below, I have a script, chkhdr++, which checks whether a C++ header is compilable standalone, and whether it is idempotent. It creates a 3-line source file such as /tmp/chkhdr-95127.cpp (the number is the process ID) that contains:
#include HEADER /* Check self-containment */
#include HEADER /* Check idempotency */
int main(void){return 0;}
and then compiles it, for example, with the command line:
/usr/bin/g++ -std=c++11 -Wall -Wextra -DHEADER=\"stdlibfacilities.h\" -c \
/tmp/chkhdr-95127.cpp
When I compile the header from the question (named as stdlibfacilities.h) with /usr/bin/g++ (which is the g++ from XCode 6.3, which in turn is really clang++), I get the errors and warnings:
In file included from chkhdr-95127.cpp:1:
In file included from ./stdlibfacilities.h:59:
/Library/Developer/CommandLineTools/usr/bin/../include/c++/v1/ext/hash_map:212:5: warning: Use of
the header <ext/hash_map> is deprecated. Migrate to <unordered_map> [-W#warnings]
# warning Use of the header <ext/hash_map> is deprecated. Migrate to <unordered_map>
^
In file included from chkhdr-95127.cpp:1:
./stdlibfacilities.h:68:20: error: no matching function for call to object of type 'hash<char *>'
return hash<char*>()(s.c_str());
^~~~~~~~~~~~~
/Library/Developer/CommandLineTools/usr/bin/../include/c++/v1/ext/__hash:38:12: note: candidate
function not viable: 1st argument ('const value_type *' (aka 'const char *')) would lose const
qualifier
size_t operator()(char *__c) const _NOEXCEPT
^
1 warning and 1 error generated.
The note about a non-viable candidate function suggests a way around the problem — namely, replace the line:
return hash<char*>()(s.c_str());
with:
return hash<const char*>()(s.c_str());
That compilation gives:
In file included from chkhdr-95148.cpp:1:
In file included from ./stdlibfacilities.h:59:
/Library/Developer/CommandLineTools/usr/bin/../include/c++/v1/ext/hash_map:212:5: warning: Use of
the header <ext/hash_map> is deprecated. Migrate to <unordered_map> [-W#warnings]
# warning Use of the header <ext/hash_map> is deprecated. Migrate to <unordered_map>
^
1 warning generated.
So, there is an easy fix for most of the trouble; add the missing const. However, you should ideally migrate the header so it uses the standard <unordered_map> instead of <ext/hash_map>.
I'm creating a small logging class that allows a printf-like syntax (courtesy boost::format) using template functions to implement variable-length parameter lists. I think I'm close: after instantiating a Log object 'logger', I want to be able to write logger.Print("This %s is a %s", some_obj, another_obj);. The way I currently have it, this produces the error "No member named 'Print' in 'Log'".
Can anyone suggest what I need to change?
Log.h:
#ifndef LOG_H
#define LOG_H
#include <string>
using std::string;
#include <sstream>
#include <ostream>
#include <fstream>
#include <boost/format.hpp>
enum Severity {
DEBUG,
INFO,
WARN,
CRIT,
DIE,
LEVELS // always last; holds # of severity levels
};
class Log {
public:
Log();
Log(const char*, const char*);
void Print_r(int, const boost::format& );
private:
static const char * sev_code[];
// order is important here!
std::ofstream output_file_stream; // this must be initialized ..
std::ostream& output_stream; // .. before this is bound.
};
int LEVEL; // (where does this belong?)
// This unpacks the variadic arguments one at a time recursively
template <typename T, typename... Params>
void Print_r (int severity, boost::format &boost_format, const T &arg, const Params&... parameters) {
Print_r(severity, boost_format % arg, parameters...); // recursively unpack
}
// This checks severity and converts pat to boost::format
template <typename... Params>
void Print (int severity, const string &pat, const Params&... parameters) {
if (severity < LEVEL) return;
boost::format boost_format(pat);
Print_r(severity, boost_format, parameters...);
}
#endif
Log.cpp:
#include "Log.h"
#include <iostream>
using std::cout;
using std::endl;
#include <string>
using std::string;
#include <fstream>
const char * Log::sev_code[] = {
"DBUG",
"INFO",
"WARN",
"CRIT",
"DIE "
};
// Constructor w/no parms = logging to cout
Log::Log() :
output_stream(cout) {
}
// Constructor w/parms = logging to file
Log::Log(const char* dir, const char* file) :
output_stream(output_file_stream) {
string output_file_name = string(dir) + "/" + string(file);
output_file_stream.open(output_file_name.c_str(), std::ofstream::out);
}
// This does the actual logging of the formatted message to the
// output_stream:
void
Log::Print_r (int severity, const boost::format &boost_format) {
std::stringstream s;
s << "[" << sev_code[severity] << "] "
<< boost_format;
output_stream << s << endl;
}
From this code the Print template is outside of the Log class. You need to move it inside the class definition.