C ++: define a simple constant to use?
In C ++, I wanted to define a constant that I can use in another function. A short answer on how to do this would be ok.
Let's say at the beginning of my code, I want to define this constant:
//After #includes
bool OS = 1; //1 = linux
if (OS) {
const ??? = "clear";
} else {
const ??? = "cls";
}
I don't know which type to use to define a "clean" string ... I'm so confused.
Later I want to use it inside a function:
int foo() {
system(::cls); //:: for global
return 0;
}
How can I define the line above and use the line below? I heard that char only had one character and that's it ... I'm not sure how to use as it says it will convert a string to const char or something.
a source to share
char*
not really char
. char*
is basically a string (these are the strings that were before C ++ appeared).
To illustrate:
int array[N]; // An array of N ints.
char str[N]; // An array of N chars, which is also (loosely) called a string.
char[]
degrades to char*
, which is why you often see functions accept char*
.
To convert std::string
to const char*
, you can simply call:
std::string s;
s.c_str()
In this case, a preprocessor is usually used to identify your OS. So you can use the compiler to generate platform-specific stuff:
#ifdef OS_LINUX
const char cls[] = "clear";
#elif OS_WIN
const char cls[] = "cls";
#endif
One thing you can consider makes it a function. This avoids the nasty dependencies of the global build order .
string GetClearCommand() {
if (OS == "LINUX") {
return "clear";
} else if (OS == "WIN") {
return "cls";
}
FAIL("No OS specified?");
return "";
}
It looks like you are trying to do this:
#include <iostream>
using namespace std;
#ifdef LINUX
const char cls[] = "LINUX_CLEAR";
#elif WIN
const char cls[] = "WIN_CLEAR";
#else
const char cls[] = "OTHER_CLEAR";
#endif
void fake_system(const char* arg) {
std::cout << "fake_system: " << arg << std::endl;
}
int main(int argc, char** argv) {
fake_system(cls);
return 0;
}
// Then build the program passing your OS parameter.
$ g++ -DLINUX clear.cc -o clear
$ ./clear
fake_system: LINUX_CLEAR
a source to share
Here's the problem, you are suffering out of scope with variables. If I declare something in parentheses, it only exists in parentheses.
if( foo ){
const char* blah = "blah";
}
As soon as we leave the operator if
, the variable blah
will disappear. You will need to instantiate it non-locally in whatever parentheses you write. Consequently:
void Bar(){
const char* blah = "blah";
if( foo ){
//blah exists within here
}
}
However, blah
it will not exist outside Bar
. Get it?
a source to share
Another option is to create a class with a bunch of static methods. Create a new method for each command. Sort of:
// in sys-commands.h
class SystemCommands {
public:
static char const* clear();
static char const* remove();
};
This gives you some good options to implement. The best part is to have a separate implementation file for each platform you choose at compile time.
// in sys-commands-win32.cpp
#include "sys-commands.h"
char const* SystemCommands::clear() { return "cls"; }
char const* SystemCommands::remove() { return "erase /f/q"; }
// in sys-commands-macosx.cpp
#include "sys-commands.h"
char const* SystemCommands::clear() { return "/usr/bin/clear"; }
char const* SystemCommands::remove() { return "/bin/rm -fr"; }
The compiled file will determine which set of commands will be used. The application code will look like this:
#include <cstdlib>
#include "sys-commands.h"
int main() {
std::system(SystemCommands::clear());
return 0;
}
Edit: I forgot to mention that I prefer static functions over global constants for a variety of reasons. If nothing else, you can make them non-persistent without changing their types - in other words, if you ever need to select a set of commands based on your runtime settings, the user code should not change or even be aware that such a change has occurred.
a source to share
You can use a common header file and link to different modules depending on the system:
// systemconstants.hpp
#ifndef SYSTEM_CONSTANTS_HPP_INCLUDED
#define SYSTEM_CONSTANTS_HPP_INCLUDED
namespace constants {
extern const char cls[]; // declaration of cls with incomplete type
}
#endif
In case of Linux, just compile and connect to this:
// linux/systemconstants.cpp
#include "systemconstants.hpp"
namespace constants {
extern const char cls[] = "clear";
}
In case of Windows, just compile and connect to this:
// windows/systemconstants.cpp
#include "systemconstants.hpp"
namespace constants {
extern const char cls[] = "cls";
}
System translation units can be placed in specific subdirectories (linux /, windows /, etc.) from which one could be automatically selected during the build process. This extends to many other things, not just string constants.
a source to share