Only the first call to getline() appears to read anything in from std::cin. Is the fact that buffer contains something a problem - why doesn't getline() just overwrite the contents of buffer?
How can I get the second call to getline() to read something in?
My code:
const int recordLen = 20;
// truncate the input to 20 chars
void getText(char line[])
{
std::cout << "Enter something for getText: ";
std::cin.getline(line, recordLen+1);
for(int i = std::strlen(line); i < recordLen; i++)
{
line[i] = ' ';
}
line[recordLen] = '\0';
}
int main()
{
char buffer[340];
getText(buffer);
std::cout << buffer;
std::cout << "Now enter some more text:";
// put more text into buffer
std::cin.getline(buffer, 30);
std::cout << "you entered : " << buffer << std::endl;
return 0;
}
So - example output of program:
Enter something for getText: alskdjfalkjsdfljasldkfjlaksjdf
alskdjfalkjsdfljasldNow enter some more text:you entered :
After the display of "Now enter some more text:", the program immediately displays "you entered:". It does not give me the opportunity to enter more text, neither does it display any characters that were truncated from the previous call to getline().
std::cin.getline(line, recordLen+1);
Here, if the input is longer than recordLen chars, the remaining characters will not be read and will remain in the stream. The next time you read from cin, you'll read those remaining characters. Note that, in this case, cin will raise its failbit, which is probably what you're experiencing.
If your first input is exactly recordLen chars long, only the newline will remain in the stream and the next call to getline will appear to read an empty string.
Other than that, getline does overwrite the buffer.
If you want to ignore anything beyond the first recordLen chars on the same line, you can call istream::clear to clear the failbit and istream::ignore to ignore the rest of the line, after istream::getline:
std::cin.getline(line, recordLen+1);
std::cin.clear();
std::cin.ignore( std::numeric_limits<streamsize>::max(), '\n' );
Related
I want simply read two chars in C++ but it can't take the second char!!
#include <iostream>
#include <sstream>
using namespace std;
int main()
{
cout << "reading char: ";
char ch1;
cin.get(ch1);
cout << ch1 << endl;
char ch2;
cout << "reading char: ";
cin.get(ch2);
cout << ch2 << endl;
return 0;
}
can anyone help me to solve this problem?
This is the output:
reading char: a
a
reading char:
Process returned 0 (0x0) execution time : 2.158 s
Press any key to continue.
*************************
The program finishes here, and it does not read the second the char
The problem here is that standard input (std::cin) is buffered. So the program gets no input until the <return> key is presses (or you fill the buffer). This gives you the impression that the code will always wait for user input.
This is not true. It will only wait for user input if the current buffer is empty. If there is data in the buffer it will read that rather than waiting for user input.
The first read:
cin.get(ch1);
Start of the program so the buffer is empty. So when you read from std::cin the program will pause waiting for the buffer to be flushed then the characters will be read. If you hit A<return> your buffer will flush with two characters in the buffer.
Buffer: 'A' '\n'
Your read will now retrieve thefirst character from the input: 'A' leaving the '\n' on the input stream:
Buffer: '\n'
Now the second read sees the buffer is not empty.
cin.get(ch2);
And does not need to wait it will read the next character from the stream. So it reads the '\n' character from the stream. and continues.
Solutions:
That depends what you want. Do you want only the first character from the line?
std::cin.ignore(); // drops the rest of the line.
// The next character that will be available will
// be the first character of the next line.
You just want to ignore white space? (this is space/tab/newline etc).
std::cin >> v1 >> v2;
Using the operator>> ignores leading white space, then reads the next value. So it will ignore new lines (they are white space).
Your issue here is get only grabs a single character from the stream. When you enter character for your first input by typing the character and pressing enter you actually put two characters into the stream. The one you entered and then enter key (newline character). That means your second call to get is going to get the newline character that is still in the buffer and not wait for you to enter anything. To fix this you should use the stream extraction operator (operator >>) to read the single character and it will skip over the white space that is left in the buffer. That turns your code into
int main()
{
cout << "reading char: ";
char ch1;
cin >> ch1;
cout << ch1 << endl;
char ch2;
cout << "reading char: ";
cin >> ch2;
cout << ch2 << endl;
return 0;
}
If you enter the first character and press enter, then the new-line character (ASCII 10) is read by the second get() call.
The problem is that when you enter in a char and then hit enter, you are entering a newline character into the console. So the call to cin.get() returns the newline to ch2 and your program then prints out ch1 and a blank newline from ch2 and exits.
Instead of using cin.get() you should use cin >> ch1 and cin >> ch2
Why should I input something on the second line of the console?
int main() {
string s;
while (true) {
cout << "Input: ";
char a = getline(cin, s).get();
cout << a << endl;
}
return 0;
}
Because you are reading twice from std::cin.
The std::getline function returns the stream, and then you call get on the stream which requires you to enter something else.
And that you apparently only have to input once is because you actually enter three characters on the second input: 'f', 'd' and a newline. So the first get call will read the 'f'. Then the next iteration the getline call will read "d\n" and the get call will read the next inbput you write and so on.
Simple solution? Don't call get:
getline(cin, s);
cout << s << '\n';
I'm writing a small shell program, but I can't even get past reading a line of input. I'm using cin.getline() to read the user supplied args into a text buffer but it doesn't work. Code:
int main(int argc, char *argv[])
{
char buffer[1024];
cout << "John's Shell>>";
cin.ignore(17);
cin.getline(buffer, 1024);
cout << buffer << endl;
return 0;
}
I'm trying to use cin.ignore(); to ignore my prompt as well as the newline character. All that happens is that after I press enter I just get a blank output. buffer is never printed. I appreciate any help
I'm trying to use cin.ignore(); to ignore my prompt
Then don't. You don't need to. The input you take from cin's buffer is separated from whatever device cout stream is sending characters to.
cin.ignore(17) just waits until there are 17 characters to ignore, so cin.getline(buffer, 1024) will only be able to read those that are left (if any).
You'd use this function to ignore undesired characters that are waiting in the input buffer, for example when you encounter that parsing failed:
int i;
if (cin >> i) {
cout << "You entered: " << i << '\n';
} else {
// input not an integer, get rid of it:
cin.ignore( std::numeric_limits<std::streamsize>::max(), '\n');
}
And there's an easier an more robust way to take a line of input:
std::string line;
std::getline(std::cin, line);
No off-by-one errors and no buffer overflows. std::string will grow automatically to accomodate any size of input, up to avaliable memory.
I am trying to read the n-th line from the standard input in the following program. However, the console will print out "current line is" before I input any number...not sure what's wrong. Thanks for help.
int main()
{
string currentLine;
int n;
cin >> n;
cout << n << endl;
while (n > 0)
{
getline(cin, currentLine);
cout << "current line is" << currentLine << endl;
n--;
}
return 0;
}
The formatted input using operator>>() stops as soon as its format can't be satisfied by the next character. For integers it stops when there is no further digit, e.g., when the next character is a whitespace like the newline from entering the line.
std::getline() reads until it finds the first newline. There was one left right before when reading the integer. You probably want to extract this newline and potentially other whitespace. You could, e.g., use
if (std::getline(std::cin >> std::ws, currentLine)) {
// do something with the current line
}
else {
// deal with a failure to read another line
}
The manipulator std::ws skips leading whitespace. As indicated above, you should also verify that the input was actually successful before processing input.
In order to get n, you have to input a number and press the Enter button. As #Kuhl said, the operator>> stops as soon as its format can't be satisfied by the next character.
This means the first time getline(cin, currentline) runs will get '\n' !
Then the program will output "current line is\n" while the '\n' will not be shown on the console.
If you want to get n and 'currentline', you may choose the #Kuhl's answer or write the program like this:
getline(cin, currentline);
while(n>0) {
// anything you want
}
The getline(cin, currentline) will help you to skip the '\n' followed by the number 'n'.
I'm sorry but I'm quite new to C++ but not programming in general. So I tried to make a simple encryption/decryption. However when I added the modification to my previous code (so there isn't two programs for encrypting and decrypting) I found that the code 'getline()' method no longer works. Instead it's just ignoring it when the code is ran. Here's the code:
int main(){
std::string string;
int op = 1; //Either Positive or Negative
srand(256);
std::cout << "Enter the operation: " << std::endl;
std::cin >> op;
std::cout << "Enter the string: " << std::endl;
std::getline(std::cin, string); //This is the like that's ignored
for(int i=0; i < string.length(); i++){
string[i] += rand()*op; //If Positive will encrypt if negative then decrypt
}
std::cout << string << std::endl;
std::getchar(); //A Pause
return 0;
}
That's because std::cin >> op; leaves a hanging \n in your code, and that's the first thing getline reads. Since getline stops reading as soon as it finds a newline character, the function returns immediately and doesn't read anything more. You need to ignore this character, for example, by using cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); (std::numeric_limits is defined in header <limits>), as stated on cppreference.
This is because you still have the newline character in the buffer which makes getline() stop reading as soon as it encounters it.
Use cin.ignore() to ignore the newline character from the buffer. This will do in your case.
In general, if you want to remove characters from your buffer untill a specific character, use:
cin.ignore ( std::numeric_limits<std::streamsize>::max(), ch )
Use :
cin.ignore ( std::numeric_limits<std::streamsize>::max(), '\n' );
to eat newlines from previous input std::cin >> op;
header - <limits>
Other way would be :
while (std::getline(std::cin, str)) //don't use string
if (str != "")
{
//Something good received
break;
}
As other stated already, the formatted input (using in >> value) start skipping space abd stop when they are done. Typically this results in leaving some whitespace around. When switching between formatted and unformatted input you typically want to get rid of leading space. Doing so can easily be done using the std::ws manipulator:
if (std::getline(std::cin >> std::ws, line)) {
...
}
You must use std::cin.ignore() before std::getline(std::cin, string) to clear the buffer, because when you use std::cin >> op before the getline a \n gets in the buffer and std::getline() reads it. std::getline() takes only the line you type, when you skip a line, std::getline() closes, so when std::getline() picks up \n from the buffer it is already terminated before you type something, because /n skips a line.
Try this way:
int main(){
std::string string;
int op = 1; //Either Positive or Negative
srand(256);
std::cout << "Enter the operation: " << std::endl;
std::cin >> op;
std::cout << "Enter the string: " << std::endl;
std::cin.ignore();
std::getline(std::cin, string); //This is the like that's ignored
for(int i=0; i < string.length(); i++){
string[i] += rand()*op; //If Positive will encrypt if negative then decrypt
}
std::cout << string << std::endl;
std::getchar(); //A Pause
return 0;
}