Basically I need user input for an integer, I tried these methods:
#include <iostream>
int main() {
int PID;
scanf("%i",&PID); //attempt 0
cin >> PID; //attempt 1
}
any ideas?
Most command-line input methods require the user to press ENTER to signal the end of the input, even if the app does not use the line break.
If you do not want the user to end the input with ENTER then you will likely have to resort to reading the input 1 character at a time and handle data conversions manually. The problem is, without a line break, how do you know when the user has finished typing the input? When the user has typed X number of characters/digits? What if the user types fewer then your max? Start a timer and stop reading when the user stops typing for X seconds? See the problem?
Line breaks are not something to be ignored. You should re-design your input logic to accept them, not avoid them. If that is really not an option, then maybe you need to re-think why you are creating a command-line app in the first place instead of a GUI app where the user can press a button when ready.
Related
This is an excerpt from the Competitive Programmer's Handbook by Antti Laaksonen:
If the amount of data is unknown, the following loop is useful:
while (cin >> x) {
// code
}
This loop reads elements from the input one after another, until
there is no more data available in the input.
My question is how do we end such a loop in the command prompt, where the prompt takes one input at a time? By pressing enter, the prompt asks for new input and not terminating the input.
Edit: I have tried using ctrl + D/Z but I am getting this:
In order for that loop to end, cin needs to enter a failed state. That will cause it to evaluate to false and stop the loop. You have a couple ways you can do that. First is to send bad input, which will cause cin to fail and end the loop. Since you are excepting integers, you could just input a letter and that will cause it to break.
Another option is to send the EOF (end of file) signal to cin You can do that using ctrl+D (windows) or ctrl+Z (linux) and the pressing enter. cin will stop reading once it sees it has reachged the EOF and it will enter a failed state and cause the loop to end.
It should be noted that with both of these options that if you want to use cin again after you do this you will need to call clear() to remove the error flags and if you entered bad input, you will need to use ignore() to remove the bad input from the stream.
My question is how do we end such a loop in the command prompt, where the prompt takes one input at a time?
Note that cin >> x; returns cin. This means when you write
while(cin >> x)
you do the >> operation into x and then check cin.
When the user enters an input whose type differs from the type of variable x, then this while loop will end automatically. This is because cin will not be in a valid state anymore and hence cin >> x will become false . Basically the loop ends when the state of the stream is set to failed. Like supplying a different type value or when EOF is encountered.
There is other way to end such a loop from inside the while block by using break .
I'm a newbie to C++ (and to programming in general). I wrote a program that reads and writes staff contact details. This code works well:
// appropriate headers...
int main()
{
char trigger{};
int options = 0;
bool testing{};
fileIps Inptbox; // for entering new data
char ext_title[20]; char ext_intercomNum[4]; char ext_dept[20];
printf("%s", "Enter Officer's Title:\n");
gets_s(ext_title, 20);
printf("%s", "Enter Officer's Intercom Number:\n");
gets_s(ext_intercomNum, 4);
printf("%s", "Enter Officer's Department:\n");
gets_s(ext_dept, 20);
Inptbox.rcv_values(ext_title, ext_intercomNum, ext_dept);
Inptbox.create_string();
testing = Inptbox.validate();
if (testing == true)
return -1;
else if (testing == false)
Inptbox.write_string();
// more code below...
My question is regarding the console output. I had tried to introduce conditional statements to enable selecting a read or write mode. The above code is for writing to file. There are more lines of code below for reading from file and they, too, worked okay.
My challenge is that once I introduce a conditional statement for the above code...
printf("%s", "Enter 1 to WRITE DATA or 2 to READ DATA\n");
cin >> options;
if (options == 1)
{
fileIps Inptbox; // for entering new data
//... rest of code...
}
// more code below...
...the output on the console is flawed, as the prompt for the first entry is displayed but is totally skipped, forcing the user to enter 'Officer's Intercom Number' first. The third prompt worked well.
To elaborate further, when I used cin to assign the value 1 to options (i.e. applying the condition), the console would immediately print...
Enter Officer's Title:
Enter Officer's Intercom Number:
...making it impossible for me to fill in the first entry (i.e. 'Title').
I struggled with this and tried several things to fix it. I used fgets() and even tried it with gets(). I revisited my classes, yet nothing worked. I read widely on things like buffering, studied questions on this site and looked through various resources on cstdio as well as ios_base and its derived classes (which was good because I learned a bunch of other things). However, unless I removed that 'if' statement from my code, nothing I else I tried worked.
So, my question is: "How can this kind of behaviour be explained and how best could I implement my code to enable me toggle between read and write mode?"
I am working with MS Visual Studio 2015.
Using the formatted extraction operator '>>' has its problems. In this case, it reads all values that can convert to an integer. However, you must give an enter to signal that you're ready. The >> operator does not process that newline. When the next time input is read, it sees the previously given newline character. Hence the 'Enter Officer's title' input is immediately set to a newline and continues. Try using something like:
std::string line;
getline(cin, line);
And test the string or convert it.
What is the difference between inputting a sequence of values for an array of integers in cin using a SPACE and an ENTER key?
For example -
If I have to input a sequence of numbers in an array and stop receiving the input as soon as 0 is entered by the user in the chain of values. It works correctly if ENTER is pressed on the keyboard to separate each number during input whereas on using SPACE it doesn't stop the input process. Can the below code be modified in some way, so that it works for the SPACE as well?
#include<iostream>
using namespace std;
int main()
{
int arr[10];
int i=-1;
do{
cin>>arr[++i];
}while(arr[i]!=0);
i=-1;
do{
cout<<"\n"<<arr[++i];
}while(arr[i]!=0);
}
"It works correctly if the enter key is pressed to separate each number during input whereas on using the space bar it doesn't stop the input process."
ENTER triggers to read the input stream from an input terminal with cin, while SPACE doesn't.
Usually ENTER from a terminal expands to have the input from the prompt plus a '\n' or '\r' '\n' character sequence sent, and it's considered part of the input.
"Can the below code be modified in some way, so that it works for the space bar as well?"
No, not unless you manage to have a terminal sending input to your program using the SPACE key.
In the end it doesn't really matter for the parsing if you input
1 2 3 4 >ENTER
or
1 2 >ENTER
3 4 >ENTER
std::istream will handle receiving ' ', '\t' or '\n' characters (see std::isspace()) transparently. To send these characters to input is still triggered by the terminal when the ENTER key is pressed.
Space and enter are doing the same thing with respect to cin. It's your mechanism of entry (e.g. your terminal program) that is treating space and enter differently: terminals usually don't pass anything along to your program until you hit enter.
To do what you want, you need to use a library that lets you interact with your terminal. (or maybe your terminal has options you can configure to do this)
Referring to two questions:
Incorrect output from C++ Primer 1.4.4
Confused by control flow execution in C++ Primer example
My question is answered in both of those posts, but I want to delve further.
First, I know this is only the beginning, but let's say I make a fully functional program that runs in a designed window. By that level, will I already know how to implement a EOF? I can't expect someone running my program to know that they need to hit Control-Z.
Is there a way to implement a specific code that functions so that it does not need me to type in an unrecognized value?
Also one guy in those questions somewhat answered the importance of EOF, but how come the program doesn't even post the final cnt - 1?
Let's say I do the numbers 10 10 10 20 20 20. Without EOF, this will only show the "10 repeats 3 times." How come the program doesn't at least type in the count "10 repeats 3 times and 20 repeats 2 times" minus the final one with white space?
lets say I make a fully functional program that runs in a designed window. By that level, will I already know how to implement a eof? I can't expect someone running my program to know that they need to hit ctrl + z.
You could either tell the user explicitly to do a specific action to end input or the design of the window itself could tell the user the information implicitly. For instance, a dialog box could ask the user to enter input and click an OK button when done.
Is there a way to implement a specific code that functions so that it does not need me to type in an unrecognized value?
It seems like you would rather use a newline character to terminate your input. An example of this usage could be std::getline. Instead of writing
while (std::cin >> val)
you could instead use
std::string line;
if (std::getline(std::cin,line))
and assume that your user's input only consists of one line of values. There are plenty of other ways to similarly achieve this task depending on how you want to constrain the user's input.
Let's say I do the numbers 10 10 10 20 20 20. WIthout eof this will only show the "10 repeats 3 times." How come the program doesn't at least type in the count "10 repeats 3 times and 20 repeats 2 times" minus the final one with white space?
Without the eof your program is still executing the while (std::cin >> val) loop since std::cin >> val has not yet received invalid input.
Since the line
std::cout << currVal << " occurs " << cnt << " times" << std::endl;
occurs after that while loop finishes execution, you don't (yet) see any information about the three 20's in the input.
When you are reading a sequence of inputs you'll need some indication when your down. That could be a sentinel value ("enter 999 to stop reading"; you'd need to detect that while reading), an invalid input ("enter X to stop reading"; when reading an int the value X is illegal and causes the stream to got into failure mode, i.e., have std::ios_base::failbit set), or the more conventional "there isn't anything more to read". For a file, the last conditions is straight forward. When reading data from the console you'll either need to teach people how to terminate the input or you'll need to use a different approach.
If you want to intercept any keypressed and react on them directly you may do so, too. You could, e.g., use ncurses and control your input via that. You could also set the concole to non-buffering (on POSIX systems using tcgetattr() and tcsetattr() to clear the ICANON flag) and deal directly with all key presses to decide whether you want to continue reading or not.
Although I'm certainly up to doing fancy I/O stuff I normally don't bother: users will understand the "end of input" character and just deal with it. That is, my input normally looks something like this:
while (in >> whatever_needs_to_be_read) { ... }
... or, if the input is genuinely line oriented
for (std::string line; std::getline(in, line); ) { ... }
The function doing this input will then be called with a suitable std::istream which may be std::cin although I have typically some way to also read from a file (in addition to the shell-privided input redirection).
BTW, despite some indications in the questions referenced, "EOF" is not a character being read. It is a character entered, though (normally). ... and it is quite conventional to "know" the end of input character (on POSIX systems a ctrl-D and on Windows a ctrl-Z). You can use other indicators, e.g., the "interrupt" (ctrl-C) but that takes more work and doesn't integrate nicely with stream. To use the interrupt chacter you'd need to setup a signal handler for SIGINT and deal with that. One slightly annoying part of doing so is that if you get it wrong you'll need to find a different way to kill the program (e.g. on POSIX using ctrl-Z to put the process to sleep and kill it via a harsher signal).
I have this block of code form my input class I wish to improve. It works fine at the moment.
http://ideone.com/ryatJ
You use it like this... What it dose is pass a reference to the stream, and a reference to the userinput and a int to mark the max range the input has to be. The usrinput is referenced so we can use that elsewhere and it returns a true false so we can use it like this.. to get input...
while (!(validate(cin, returnval, a))){
//# Error Code code here
}
Basically everything works.. it asks the user to input a number that we are expecting as a int.
Using if (cin >> int) - I get a true false based on if the user entered a int or not. (so any string or anything... errors)
Using > and < we make sure the int is in the correct range, or it errors.
Useing peek we check the stream for a \n.. if it is not found.. it errors. (so 2.2 or 2:3 4#3 etc etc will error)
So that is all working, so well in fact I only just recently noticed that there is one more error check I need. Though I am not sure how to do it.
Basically if you just press enter with out first putting in ANY value, cin just goes to a new line. Is there a way to detect that the user just hit enter and nothing else, so I can return teh correct error message and redraw the menu screen and all the other stuff I wish to do.?
SUMMERY
How can I add to this a function to check if enter is pressed with out entering any other vales?
Thanks for the help
--Jynks
EDIT------
I can not answer my own question.. but this is the answer...
I was very close.. but the answer was in my code already.... meaning that cin.peek() is looking at the stream, at the moment it is calling it after it is read into a variable. This means it is seeing the "2nd" char and why the test works... all I needed to do was make a new test b4 the cin was read and it checked the 1st character..
Solved
http://ideone.com/mt7jH