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.
Related
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;
}
I have a problem using getline method to get a message that user types, I'm using something like:
string messageVar;
cout << "Type your message: ";
getline(cin, messageVar);
However, it's not stopping to get the output value, what's wrong with this?
If you're using getline() after cin >> something, you need to flush the newline character out of the buffer in between. You can do it by using cin.ignore().
It would be something like this:
string messageVar;
cout << "Type your message: ";
cin.ignore();
getline(cin, messageVar);
This happens because the >> operator leaves a newline \n character in the input buffer. This may become a problem when you do unformatted input, like getline(), which reads input until a newline character is found. This happening, it will stop reading immediately, because of that \n that was left hanging there in your previous operation.
If you only have a single newline in the input, just doing
std::cin.ignore();
will work fine. It reads and discards the next character from the input.
But if you have anything else still in the input, besides the newline (for example, you read one word but the user entered two words), then you have to do
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
See e.g. this reference of the ignore function.
To be even more safe, do the second alternative above in a loop until gcount returns zero.
I had similar problems. The one downside is that with cin.ignore(), you have to press enter 1 more time, which messes with the program.
int main(){
.... example with file
//input is a file
if(input.is_open()){
cin.ignore(1,'\n'); //it ignores everything after new line
cin.getline(buffer,255); // save it in buffer
input<<buffer; //save it in input(it's a file)
input.close();
}
}
I know I'm late but I hope this is useful.
Logic is for taking one line at a time if the user wants to enter many lines
int main()
{
int t; // no of lines user wants to enter
cin>>t;
string str;
cin.ignore(); // for clearing newline in cin
while(t--)
{
getline(cin,str); // accepting one line, getline is teminated when newline is found
cout<<str<<endl;
}
return 0;
}
input :
3
Government collage Berhampore
Serampore textile collage
Berhampore Serampore
output :
Government collage Berhampore
Serampore textile collage
Berhampore Serampore
i think you are not pausing the program before it ended so the output you are putting after getting the inpus is not seeing on the screen right?
do:
getchar();
before the end of the program
The code is correct. The problem must lie somewhere else. Try the minimalistic example from the std::getline documentation.
main ()
{
std::string name;
std::cout << "Please, enter your full name: ";
std::getline (std::cin,name);
std::cout << "Hello, " << name << "!\n";
return 0;
}
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' );
This question already has answers here:
Need help with getline() [duplicate]
(7 answers)
Closed 7 years ago.
This is probably a very simple problem but forgive me as I am new.
Here is my code:
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
int main ()
{
string name;
int i;
string mystr;
float price = 0;
cout << "Hello World!" << endl;
cout << "What is your name? ";
cin >> name;
cout << "Hello " << name << endl;
cout << "How old are you? ";
cin >> i;
cout << "Wow " << i << endl;
cout << "How much is that jacket? ";
getline (cin,mystr);
stringstream(mystr) >> price;
cout << price << endl;
system("pause");
return 0;
}
The problem is that when asked how much is that jacket? getline does not ask the user for input and just inputs the initial value of "0". Why is this?
You have to be careful when mixing operator>> with getline. The problem is, when you use operator>>, the user enters their data, then presses the enter key, which puts a newline character into the input buffer. Since operator>> is whitespace delimited, the newline character is not put into the variable, and it stays in the input buffer. Then, when you call getline, a newline character is the only thing it's looking for. Since that's the first thing in the buffer, it finds what it's looking for right away, and never needs to prompt the user.
Fix:
If you're going to call getline after you use operator>>, call ignore in between, or do something else to get rid of that newline character, perhaps a dummy call to getline.
Another option, and this is along the lines of what Martin was talking about, is to not use operator>> at all, and only use getline, then convert your strings to whatever datatype you need. This has a side effect of making your code more safe and robust. I would first write a function like this:
int getInt(std::istream & is)
{
std::string input;
std::getline(is,input);
// C++11 version
return stoi(input); // throws on failure
// C++98 version
/*
std::istringstream iss(input);
int i;
if (!(iss >> i)) {
// handle error somehow
}
return i;
*/
}
You can create a similar function for floats, doubles and other things. Then when you need in int, instead of this:
cin >> i;
You do this:
i = getInt(cin);
Its because you have a '\n' left lying on the input stream from a previous call.
cin >> i; // This reads the number but the '\n' you hit after the number
// is still on the input.
The easiest way to do interactive user input is to make sure each line is processed independently (as the user will hit enter after each prompt).
As a result always read a line, then process the line (until you get familiar with the streams).
std::string line;
std::getline(std::cin, line);
std::stringstream linestream(line);
// Now processes linestream.
std::string garbage;
lienstream >> i >> garbage; // You may want to check for garbage after the number.
if (!garbage.empty())
{
std::cout << "Error\n";
}
Ignore some characters until line feed is reached.
cin.ignore(256, '\n')
getline (cin,mystr);