The program must know what operating system its running under because it has to be recompiled for each os. Add some sort of preprocessor directive that tells the program what os its being compiled for. For example, you might put the define _WIN32 in the makefile when compiled for MS-Windows and _UNIX in another make file when being compiled for *nix os. Inside the program you can use that macro to determine which operating system its being compiled for.
#ifdef _WIN32
// do something for MS-Windows
#elif defined(_UNIX)
// beging compiled for *nix
#edndif
Ancient Dragon
Retired & Loving It
30,042 posts since Aug 2005
Reputation Points: 5,662
Solved Threads: 2,341
The best way to do this would be know what OS your program will be working on. I think if you put the Windows call in a function and set it to return a bool true if successful and false if not (using an if statement) then you would be able to determine if you should call the other function.
\
Not really. If the program is being compiled for *nix then the MS-Windows win32 api functions are not even available to the program, so it is impossible for the program to call it.
Ancient Dragon
Retired & Loving It
30,042 posts since Aug 2005
Reputation Points: 5,662
Solved Threads: 2,341
That will work providing you create the makefiles for each os as I described previously.
Ancient Dragon
Retired & Loving It
30,042 posts since Aug 2005
Reputation Points: 5,662
Solved Threads: 2,341
The exact macro to test for depends on OS and compiler. Here is a handy reference for Pre-defined C/C++ Compiler Macros .
Unless you have been careful to predefine specific macros in your makefiles as AD instructed, you should test for all the possible macros that you might expect. On Windows, I usually have something like
#if defined(__WIN32__) || defined(__WIN32) || defined(_WIN32) || defined(WIN32)
#define __WIN32__
#endif
...
#ifdef __WIN32__
// windows stuff here
#elif defined( ... )
// other stuff here
#else
// generic stuff here
#endif
Hope this helps.
Duoas
Postaholic
2,043 posts since Oct 2007
Reputation Points: 1,140
Solved Threads: 229
I think we have an impressive example of a false problem.
If you want to clear console window in portable manner, use portable direct console i/o library (pdcurses, for example, or others). That's the only right answer. May be a suitable ersatz of such libraries is stuff implemented with minimal variations in most of C and C++ programming systems. If you need to use standard console i/o (stdio.h or iostream), never use clear screen operation in your program interface design: no such entity as a screen in C and C++ stream i/o models.
As usually you can't run executable module on different OS in native mode, so the question "is there some way to find which OS is being used at the moment of execution so the program can decide..." is a senseless sentence. The obvious answer is "your program compiled and linked for OS1 can't run on OS2 so it find nothing on OS2, moreover it can't find itself on OS2".
It's the other question: "How to write portable sources which can select proper pieces of codes for different OS by C++ conditional compilation features?". Download good portable library (or system) and look at its configuration header. Of course, it looks like Ancient Dragon's example. But it's the other story and it's not so simple in common case.
ArkM
Postaholic
2,001 posts since Jul 2008
Reputation Points: 1,234
Solved Threads: 348
If this is just some homework problem, you could try one, then the other. Only one will work:
if (system( "clear" )) system( "cls" );
However, likeArkM said, better to do it the Right Way.
Duoas
Postaholic
2,043 posts since Oct 2007
Reputation Points: 1,140
Solved Threads: 229
what do you mean by "create the makefiles for each os"? sorry, I'm a bit of a noob :/
I did:
#include <iostream>
using std::cout;
using std::cin;
using std::endl;
void clearScreen()
{
#ifdef _WIN32
system("cls");
#elif defined(_UNIX)
system("clear");
#endif
}
int main()
{
cout << "coco" << endl;
cin.get();
clearScreen();
cout << "coco2" << endl;
}
and the result:
omc@linus-marx:~$ /home/omc/workspace/LigaSagres/Debug/LigaSagres
coco
coco2
omc@linus-marx:~$
so it didn't work. I guess maybe because I have not created "the makefiles for each os"
What do you mean by "it didn't work" ? I don't know what that stuff is that you posted.
"makefile for each os" means that you have to compile your program in each os -- once under *nix and again under MS-Windows. You can't compile once and run on both operating systems -- that won't work.
If you use g++ compiler then you can probably have one source file and use the same compiler on both os. You will need a version of g++ for unix and another version of g++ for MS-Windows.
Ancient Dragon
Retired & Loving It
30,042 posts since Aug 2005
Reputation Points: 5,662
Solved Threads: 2,341
Sigh. You know, you really shouldn't be dinking with the screen at all. But if all you want is something to clear the screen in Win32 and POSIX, here are a couple of functions. Your teacher will know you didn't write them yourself!
// clearscreen.cpp
#include <iostream>
#include <string>
#if defined(__WIN32__) || defined(__WIN32) || defined(_WIN32) || defined(WIN32) || defined(__TOS_WIN__) || defined(__WINDOWS__)
#ifndef __WIN32__
#define __WIN32__
#endif
#include <windows.h>
#else
#include <unistd.h>
#ifdef _POSIX_VERSION
#ifndef __UNIX__
#define __UNIX__
#endif
#include <term.h>
#endif
#endif
#if !defined(__WIN32__) && !defined(__UNIX__)
#warning Works best on a Windows or POSIX platform.
#endif
void clearscreen()
{
#if defined(__WIN32__)
HANDLE hStdOut;
CONSOLE_SCREEN_BUFFER_INFO csbi;
DWORD count;
DWORD cellCount;
COORD homeCoords = { 0, 0 };
hStdOut = GetStdHandle( STD_OUTPUT_HANDLE );
if (hStdOut == INVALID_HANDLE_VALUE) return;
/* Get the number of cells in the current buffer */
if (!GetConsoleScreenBufferInfo( hStdOut, &csbi )) return;
cellCount = csbi.dwSize.X *csbi.dwSize.Y;
/* Fill the entire buffer with spaces */
if (!FillConsoleOutputCharacter(
hStdOut,
(TCHAR) ' ',
cellCount,
homeCoords,
&count
)) return;
/* Fill the entire buffer with the current colors and attributes */
if (!FillConsoleOutputAttribute(
hStdOut,
csbi.wAttributes,
cellCount,
homeCoords,
&count
)) return;
/* Move the cursor home */
SetConsoleCursorPosition( hStdOut, homeCoords );
#elif defined(__UNIX__)
static char* console_clearscreen = 0;
if (!console_clearscreen)
{
int result;
setupterm( NULL, STDOUT_FILENO, &result );
if (result > 0)
console_clearscreen = tigetstr( "clear" );
}
if (console_clearscreen)
putp( console_clearscreen );
#else
std::cout << std::string( 100, '\n' );
#endif
}
// end clearscreen.cpp
// clearscreen.hpp
#ifndef CLEARSCREEN_HPP
#define CLEARSCREEN_HPP
void clearscreen();
#endif
// end clearscreen.hpp
Enjoy.
Duoas
Postaholic
2,043 posts since Oct 2007
Reputation Points: 1,140
Solved Threads: 229
I think Duodas have posted a good example of multilevel environment recognition with subsequent macros standartisation (#define __WIN32__, for example). More complicated example from the Boost library:
http://www.boost.org/doc/libs/1_36_0/boost/config/select_platform_config.hpp
The key point is: don't dissipate OS/compiler dependencies over all your codes. Incapsulate all this stuff in the only .h header file. Declare your own portable functions (and data structures) in this file. For example, suppose its name is omgconio.h:
#ifndef OMGCONIO_H
#define OMGCONIO_H
...
/** Explain ClrScr functionality */
void ClrScr();
int Peek();
bool KbHit();
int GetCh();
...
#endif
Use only these functions calls in your source(s).
Create omgconio.cpp file with these functions inplementation. Place all OS/compiler selecting conditional compilation directives in this file only. Add omgconio.h and omgconio.cpp files to your projects.
Now you know where is OS/compiler dependency incapsulated if you will be ready to expand or correct your platform independent direct console i/o support.
ArkM
Postaholic
2,001 posts since Jul 2008
Reputation Points: 1,234
Solved Threads: 348