why does cout.tellp always return -1? - c++

I want to provide a tab-like capability for C++ text output streams. The feature should allow me to say "note this position", then allow multiple insert operations, and finally allow me to say "add enough fill characters so as to end up N characters past the originally noted position".
The standard iostream system does not seem to maintain a column position but I had thought that I could fake it using tellp(). My assumption was that the difference between tellp() at two points in my output sequence would correspond to the number of intervening bytes.
Unfortunately, at least in my Gnu C++ environment, cout does not maintain the fiction of a stream position. Every cout.tellp() call returns -1. Why is that?

tellp returns a position in a stream so that you can seek to it. Console does not allow seeking. Besides, even you interpret position as "the number of bytes written to the stream since it was created", that number won't be of any use for cursor positioning - the screen wraps around, its width is generally unpredictable. You just won't know what column you're on, since the row length is variable.
If you want reasonable cursor positioning on the screen, check out the ANSI terminal specification and escape commands that come with it. They allow for cursor position discovery and placement.
http://ascii-table.com/ansi-escape-sequences.php
In general, the screen is not a stream. Neither is the keyboard, for that matter :)

Related

C++ char spacing in console output, UTF-16 characters

I'm making a game in C++ console using UTF-16 characters to make it little bit more interesting, but some characters are different size then others. So, when I print the level, things after character are moved further than others. Is there any way how to add spacing between characters with some console function, I try to google something helpful, but I have not found nothing.
I tried to change font size by CONSOLE_FONT_INFOEX, but it changed nothing, maybe i implement it in the wrong way, or it not work with UTF-16 characters.
// i tried this
CONSOLE_FONT_INFOEX cfi;
cfi.cbSize = sizeof(cfi);
cfi.dwFontSize.X= 24;
cfi.dwFontSize.Y= 24;
Unfortunately I expect that this will heavily depend on the particular console you're using. Some less Unicode-friendly consoles will treat all characters as the same size (possibly cutting off the right half of larger characters), and some consoles will cause larger characters to push the rest of the line to the right (which is what I see in the linked image). The most reasonable consoles I've observed have a set of characters considered "double-wide" and reserve two monospace columns for those characters instead of one, so the rest of the line still fits into the grid.
That said, you may want to experiment with different console programs. Can I assume you are on Windows? In that case, you might want to give Windows Terminal a try. If that doesn't work, there are other console programs available, such as msys's Mintty, or ConEmu.
So, after some intense googling i found the solution. And solution is fight fire with fire. Unicode include character Thin Space, that is 1/5 of the normal space, so if i include two of them with one normal space after my problematic character, the output is diplaying how i want. If anybody runs into some simliar issue, unicode have lot of different sized spaces. I found Website that shows them all of them, with their propperties.
fixed output picture

(C++) Can the color of text change as it is typed?

I have a list of instructions in my program and they are activated by entering a string. There are a large number of possible instructions. You could call them commands if you like.
I already have a program that can successfully execute the instructions I've added so far.
For example, adding a person to the database would require the user to enter add "John" "Doe".
This would output to the screen Added John Doe to the database, ID#1234. The IDs are random.
I know how to add colors; in this output text, "John Doe" would be colored green.
What I'm wondering is, can I make it so that color changes as one types? Because I learned how to use some kind of keyboard mode change so that when I type a password, all characters are displayed as * of any color I desire, or even nothing displayed at all, through "display" of \0, and I know how to do that. I was wondering if the color could change before the complete string (extracted with std::getline(std::cin, str);) is typed.
The first reason I want the colors to change is because when there are so many commands, and I already have more complex commands than that, I want to provide a way for the user to be able to correct syntax mistakes before they press enter. Something like Windows PowerShell, perhaps, which was written in C#. I know that C# is a very different language than C++, but if C# can achieve something like that, I want to see if C++ can as well. My hope is that it doesn't require thousands of lines of application-specific code, especially considering that PowerShell is an actual application and not a simple terminal-run executable. And while PowerShell appears to be open-source, I don't understand C#. See the bottom for the second reason.
I have no idea if this is possible, but because similar manipulation of entered text is possible (as I said, I know how to add colors and also mask text as some other single character like *), I want to know if this is also possible.
Simple examples:
Firstly, the user should know when they have not entered a valid command, and when they have. I want the text to be in red until the letters entered so far consist of an actual keyword, like add. So, the text would be red until the second d is added, when it reverts to white, and if another letter is entered, it becomes red again.
Example 1: add "John Elias" "Doe"
After the space, the text after "add" should be red no matter what, unless the character after the space is a quotation mark. In order to tell the user that they have not terminated the string, the text beyond the (orange?) quotation mark should be orange. When the final quotation mark is entered, the entire content of the quotation marks (including the quotation marks) should be some other color (probably green?) to tell the user that they have successfully entered an argument. The same applies to any instances of quotation-mark arguments. Note that a space is allowed in a quotation argument.
Example 2: list-info 1234
In this command, it gets more complex. list is a separate command, so the text should be red until t is entered, and it turns white. But then it turns red again after that, until o is entered, and it turns white again. The numerical argument following it should be red if the entered character isn't a digit. If it is, it's still red, because the only valid IDs are 3- or 4-digit numbers. It should turn green(?) once a third digit is entered, and still stay green when another digit is entered. But if a fifth digit is entered (or another character for that matter), the number turns red again. Although this would better be implemented as returning an error if the entered number is invalid, I would still like to know if this can be done as well.
Example 3: add "John" "Elias" "Doe" "fourth-string"
Since there is an overloaded function that enables an explicit first-middle-last name to be stored as well, it should be ok if there is a third string. But if there is a fourth string added, then it should be in red no matter what because add cannot take more than 3 arguments.
My question is, are any of these things possible? And yes, I am aware that it is almost certainly better to just implement an error system, but my intention is to expand my coding ability, and that is the second reason, and coding an error system will not do that because I have already done that for every command.
For reference, I'm operating in Linux Ubuntu 18.04, I compile with g++, my code conforms to C++17, I use ANSI escape sequences for color, bold, etc., and for masking characters with something like * I use a pointer to a char array (passed by address as char**) and a C-style FILE* to reference the input stream stdin (because I haven't bothered to conform it to a typical C++ implementation yet, learning ways to advance my current skills is my priority at this point in time).

