3

I've read that the std::cin thing in C++ (I'm paraphrasing here) "takes input from the standard input stream, which is usually the keyboard".

How does one change it to allow some other device to provide input? I've no idea what purpose I'd use this for, but I'm curious how one could do this nonetheless.

(I'm sure the answer is out there somewhere, but after searching for a while, I haven't found it; if you know of a great resource that would answer my question, I'd be very grateful if you could let me know what it is.)

UPDATE: Unless what I'm asking is not possible in normal C++, this is not a duplicate question. I'm not looking to redirect stdin/stdout to a file; I want to know if it's possible to redirect it to some other device like a mouse or a game controller.

Michael Gaskill
  • 7,913
  • 10
  • 38
  • 43
Ben Sandeen
  • 1,403
  • 3
  • 14
  • 17
  • 3
    Have a look at [here](http://stackoverflow.com/questions/10150468/how-to-redirect-cin-and-cout-to-files). Should be what you're after... – Aconcagua Jun 27 '16 at 21:22
  • 3
    The way that you read from other input devices is device-specific. You'd have to use the APIs on the platform (operating system) that you're using, and they're different on each platform. If you're really curious, you can google search for "C++ mouse input" or "C++ joystick input" (and even "C++ keyboard input" for low-level keyboard handling) to find the details that you're looking for. Add "Windows", "Linux", or "Mac" to the search to find results for your specific platform. Note that Linux (and other Unix-like systems) can support X11, KDE, or Gnome GUIs, so those are different, too. – Michael Gaskill Jun 28 '16 at 02:36
  • @PaulR: Could you please remove the "marked as duplicate" thing, because it's not a duplicate, as I edited my question to explain – Ben Sandeen Jun 28 '16 at 07:01
  • And thanks for the answer, @MichaelGaskill. If you put that as an answer, I'll accept it! :D – Ben Sandeen Jun 28 '16 at 07:02
  • @BenSandeen: OK - question re-opened. You should really specify though how input from a non-character device such as a mouse or game controller should be treated as a character stream, as it's not obvious at all how or why you would want to do this. Otherwise the question is likely to be closed again, as "unclear what you're asking". – Paul R Jun 28 '16 at 07:04
  • 2
    This is not within the scope of the C++ standard. The way you redirect standard in/out/err is system dependent (and also the nature of standard in/out/err - the reason they say usually keyboard is that on most systems standard in comes from the keyboard, but the C++ standard does not require that). – skyking Jun 28 '16 at 07:11
  • 1
    On *nix, you can redirect device files to stdin, e.g. `./program < /dev/random`. If you have a device that creates a stream, this may be a possibility. – Karsten Koop Jun 28 '16 at 07:20
  • 2
    You can redirect to a file. You cannot redirect to something that is not a file. Either way you cannot redirect from your program using standard C++. If your OS exposes your mouse or your game controller as a file (normally Unix-like OSes do that), then yes, you can redirect the standard input (when invoking your program from a shell, not from within the program) to use these devices. If not, then no, there's no way to do such redirection. You have to use OS-specific and device-specific APIs which usually have nothing to do with std::stream. – n. m. could be an AI Jun 28 '16 at 08:04

2 Answers2

2

The way that you read from other input devices is device-specific. You'd have to use the APIs on the platform that you're using; the APIs are different on each platform.

If you're really curious, you can google search for "C++ mouse input" or "C++ joystick input" (and even "C++ keyboard input" for low-level keyboard handling) to find the details that you're looking for. Add "Windows", "Linux", or "Mac" to the search to find results for your specific platform.

Note that you can find some excellent low-level device control, suitable for game development, on the Stack Exchange Game Development site.

Windows APIs

On Windows, the low-level device inputs require that you use the Windows event-handling system and handling the specific events that your app needs. Microsoft documents the low-level APIs on the Windows Dev Center.

The specific APIs are:

Mac OS X

Handling low-level input events on the Mac is different than on Windows, and the documentation on the Mac Developer Library is often presented in Objective C, rather than C++. It's useful to note that on Mac OS X, XCode will allow you to write hybrid C++/Objective C code called Objective C++, so you can easily leverage your C++ experience.

The individual APIs are:

Linux/*nix

Linux (and other Unix-like systems) can support X11, KDE, or Gnome GUIs, so those each have their own APIs. I won't enumerate them here, but you can easily locate the appropriate APIs for your purpose, if you want to develop for Linux, FreeBSD, OpenBSD, or any of the other Unix variants.

Abstraction Libraries / Frameworks

There are a number of libraries (C) and frameworks (C++) that provide cross-platform interfaces for low-level input and output. Some are very well done and widely supported, and often have game engines built on them.

Some very common and well supported libraries are:

There are also portable frameworks, typically used for developing more traditional applications, and these also provide abstractions for handling user input:

If you dig around just a bit, you can find many, many more portable libraries and frameworks. Not only will they generally make it easier to develop complex logic, you'll also have a significant advantage getting your code to build and run on another platform, entirely.

Community
  • 1
  • 1
Michael Gaskill
  • 7,913
  • 10
  • 38
  • 43
  • The sentence "The way that you read from other input devices is device-specific" seems to be incorrect because it contradicts what is written in following books: 1. B. Stroustrup, Programming: Principles and Practice Using C++, 2nd Ed. 2. H. Schildt, C++ from the Ground Up, 3rd Ed. (I will add chapters and quoted texts from these books next to this comment) Reading these books my understanding is: standard C++ I/O library is designed NOT to be device-specific, and programmers shall be able to use the library in a same way for different devices, keyboard etc. correct me if I'm wrong? – Nadeem Dec 30 '20 at 14:03
  • The most fundamental point to understand about the C++ I/O system is that it operates on streams...All streams behave in the same manner, even if the actual physical devices they are linked to differ. Because all streams act the same, **the same I/O functions and operators can operate on virtually any type of device. For example, the same method that you use to write to the screen can be used to write to a disk file or to the printer.** (Chap 18, Page 418, Section "C++ Streams", book C++ from the Ground Up, by H. Schildt, 3rd Ed. – Nadeem Dec 30 '20 at 14:16
  • "Most modern operating systems separate the detailed handling of I/O devices into device drivers, and programs then access the device drivers through an I/O library that makes I/O from/to different sources appear as similar as possible. Generally, the device drivers are deep in the operating system where most users don’t see them, and **the I/O library provides an abstraction of I/O so that the programmer doesn’t have to think about devices and device drivers**" (Chap 10, section 10.1 "Input and output" in the book Programming: Principles and Practice Using C++ by B. Stroustrup, 2nd Ed) – Nadeem Dec 30 '20 at 14:17
  • Well, those all refer to specific types of input devices, specifically blocking, synchronous text streams. C++ I/O streams don't really handle non-blocking / async input at all. What was asked about was explicitly `I want to know if it's possible to redirect it to some other device like a mouse or a game controller`, which is async, non-blocking input that standard C++ I/O streams does not directly support. In fact, if you want to handle async, non-blocking keyboard input, you have to use a method other than I/O streams. – Michael Gaskill Jan 01 '21 at 05:19
  • C, C++, and most other standard I/O libraries for other languages only effectively handle "cooked" input, which is processed, normalized input, and completely different from "raw" input. It's unfortunate that such sweeping statements are made about "virtually any type of device", when this only actually is true for certain categories of devices; there are far, far more device types that are only effectively usable by bypassing I/O streams, including such common input sources as mouse events, game controller events, clock timings, audio input, video input, or even block-level file I/O. – Michael Gaskill Jan 01 '21 at 05:26
  • I have provided links to Windows APIs, Mac OS APIs, and 3rd party libraries that handle these sorts of non-standard I/O interfaces, if you want to do anything at all interesting with those sorts of devices. Heck, if you want to output to a GUI, you have to bypass C++ I/O streams, because the GUI doesn't conform to I/O streams limitations. It's worth looking a bit into at least some of these to understand why they simply cannot work via I/O streams, by their very nature. – Michael Gaskill Jan 01 '21 at 05:33
  • Regarding this statement "`All streams behave in the same manner, even if the actual physical devices they are linked to differ`", it reminds me of the old adage "`in theory, theory and practice are the same; however, in practice they differ`". Meaning: don't rely solely on theory for wisdom and truth, and don't be surprised to find that strong absolute statements like those quoted are indeed flawed or incomplete in ways that you'd not guess until you had direct experience working with them. – Michael Gaskill Jan 01 '21 at 05:42
1

Usually, you change it prior to starting your program. For example, standard input may come from a file:

./my_program </some/file/name

or from another process:

/some/other/program | ./my_program

You can change stdin from within a program, but it's almost always the wrong thing to do, and can cause surprise for anyone else working on it¹. If you're writing re-usable code that needs to perform input, I recommend that you pass the input stream (or file descriptor, or FILE* if you're working with C) into your functions, to allow the external code to open its own files if it wants (perhaps more than one file, and perhaps also pipes or sockets...)


¹ "Someone else" can often be read as "yourself in 6 months' time"...

Toby Speight
  • 27,591
  • 48
  • 66
  • 103