I'm in a course for C++ programming.
Our professor created a linux validation script against which our program output must match exactly.
The problem is, this program excepts probably 150-200 lines of input and if anything goes in wrong you have to start all over again. If you even enter an incorrect char, it must be restarted as the backspace registers as a character of its own.
Is there a way I can force the CIN input to match exactly, so that the program will input the data on its own according to my specifications?
No, there isn't. You must know what is being expected beforehand to pass the validation.
Related
The title is misleading because I'm more interested in finding an alternate solution. My gut feeling is that checking whether the buffer is empty is not the most ideal solution (at least in my case).
I'm new to C++ and have been following Bjarne Stroustrup's Programming Principles and Practices using C++. I'm currently on Chapter 7, where we are "refining" the calculator from Chapter 6. (I'll put the links for the source code at the end of the question.)
Basically, the calculator can take multiple inputs from the user, delimited by semi-colons.
> 5+2; 10*2; 5-1;
= 7
> = 20
> = 4
>
But I'd like to get rid of the prompt character ('>') for the last two answers, and display it again only when the user input is asked for. My first instinct was to find a way to check if the buffer is empty, and if so, cout the character and if not, proceed with couting the answer. But after a bit of googling I realized the task is not as easy as I initially thought... And also that maybe that wasn't a good idea to begin with.
I guess essentially my question is how to get rid of the '>' characters for the last two answers when there are multiple inputs. But if checking the cin buffer is possible and is not a bad idea after all, I'd love to know how to do it.
Source code: https://gist.github.com/Spicy-Pumpkin/4187856492ccca1a24eaa741d7417675
Header file: http://www.stroustrup.com/Programming/PPP2code/std_lib_facilities.h
^ You need this header file. I assume it is written by the author himself.
Edit: I did look around the web for some solutions, but to be honest none of them made any sense to me. It's been like 4 days since I picked up C++ and I have a very thin background in programming, so sometimes even googling is a little tough..
As you've discovered, this is a deceptively complicated task. This is because there are multiple issues here at play, both the C++ library, and the actual underlying file.
C++ library
std::cin, and C++ input streams, use an intermediate buffer, a std::streambuf. Input from the underlying file, or an interactive terminal, is not read character by character, but rather in moderately sized chunks, where possible. Let's say:
int n;
std::cin >> n;
Let's say that when this is done and over is, n contains the number 42. Well, what actually happened is that std::cin, more than likely, did not read just two characters, '4' and '2', but whatever additional characters, beyond that, were available on the std::cin stream. The remaining characters were stored in the std::streambuf, and the next input operation will read them, before actually reading the underlying file.
And it is equally likely that the above >> did not actually read anything from the file, but rather fetched the '4' and the '2' characters from the std::streambuf, that were left there after the previous input operation.
It is possible to examine the underlying std::streambuf, and determine whether there's anything unread there. But this doesn't really help you.
If you were about to execute the above >> operator, you looked at the underlying std::streambuf, and discover that it contains a single character '4', that also doesn't tell you much. You need to know what the next character is in std::cin. It could be a space or a newline, in which case all you'll get from the >> operator is 4. Or, the next character could be '2', in which case >> will swallow at least '42', and possibly more digits.
You can certainly implement all this logic yourself, look at the underlying std::streambuf, and determine whether it will satisfy your upcoming input operation. Congratulations: you've just reinvented the >> operator. You might as well just parse the input, a character at a time, yourself.
The underlying file
You determined that std::cin does not have sufficient input to satisfy your next input operation. Now, you need to know whether or not input is available on std::cin.
This now becomes an operating system-specific subject matter. This is no longer covered by the standard C++ library.
Conclusion
This is doable, but in all practical situations, the best solution here is to use an operating system-specific approach, instead of C++ input streams, and read and buffer your input yourself. On Linux, for example, the classical approach is to set fd 0 to non-blocking mode, so that read() does not block, and to determine whether or not there's available input, just try read() it. If you did read something, put it into a buffer that you can look at later. Once you've consumed all previously-read buffered input, and you truly need to wait for more input to be read, poll() the file descriptor, until it's there.
Thanks for taking the time to read this first of all,
I'm currently writing a driver program for a class in C++ and I need some input from the user. I've started using typedef to create validation programs so I can switch between different types fairly easily. For the particular problem I'm working on, I've found that I'm only working with char which leads me to my questions:
My validation checks to see if the input is char. Is using validation pointless if I know I'm just working with char in particular? Everything that the user types in seems to be a char.
Is there anything that the user could type in that won't be considered a char?
This question may seem a bit trivial but I've never really thought about this before! Still learning the language, so any guidance is appreciated.
Code in question (ElementType is of type char):
void getInput( ElementType & cho )
{
while ( !(cin >> cho) )
{
cout<< "That is an invalid input..."
<< "\nTry again: ";
}
cout<< endl;
}
Is there anything that the user could type in that won't be considered a char?
Yes: Shift, Ctrl, Alt, Num Lock to name a few.
The point is that a keyboard is its own beast with a potential output for each key-press, key-release of every key. A keyboard driver (software) takes these events and translates them into a series of char for a program's cin/stdin. Alternatively, a program could get access to the low level events, but may be beyond standard C++ code.
Recommend staying with the model that cin receives sporadically any of the usually 256 different char including '\0' until program-end or cin is closed from some source be it a keyboard, re-directed file input, piped input, or a remote device. Ignore that idea that input usually comes from a keyboard. It is simply a sequence of char.
Is using validation pointless?
Validation is useful. Code should validate the char arriving per the requirements of the program - not the requirements of char. Example, code may have trouble handing a null character, a negative char, a char outside the ASCII range of 0 - 127, or too many char between line endings. Validating input makes code resilient against hackers who will exploit a vulnerable program.
Under Linux, with UTF-8 input, I can certainly type a lot of stuff that isn't a char. E.g. typing รก gives two bytes. There are quite a lot of others, directly typeable depending on the keyboard handling in place.
International character handling is complex. Not all the world types ASCII.
Suppose I created a character array say of 20 bytes and prompts the use to input their name provided their name should not be more than 20 characters...
For Example:
char Name[20];
gets(Name);
Now suppose his name is abcdefghijklmnopqrstuvwxyz
But as soon as he enters abcdefghijklmnopqrst, the Name should not take any further input... Neither the further input provided by the user should appear on the console screen... Only the cursor should blink until he presses enter. So how to do it??
More Information
Operating System: Windows 7
Compiler: Visual C++ 2010 Express
The manpage states:
Never use gets(). Because it is impossible to tell without knowing the data in advance how many characters gets() will read, and because gets() will continue to store characters past the end of the buffer, it is extremely dangerous to use. It has been used to break computer security. Use fgets() instead.
So you could use fgets:
char *fgets(char *s, int size, FILE *stream);
Yet the input sequence doesn't stop yet; however, you are no longer running into undefined behaviour and security holes, iff used correctly.
You should better use C++ facilities like std::string, std::getline, and the standard iostreams. They won't enable you stopping input, however, they prevent security holes when used in the canonical manner.
Summary of Standard Alternatives:
gets() can not be used correctly. People will may die when you use this (you wouldn't find a smile on my face as I am not kidding). There is provably no correct way to use it. Do not forget it, but throw it out of your toolbox now.
fgets() can be used correctly, but there's a lot of opportunity to misuse it.
iostreams and strings are automatically used correctly. Use them.
Unforunately, there is no builtin solution to read at max N characters from input without having to discard superfluous characters typed in. You would have to use a 3rd-party library or roll your own.
Here's silly answer:
If you want for example the user to enter a name with maximum 20 characters
Create a char array with. size[20]
Ask the user to enter the size of the name and check the validity of the number if its less than or equal.20 then move on and add the name else ask the user to enter the size again.
You can use a string instead of a char but that won't make sure that the user actually followed the size rule
For example a user can enter a size 10 and the program will allow him to enter the name but once he's allowed if you are using the.string he can write as many as he wishes.
OR using a char array. for name with 20 or less.characters
For example the code would need a simple for loop
Since we already have the size given which is less than or equal.20
For(int i =0; i<20; i++)
Cin>>char[i]
Then you can assign the characters into a string.
I am in high school and it is mandatory to use Turbo C++ compiler, I know it is a very old compiler but please understand my situation.
So I was writing a code on a employee database. The code snippet:
userdb user;
fstream fil;
while(fil.read((char*)&user,sizeof(userdb)))
{
cout<<user.name;
cout<<user.pass;
cout<<user.age;
cout<<user.address;
}
fil.close();
Now the problem is that if a user doesn't have his address inputted in the database, the compiler displays garbage.
How can I check if a value has nothing(garbage) so as to not print it on the screen?
(I have tried address[0]='\0' and strcmp("",address)==0 and this is not working)
Empty field does not mean anything in this context. Indeed, you are reading N bytes from a file, storing them into memory. You tell the computer to interpret this portion of memory as a string. There's nothing to be done to know whether the field is empty or not.
Your best bet, would be to look at this memory, and to try to guess whether is looks like an actual address or not.
Maybe first could you look at whether this address string, stored into a character array of a fixed size, has a termination character in it. If not, you could guess that it is invalid, and possibly add this termination character at the end of the character array.
So this is a problem that I've been having since I started programming (Not that long ago. I still don't know why I started with C++). When I have some integer variables and the user's input defines them, if the user inputs something other than an integer the program freaks out and runs an endless loop of the last command it was given. I don't think sample code is needed but if it is I can make a basic example pretty easily.
If you want to know exactly what your mistake was, then we'd need to see your code, but the usual idiom is like this:
int i;
while (std::cin >> i) {
// do something with the user's input, i
}
if (std::cin.fail()) {
std::cout << "not a number!\n";
}
If failure occurs and you want to get past the invalid input so that the user can try again, first call cin.clear(), then either cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n') to ignore the whole line, or std::string s; std::cin >> s; to ignore a whitespace-separated word.
Beware that because the second case actually constructs the string in memory, the user could input a few gigabytes without a space, and the program will fail. That's usually fine if the input is from a terminal, it's the user's own stupid fault. It might be less fine if the input is from an HTTP request or other untrusted source, so some time in future you might end up worrying about it...
Check this out Guess the number - Infinite loop when bad read
When programming always, and i mean always, validate your input.
Check if the input you get is sane.
What i mean by that if you get something that is supposed to be int check if it is.
Convert it if it is not.
If you get a string check if it is in bounds, meaning is it to long, to short, to whatever.
cin
Would be the Term to Google for in your case.