Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

how can I guess which OS is running a C/C++ program?

86 views
Skip to first unread message

alexo

unread,
Jan 28, 2017, 8:55:27 AM1/28/17
to
Hi all,
I'd like to write a console program for a text-based game.
(I know it's overdated, but I like the console - it reminds me when I
started using computers). And probably I will be the only one to use it :(

Sometimes when the buffer on screen is too clumsy, thers the need to
clear the screen. I know of the system() function defined in the
<stdlib.h> header file, and I know that in MS-Windows I get what I want
calling system("cls").

I also need the program run under linux, were the system function would
be system("reset"). So my question is: is there a way to know from the
inside of a C/C++ program which OS is running it?

I could write something like:



#ifdef SOME_WINDOWS_VARIABLE
#define CLEARSCR() system("cls")

#ifdef SOME_LINUX_VARIABLE
#define CLEARSCR() system("rset")


and at need call generically CLEARSCR();

Thank you for your replies,
Alex

Paavo Helde

unread,
Jan 28, 2017, 9:19:18 AM1/28/17
to
Why macros? What is wrong with functions?
>
> and at need call generically CLEARSCR();

For console programs there are some portable libraries like ncurses. But
if you just want to clear the screen then this would probably be an
overkill.

In practice, for telling apart Windows and Linux you could study some
environment variables like OS, OSTYPE, WINDIR etc. But do you really
need to distinguish them? Just run both cls and reset and be done.

system("cls 2>/dev/null");
system("reset 2>NUL");

hth
Paavo





alexo

unread,
Jan 28, 2017, 10:56:03 AM1/28/17
to
Hi Paavo,
thank you for your quick reply.

Maybe I was not as clear as I hoped.
What I need to do is to compile my sourcecode under windows and then
compiling take the same sourcecode (without modifying a thing) and under
linux. I'm too new to programming to make a cross-compilation.

The macro serves to generically say to the program: CLEARSCR()
If I'm under Windows it should expand to: system("cls"),
if I'm under linux it should expand to system("reset").

At least this would be my intention.

I'm studying PDcurses - it is portable. As far as I know ncurses is tied
to linux only (but I may be wrong).

Anyway this is not what I want. It is not my intention to build a Text
User Interface; it's just OK the output cout or printf put to the console.

thank you

Paavo Helde

unread,
Jan 28, 2017, 11:20:41 AM1/28/17
to
> Maybe I was not as clear as I hoped.
> What I need to do is to compile my sourcecode under windows and then
> compiling take the same sourcecode (without modifying a thing) and under
> linux. I'm too new to programming to make a cross-compilation.

OK, I see you want to find out this at compile time. My earlier
suggestion was to just issue both commands, with any errors suppressed,
and not bother even to find out which platform you are on, neither at
compile or run time. But I see you insist on doing things "properly",
that's OK too.

There is no standard C++ way to find out the OS at the compile time
(presumably because C++ does not even require an OS to be present), but
in practice there are some predefined preprocessor macros which you can
check, e.g.

#if (defined (_WIN32) || defined (_WIN64))
void ClearScreen() {
system("cls");
}
#elif (defined (LINUX) || defined (__linux__))
void ClearScreen() {
system("reset");
}
#else
#error Unsupported platform.
#endif

>
> The macro serves to generically say to the program: CLEARSCR()
> If I'm under Windows it should expand to: system("cls"),
> if I'm under linux it should expand to system("reset").

Macros are (a sometimes necessary) evil, there is no need to create new
macros here, see the above example.


alexo

unread,
Jan 28, 2017, 11:46:21 AM1/28/17
to
This is right what I wanted to know
so in Windows I can use _WIN32 or _WIN64
and on Linux: LINUX or __linux__

Thnk you. By the way you also teached me to use the #if #elif #else
#error and #endif.

Thank you

Alf P. Steinbach

unread,
Jan 28, 2017, 3:24:32 PM1/28/17
to
On 28.01.2017 15:19, Paavo Helde wrote:
> reset 2>NUL

Won't that create a file `NUL` in Unix-land?

Cheers!,

- Alf

Alf P. Steinbach

unread,
Jan 28, 2017, 3:27:24 PM1/28/17
to
On 28.01.2017 17:46, alexo wrote:
>>
>> #if (defined (_WIN32) || defined (_WIN64))

`_WIN32` is defined in both 32-bit and 64-bit Windows.

There is no need to check explicitly for `_WIN64`.


>> void ClearScreen() {
>> system("cls");
>> }
>> #elif (defined (LINUX) || defined (__linux__))

I would just not check this at all. Or else a far more elaborate check.
The above check is either too much or too little, IMHO.


>> void ClearScreen() {
>> system("reset");
>> }
>> #else
>> #error Unsupported platform.
>> #endif

[snip]


Cheers!,

- Alf


Christiano

unread,
Jan 28, 2017, 3:40:41 PM1/28/17
to
I saw that your question was answered but I would like to add one thing.
You can clear the screen by using only c ++ cout because of the shell
properties.

Test this code:

#include <iostream>
#include <string>
using namespace std;

int main()
{
cout << "\033[2J" << endl; // clear screen
cout << "\033[0;0f" << endl; //puts the cursor at line 0, columm 0

string text = "Hello, world...\n";

for(int i=0;i<text.size();i++)
{
// text with colors
cout << "\033[0;"<< (31+i%7) <<"m" << text[i] ;
}

char c;
cout << "\033[10;30f:)...";
cin >> c;


return 0;
}

Reference:
http://www.tldp.org/HOWTO/Bash-Prompt-HOWTO/c327.html

Does It work to Windows?

No when I had used it, however apparently this situation has changed with
windows 10:
http://www.nivot.org/blog/post/2016/02/04/Windows-10-TH2-%28v1511%29-
Console-Host-Enhancements

Richard

unread,
Jan 28, 2017, 6:10:22 PM1/28/17
to
[Please do not mail me a copy of your followup]

Christiano <chris...@engineer.com> spake the secret code
<588d01b8$0$10708$c3e8da3$5d8f...@news.astraweb.com> thusly:

>Test this code:
>
>#include <iostream>
>#include <string>
>using namespace std;
>
>int main()
>{
> cout << "\033[2J" << endl; // clear screen
> cout << "\033[0;0f" << endl; //puts the cursor at line 0, columm 0
>
> string text = "Hello, world...\n";
>
> for(int i=0;i<text.size();i++)
> {
> // text with colors
> cout << "\033[0;"<< (31+i%7) <<"m" << text[i] ;
> }
>
> char c;
> cout << "\033[10;30f:)...";
> cin >> c;
>
>
> return 0;
>}

In this code, the assumption is that ANSI escape sequences are
supported by the environment. This is almost always the case when
using modern equipment, but if you're going retro with a console
oriented game, then you might want to support a retro terminal over
the serial port (easy to setup in unix). In that case, you'll want to
use curses as it abstracts the operation of "clear screen" into
whatever ESC sequences are needed for the terminal in use.
--
"The Direct3D Graphics Pipeline" free book <http://tinyurl.com/d3d-pipeline>
The Terminals Wiki <http://terminals-wiki.org>
The Computer Graphics Museum <http://computergraphicsmuseum.org>
Legalize Adulthood! (my blog) <http://legalizeadulthood.wordpress.com>

alexo

unread,
Jan 29, 2017, 7:02:58 AM1/29/17
to
Il 28/01/2017 21:40, Christiano ha scritto:

> Test this code:
>
> #include <iostream>
> #include <string>
> using namespace std;
>
> int main()
> {
> cout << "\033[2J" << endl; // clear screen
> cout << "\033[0;0f" << endl; //puts the cursor at line 0, columm 0
>
> string text = "Hello, world...\n";
>
> for(int i=0;i<text.size();i++)
> {
> // text with colors
> cout << "\033[0;"<< (31+i%7) <<"m" << text[i] ;
> }
>
> char c;
> cout << "\033[10;30f:)...";
> cin >> c;
>
>
> return 0;
> }
>
> Reference:
> http://www.tldp.org/HOWTO/Bash-Prompt-HOWTO/c327.html

Too many "magic" numbers.
Thank you anyway,

this is the output compiled with Code::Block 16.01 - MingW compiler
under MS-Windows:

[2J
[0;0f
[0;31mH [0;32me [0;33ml [0;34ml [0;35mo [0;36m, [0;37m
[0;31mw [0;32mo [0;33mr [0;34ml [0;35md [0;36m. [0;37m. [0;31m. [0;32m
[10;30f:)...

Microsoft Visual Studio 17 RC doesn't evn compile it.


Richard

unread,
Jan 30, 2017, 1:23:50 PM1/30/17
to
[Please do not mail me a copy of your followup]

alexo <alessandr...@libero.it> spake the secret code
<o6klkt$1dcu$1...@gioia.aioe.org> thusly:

>Too many "magic" numbers.

He is using ANSI escape sequences, which are well documented.

<https://en.wikipedia.org/wiki/ANSI_escape_code>

alexo

unread,
Feb 4, 2017, 6:14:39 AM2/4/17
to
>> Too many "magic" numbers.
>
> He is using ANSI escape sequences, which are well documented.
>
> <https://en.wikipedia.org/wiki/ANSI_escape_code>

I have tried that code in MinGW, code::blocks IDe's integrated console
and Visual studio 2017 RC as I have already said.

The latter doesn't even compile, the others just output garbage.
Even if is an ANSI codification - and a standardised feature - it seems
not to be universally supported...and too tricky.

The solution that Pavlo gave me was exactly what I expected and
requested for.

I know I can rely on your answers.
Thank you.



Richard

unread,
Feb 4, 2017, 5:43:32 PM2/4/17
to
[Please do not mail me a copy of your followup]

alexo <alessandr...@libero.it> spake the secret code
<o74d2m$1p9u$1...@gioia.aioe.org> thusly:

>>> Too many "magic" numbers.
>>
>> He is using ANSI escape sequences, which are well documented.
>>
>> <https://en.wikipedia.org/wiki/ANSI_escape_code>
>
>I have tried that code in MinGW, code::blocks IDe's integrated console
>and Visual studio 2017 RC as I have already said.
>
>The latter doesn't even compile, the others just output garbage.

This is the second time you've said that this very standard code
doesn't compile. What exactly is the compile error?

By "output garbage", I assume you are referring to the output of the
program and not the output of the compilation process.

The Windows command processor CMD.EXE doesn't guarantee to support
ANSI escape sequences. In DOS, there was a driver loaded to support
them -- ANSI.SYS -- because DOS was more like a terminal environment.
You can get a program for Windows to interpret the sequences like
ANSI.SYS -- one such program is ANSICON:
<http://adoxa.altervista.org/ansicon/>

>Even if is an ANSI codification - and a standardised feature - it seems
>not to be universally supported...and too tricky.

There are several choices here. You can code something that is
portable across operating systems or you can code something specific
to Windows. The most portable solution is to use the curses library
and have it output the appropriate escape codes for the environment.
To code directly to Windows you can use one of the two approaches
shown here:
<https://msdn.microsoft.com/en-us/library/windows/desktop/ms682022(v=vs.85).aspx>

alexo

unread,
Feb 5, 2017, 5:29:12 AM2/5/17
to
Il 04/02/2017 23:43, Richard ha scritto:

> By "output garbage", I assume you are referring to the output of the
> program and not the output of the compilation process.

You guessed it ;) sorry I was not clear.

Compilation with minGW is ok, no warnings.
I've re-compiled your code in Visual studio and it compiles perfectly.
I don't know what went wrong that time.

But, as already reported earlier, this is what I get when running your code:

[2J
[0;0f
[0;31mH [0;32me [0;33ml [0;34ml [0;35mo [0;36m, [0;37m
[0;31mw [0;32mo [0;33mr [0;34ml [0;35md [0;36m. [0;37m. [0;31m. [0;32m
[10;30f:)...

> The Windows command processor CMD.EXE doesn't guarantee to support
> ANSI escape sequences.

OK, nor even Window 10's CMD supports it as I can see.

> There are several choices here. You can code something that is
> portable across operating systems or you can code something specific
> to Windows.

The solution using the macros _WIN32 or __linux__ worked fine.
I've tested the code on both the OSes and calling the system() routine
worked perfectly.

The most portable solution is to use the curses library
> and have it output the appropriate escape codes for the environment.

PDcurses is what I'm studying, but I don't have the necessity to manage
the console screen as individual cells. It's just fine the normal cout.
I just needed a way to clear the screen's buffer.

The game I'm trying to write is a text-driven old-style RPG. It needs a
lot of paper to sketch the corridor passages and to annote the eventual
content of a room. But this project is just a hobby, that I write from
time to time not even frequently. Probably will be never finished.

> To code directly to Windows you can use one of the two approaches
> shown here:
> <https://msdn.microsoft.com/en-us/library/windows/desktop/ms682022(v=vs.85).aspx>

The second solution require to include the <windows.h> header. I don't
know anything about it, sorry. The first olution is the simpler and
clearer and will be that I will use.
Programming is an "art"
...and art is beauty.

So the principle I conform is KISS: "keep it simple, stuid" or "keep it
short, simple".

Regards,
Alex


Alf P. Steinbach

unread,
Feb 5, 2017, 6:08:42 AM2/5/17
to
On 05.02.2017 11:29, alexo wrote:
> Il 04/02/2017 23:43, Richard ha scritto:
>
>> The Windows command processor CMD.EXE doesn't guarantee to support
>> ANSI escape sequences.
>
> OK, nor even Window 10's CMD supports it as I can see.

Windows 10's console windows support ANSI escape sequences via the
ordinary standard streams, but not via direct console i/o.

However, since it's a new feature as of Windows 10, expect some
imperfections.

Cheers & hth.,

- Alf

alexo

unread,
Feb 5, 2017, 8:02:50 AM2/5/17
to
Il 05/02/2017 12:07, Alf P. Steinbach ha scritto:
> On 05.02.2017 11:29, alexo wrote:
>> Il 04/02/2017 23:43, Richard ha scritto:
>>
>>> The Windows command processor CMD.EXE doesn't guarantee to support
>>> ANSI escape sequences.
>>
>> OK, nor even Window 10's CMD supports it as I can see.
>
> Windows 10's console windows support ANSI escape sequences via the
> ordinary standard streams, but not via direct console i/o.

can you explain it with a simple example?
sorry but I'm not that geek as you think of me ; )

thanks,


alf.p.s...@gmail.com

unread,
Feb 5, 2017, 8:20:51 AM2/5/17
to
In a cmd.exe instance, type "echo " followed by Alt+027 on the numeric keypad, followed by "[2J".

The Alt+027 is echoed as "^[" but is internally the ASCII escape character:

[example]
[C:\my\drive_h\forums\clc++\001]
> echo ^[[2J
[/example]

Now when you hit return the specified text is output by the echo command, causing the screen to be cleared. The cursor maintains its position so it's not exactly the same as the cls command. But shows that escape sequences work.

When you try that directly in a C++ program you get silly translated (interpreted) characters instead of a clear screen. That's because with both recent g++ and recent Visual C++ -- I don't know how it was before -- the newgfangled escape sequence support is disabled by default.

To enable it you can call the Windows API SetConsoleMode function:

[code]
#include <windows.h>
// Documentation of Windows support for ANSI escape sequences:
// https://msdn.microsoft.com/en-us/library/windows/desktop/mt638032(v=vs.85).aspx

#include <windows.h>
namespace winapi {
HANDLE const out = GetStdHandle( STD_OUTPUT_HANDLE );

void enable_ansi_sequences()
{
DWORD old_mode;
GetConsoleMode( winapi::out, &old_mode );
SetConsoleMode(
winapi::out,
old_mode | 4 // ENABLE_VIRTUAL_TERMINAL_PROCESSING
);
}
}

#include <iostream>
using namespace std;
int main()
{
winapi::enable_ansi_sequences();
cout << "\x1B[2J"; // Clear the screen.
// cout << "\x1B[H"; // And send cursor hoome (up left).
}
[/code]

You can place that Windows-specific stuff, plus the call to it, in a separate compilation unit, then the main code can be the same for Windows and Unix-land.

As long as only the common subset of escape sequences is used. :)

alexo

unread,
Feb 5, 2017, 11:24:11 AM2/5/17
to
Il 05/02/2017 14:20, alf.p.s...@gmail.com ha scritto:
> On Sunday, February 5, 2017 at 2:02:50 PM UTC+1, alexo wrote:
>> Il 05/02/2017 12:07, Alf P. Steinbach ha scritto:
>>> On 05.02.2017 11:29, alexo wrote:
>>>> Il 04/02/2017 23:43, Richard ha scritto:
>>>>
>>>>> The Windows command processor CMD.EXE doesn't guarantee to support
>>>>> ANSI escape sequences.
>>>>
>>>> OK, nor even Window 10's CMD supports it as I can see.
>>>
>>> Windows 10's console windows support ANSI escape sequences via the
>>> ordinary standard streams, but not via direct console i/o.
>>
>> can you explain it with a simple example?
>> sorry but I'm not that geek as you think of me ; )
>
> In a cmd.exe instance, type "echo " followed by Alt+027 on the numeric keypad, followed by "[2J".
>
> The Alt+027 is echoed as "^[" but is internally the ASCII escape character:
>
> [example]
> [C:\my\drive_h\forums\clc++\001]
>> echo ^[[2J
> [/example]
>
> Now when you hit return the specified text is output by the echo command, causing the screen to be cleared. The cursor maintains its position so it's not exactly the same as the cls command. But shows that escape sequences work.
>
> When you try that directly in a C++ program you get silly translated (interpreted) characters instead of a clear screen. That's because with both recent g++ and recent Visual C++ -- I don't know how it was before -- the newgfangled escape sequence support is disabled by default.

tested. OK.

> To enable it you can call the Windows API SetConsoleMode function:
>
> [code]
> #include <windows.h>
> // Documentation of Windows support for ANSI escape sequences:
> // https://msdn.microsoft.com/en-us/library/windows/desktop/mt638032(v=vs.85).aspx
>
> #include <windows.h>
> namespace winapi {
> HANDLE const out = GetStdHandle( STD_OUTPUT_HANDLE );
>
> void enable_ansi_sequences()
> {
> DWORD old_mode;
> GetConsoleMode( winapi::out, &old_mode );
> SetConsoleMode(
> winapi::out,
> old_mode | 4 // ENABLE_VIRTUAL_TERMINAL_PROCESSING
> );
> }
> }
>
> #include <iostream>
> using namespace std;
> int main()
> {
> winapi::enable_ansi_sequences();
> cout << "\x1B[2J"; // Clear the screen.
> // cout << "\x1B[H"; // And send cursor hoome (up left).
> }
> [/code]

not tested yet. But I find it terribly ugly. It's simpler to have a
single call to system() that in windows calls "cls" and on linux calls
"reset".
What is coming out from this conversation is a "new world" of concepts.
I don't want study it, but thank you to have me shown this possibility.
Computers are woderful.

thank you

Richard

unread,
Feb 5, 2017, 1:54:36 PM2/5/17
to
[Please do not mail me a copy of your followup]

You didn't answer my question about the compile error.

That's the only interesting part of this thread to me.

alexo

unread,
Feb 6, 2017, 11:34:14 AM2/6/17
to
Il 05/02/2017 19:54, Richard ha scritto:
> [Please do not mail me a copy of your followup]
>
> You didn't answer my question about the compile error.
>
> That's the only interesting part of this thread to me.
>
Hi, Richard.
I have recompiled your code on Visual Studio and all went well. No
errors or warnings.
I don't know what I did wrong last time. But obviously was a fault of mine.
Forget this issue. Sorry
but thank you for your precious words.

Cheers


J. Clarke

unread,
Feb 12, 2017, 10:14:28 PM2/12/17
to
In article <o6klkt$1dcu$1...@gioia.aioe.org>, alessandr...@libero.it says... > Il 28/01/2017 21:40, Christiano ha scritto: > > Test this code: > > #include <iostream> > > #include <string> > > using namespace std; > > int main() > > { > > cout << "\033[2J" << endl; // clear screen > > cout << "\033[0;0f" << endl; //puts the cursor at line 0, columm 0 > > string text = "Hello, world...\n"; > > for(int i=0;i<text.size();i++) > > > > // text with colors > > cout << "\033[0;"<< (31+i%7) <<"m" << text[i] ; > > > > char c; > > cout << "\033[10;30f:)..."; > > cin >> c; > > return 0; > > } > > Reference: > > http://www.tldp.org/HOWTO/Bash-Prompt-HOWTO/c327.html > Too many "magic" numbers. > Thank you anyway, > this is the output compiled with Code::Block 16.01 - MingW compiler > under MS-Windows: [0;0f [0;31mH [0;32me [0;33ml [0;34ml [0;35mo [0;36m, [0;37m [0;31mw [0;32mo [0;33mr [0;34ml [0;35md [0;36m. [0;37m. [0;31m. [0;32m [10;30f:)... > Microsoft Visual Studio 17 RC doesn't evn compile it. What happens when you try to compile it? It compiled fine under 2015 for me.
0 new messages