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.

+2


a source to share


4 answers


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

      

+4


a source


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?

+2


a source


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.

0


a source


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.

0


a source







All Articles