Scrolling character letter in C++

I am building a part of a tower defense game in a strictly console environment and i am stuck at the moving of a creature lets say "c", i would like the letter "c" to start on the left and move a space at a time to the right on the same line basically:
c (one second later)
c (one second later)
c and so on....
i thought that this could be implimented with an array but am lost, i want to be able to use simple code, not weird libraries and weird methods, just simple as possible. Thank you
One method is display all the characters, then a carriage return ('\r') and then reprint the line.
This allows you to "walk" characters across. This will only work on video terminals that do not advance a line upon receiving a CR.
Another method would be to print 10 backspace characters, a space, then your 10 'c'. This may not be as fast as the carriage return method above, but worth looking at.
As others have said, you may want to look into a terminal library such as ncurses. The library allows you to position the cursor on the screen, based on the terminal type. This may require setting up the console window to emulate a terminal.

Reading a stream from the right in c++

I'm a bit of a noob to c++. I understand that when one reads from a stream, you read from the left. e.g If you had a file with the line:
I'm playing around with streams
When you read the file, the first string you'll retrieve from the file is I'm
Is it possible to make the first string you retrieve to be streams
Reading a stream from the right, basically.
Note: This is assuming that you don't read entire lines per time
Streams are not read from left to right, they're read from first to last. They are supposed to model things where this is the logical way to read them and in some cases (e.g. keyboard input) the only sensible way to read them. For a stream that is entirely known at the start (e.g. a file) you could, if you really really wanted, painstakingly seek to the last element and then read them in one-by-one seeking as you go. This would be slow and ugly.
Instead, I recommend you read from first to last in the usual fashion and then manipulate the data once you've got it.
What you want to do is to read the words from right to left, not the whole stream. Reading the stream from right to left would result in smaerts not in streams and I am sure you can not do that out of the box. What I suggest is that you read the words in a vector and then reverse it. Alternatively, reverse the whole string before reading from it and then reverse each word after reading it.
No, there's no support for this in the streams library. A file is generally arranged with the document data going from left to right, top to bottom. Given variable length lines, you can't generally know where the line terminates unless you scan over all the data in the line.
For this requirement, you're best off reading an entire line into a string with getline, then you have many options such as:
writing your own string scanner to find each word in turn (simple enough, fast)
creating a istringstream from the reversed line text, then looping to stream each word in turn - reversing it back before processing (convenient for stream features - whitespace skipping, conversions, status etc.)
tokenising the line into an array or similar, and iterating that in reverse order (simple conceptually, but memory hungry)

Restrict users to enter numbers valid only till 2 decimal places C/C++

I am making an currency change program where I would be providing exact change to the input amount, for example a value of 23 would be one 20 dollars and 3 one dollar bills
I want to restrict the user to input the value only till 2 decimal places. For example: the valid inputs are
20, 20.4, 23.44 but an invalid input would be 20.523 or 20.000.
How can I do this is C/C++.
I read about one function that is setprecision but that is not what I want, setprecision allows to display the value till that decimal point, it still doesn't stop the user from entering any value.
Is there any way to do this?
Read the amount from the user as a string, either character by character or the entire line, and then check its format, and then convert it.
It's generally easier to let the user type whatever they want followed by the program rejecting the input if it isn't valid rather than restricting what they can type on a keystroke basis.
For keystroke analysis you would need a state machine with 4 states, which we can call Number, Numberdot, Numberdotone, and Numberdottwo. Your code would have to make the proper transitions for all keystrokes, including the arrow keys to move the cursor to some arbitrary place and the Backspace key. That's a lot of work.
With input validation, all you have to do is check the input using a regular expression, e.g. ^(([0-9]+) | ([0-9]+.[0-9]) | ([0-9]+.[0-9][0-9])$. This assumes that "20." is not valid. Then if it's invalid you tell the user and make them do it again.
I do not believe that there is any way to set the library to do this for you. Because of that you're going to have to do the work yourself.
There are may ways you can do this, but the only true way to handle restricting the input is to control reading it in yourself.
In this case you would loop on keyboard input, for ever keystroke you would have to decided if it can be accepted in the context of the past input, then display it. That is, if there is a decimal point you would only accept to more numbers. This also allows you to limit input to numbers and decimal places as well, not to mention input length.
The down side is you will have to handle all the editing commands. Even bare bones you would need to support delete and enter.
This is rather a task for the GUI you are using, than for core C/C++. Depending on your GUI/Web Toolkit you can give more or less detailed rules how data can or can not be entered.
If you are writing a normal GUI application you can control and modify the entered keys (in C or C++).
In a WEB application you can do similar things using javascript.
The best solution would be when all illegal input is impossible.