I would like to write a function :
inline char separator()
{
/* SOMETHING */
}
that returns the file separator of the system in standar
I'm not sure how to do it other than by checking ifdefs
inline char separator()
{
#ifdef _WIN32
return '\\';
#else
return '/';
#endif
}
or (as suggested by PaperBirdMaster)
const char kPathSeparator =
#ifdef _WIN32
'\\';
#else
'/';
#endif
that can be something like this
#if defined(WIN32) || defined(_WIN32)
#define PATH_SEPARATOR "\\"
#else
#define PATH_SEPARATOR "/"
#endif
std::filesystem::path::preferred_separator should now be used as a clean C++17
library function how it seems.
If your compiler already offers c++17 capabilities, then you can use std::experimental::filesystem::path::preferred_separator
which should return either /
or \
depending on your platform.
See this for more information.
I'm surprised no one has offered the following. This builds a bit on what others are offering here.
Although In this example I'm trying to dynamically grab the name of the executable being run for usage, it wouldn't be too hard to make the jump and reapply this however you need.
Windows uses forward slash to denote arguments. So you could check for that first in the first argument argv[0]
, which contains the name of the program being run.
Note the following results in stripping the pathname previous of the last slash, leaving sepd
as the filename of the program.
#include <string.h>
#include <stdio.h>
int main(int argc, char *argv[]){
//int a = 1
//int this = (a == 1) ? 20 : 30; //ternary operator
//is a==1 ? If yes then 'this' = 20, or else 'this' = 30
char *sepd = (strrchr(argv[0], '\/') != NULL) ?
strrchr(argv[0], '\/') :
strrchr(argv[0], '\\');
printf("%s\n\n", sepd);
printf("usage: .%s <host> \n\n", sepd);
while (getchar() != '\n');
}
But in all reality, this is pretty dirty and with Windows' most recent move to include Bash (not yet implemented at this time), this may produce unexpected or unanticipated results.
It's also not as sane and impervious to errors as what others have offered, particularly #ifdef _WIN32
.
This question is really hinting at a much nastier problem.
If you simply care about UNIX vs. Winodws and you only care about directories and files, then what you've already seen will (mostly) work, but the more generic issue of splicing a path name into its components is a much uglier problem. Depending on the platform, a path may include one or more of:
While there are 3rd party libraries (like various CPAN Perl modules, Boost, and others) for this, and every OS includes system functions for this, there's nothing built-in to C for this and the C++ standard only gained this functionality (by incorporating the Boost module) in 2017.
Some examples of what such a function may need to deal with are:
There are many others as well.
It is worth noting that the C++17 filesystem library does not cover all of these possibilities. The std::filesystem::path
consists of an optional root-name (a volume identifier), an optional root-directory (to identify absolute paths), and a sequence of filenames separated by directory separators. This covers everything likely to be valid on UNIX platforms and the majority of use-cases for other platforms, but is not comprehensive. For example, it does not have any support for sub-streams (relying on the OS to somehow map them onto a file name - which is done by Mac OS X, but not classic MacOS). It also does not include support for file version numbers.
See also Wikipedia's entry on Path and the C++17 std::filesystem::path class
http://en.cppreference.com/w/cpp/filesystem
I recommend you look at what you want to do with the directory separator (extract the base-name, break a path into a list of directories, etc.) and write a function to do that. If you're using C++17 (and you are certain your code won't be compiled by a pre-17 C++ compiler) then you can (probably) use standard C++ library code to write a portable implementation of this function. If not, that function will need to use platform-specific #ifdef
s for each platform you will be supporting, using a #error
if none of the conditions are met, to force you to to add conditions for unexpected platforms.
Or use a 3rd party library (like Boost) that includes functions for all of this, if that is acceptable.