Problems reading first line from file after 'getline' - c++

After inputting getline, the first row of numbers in my input file are ignored and the program starts at the second line until the end.
Here's the code:
while (!file.eof())
{
getline(file, lineBuffer);
if(lineBuffer.length()==0)
{
continue; //ignore empty lines
}
else
{
// file.open("test.txt");
while (file >> A >> B >> N)
{
for(int count=1; count<=N; count++)
{
if(count%A == 0 && count%B == 0) { cout << "FB "; }
else if(count%A == 0) { cout << "F "; }
else if(count%B == 0) { cout << "B "; }
else { cout << count << " "; }
}
cout << endl;
}
}
}
The input file contains 3 rows of integers and only the second line and third like are processed. I've looked this up extensively, but no one has mentioned a case similar to mine. Usually they deal with people trying to get user input after a getline function. Any ideas would be greatly appreciated.

getline(file, lineBuffer) reads a line from file and stores it in lineBuffer. If you want to use it, you should then process lineBuffer instead of reading from file (where the first line will already be skipped). To make it work, simply remove all code outside of the inner while. This will read from the file 3 numbers at a time, stopping when extracting one of them fails.

Is the above code real or is it an example?
If it is real, you don't need to skip th eempty lines. The operator>> will skip the whitespaces for you.
The following code without any lineskipping performs just the same reading of "A B N" lines:
// outer loop is not needed, either remove it, or include error checking
// while (!file.eof() && !file.fail())
{
while (file >> A >> B >> N)
{
for(int count=1; count<=N; count++)
{
if(count%A == 0 && count%B == 0) { cout << "FB "; }
....
If for some reason you cannot remove the getline at all, remember that getline reads the line ALWAYS (well, unless the streampointer reached its end). This means that your code skips the empty lines, then reads first nonempty line, notices that the line is not empty and breaks the loop. Note that it has read the line, hence, your first-line-of-data now is in the linebuffer, and not in the stream anymore. Now you have to either unget the whole line (if your stream supports it) or rewind the stream by the line's length (if your stream supports it) or - just read the data from the line - for example using istringstream class.
In general, mixing getline and operator>> is doable but tricky, (especially when you first read via >> and then want to skip a 1 or 2 lines), as they behave a little differently in terms of buffering and whitespace-handling. If you really want that, search for this subject - there are lots of examples how to sync them.

Related

How to skip empty lines without string class

In the following code I can't use the std::string class.
I'm trying to read a file that has empty lines, and I want to ignore the empty lines when I encounter them.
I've tested out some ideas using a simplified example and a made-up text file containing empty lines.
int main() {
ifstream fin;
fin.open("test.txt");
if(fin.fail()){
cout << "Input file fail.";
exit(-1);
}
char line[10];
while(!fin.eof()){
fin.getline(line, 10);
if(line[0] == '\n')
cout << "skip" << "\n";
else
cout << line << "\n";
}
}
I've also tried things like strlen(line) == 1, but nothing worked so far.
What is the problem?
std::getline() already takes care of the '\n' character (it will be discarded), line[0] would contain '\0' in the case of an empty input.
Just compare for '\0' instead of '\n':
if(line[0] == '\0')
cout << "skip" << "\n";
else
cout << line << "\n";
I've also tried things like strlen(line) == 1
If so, shouldn't that have been strlen(line) == 0 for an empty line?
There are two problems with your code. The first is that your loop isn't correct. You have to check the result of the getline() call, not eof(). Please see Why is iostream::eof inside a loop condition considered wrong. That restructured loop becomes:
while (fin.getline(line, 10)) {
...
}
Next, when you read a line with getline() (and 10 seems really short for a line), the delimiter will not be part of the body. There will not be a \n in line when you're doing reading. You'll just have an empty string. So the right way to discard empty lines is:
while (fin.getline(line, 10)) {
if (line[0]) {
// we have contents!
}
}
Or really, std::string is just way better:
std::string line;
while (std::getline(fin, line)) {
if (!line.empty()) {
....
}
}
std::getline() discards the delimiter \n. But you might also want to consider that on some systems lines may be delimited by \r\n.

How to read data from stdin, for a given number of test cases in C++

This might sound silly, but it's my first time solving programming contests on line. The problem is usually described as:
Input:
First line indicates the number of test cases t.For the next 't' lines the data is entered.
I've written the following program (with the correct headers included):
vector<string> read_strings(int t_cases) {
vector<string> ip_vec;
string line, str;
int cnt = 0;
while (cnt != t_cases-1) {
std::getline(std::cin, line);
++cnt;
}
std::istringstream iss(line);
while (iss >> str) {
ip_vec.push_back(str);
}
return ip_vec;
}
But this program always gets stuck in an input loop. I've also tried to parse the line as soon as it's entered by putting iss in the first while loop. If anyone could provide me a pointer on how to solve this problem, I will be able to finally test the rest of the program.
Thanks.
You need to add the lines to the vector as they are read. The first while loop is reading through all the test cases, but is not saving them somewhere. Then next while loop tries to reads line, which is the last test case read. Try the following:
vector<string> ip_vec;
string line, str;
for (int cnt = 0; cnt < t_cases; cnt++) {
std::getline(std::cin, line);
ip_vec.push_back(line);
}
Since you're starting to learn how programming contests work, I wouldn't recommend you to store all the input given. In general, you can store the number of inputs t and for each test case, the program outputs the answer for that test before reading the next test case. For example:
for (int i = 1; i <= t; i++) {
cin >> input;
// Some computations specific to the problem
cout << output << endl; // Pay attention on how the problem wants the output to be printed.
}
If the problem doesn't give you the number of test cases, you can simply change the loop to:
while (cin >> input) {
// Computations...
cout << output << endl;
}
It's usually how I solve problems from programming contests.
EDIT: As noted by #AnkitKulshrestha, if there's more than one input that you have to read for each test case, you can simply read them like this (with three inputs, for example):
while (cin >> a >> b >> c) {
// Computations...
cout << output << endl;
}

How to read in each line from a file c++ [duplicate]

This question already has answers here:
Why is iostream::eof inside a loop condition (i.e. `while (!stream.eof())`) considered wrong?
(5 answers)
Closed 9 years ago.
I have two questions. I'm trying to read in line by line from a file but I can't get each line to go individually to where I can use it. Also, I can't figure out how to ask the user for their file name and than use what they type in the program. All the examples I've found just has the name of the file in the code already and just putting it in cin doesn't seem to work. I am trying to separate two different types of lines, so for example, abcd and 1234. If the first value is a letter do case a, if it's a number, do case b. But all I've managed to do is have getline have everything in one so I can't actually separate it. Anyone have any advise?
string x;
cout << "Enter your file: " ;
cin >> x
string line;
ifstream myfile;
myfile.open (x);
while(!myfile.eof())
{
getline(myfile,line, ' ');
}
cout << line << endl;
There is nothing wrong with your cin statement for reading the file name. As long as the file exists, what you have will open the file. Though, you can add some error checking to it:
std::string x;
std::cout << "Enter your file: " ;
if (!(std::cin >> x))
{
std::cerr << "Invalid input!" << std::endl;
return -1;
}
std::ifstream myfile(x);
if (myfile.is_open())
{
std::string line;
while (myfile >> line)
{
std::cout << line << std::endl;
}
}
else
{
std::cerr << "Unable to open file: " << x << std::endl;
return -1;
}
Note the proper while condition (do not use eof() for std::istream while conditions!). Additionally, if you are separating on whitespace, there is no need to use std::getline - operator>> will do the same thing.
If you want to do different things based on what the value of line is, then check the string. For example:
if (line[0] >= '0' && line[0] <= '9')
// do something with digits
else
// do something with non-digits
First, don't put eof() in while condition. It's wrong because iostream::eof will only be set after reading the end of the stream. It does not indicate, that the next read will be the end of the stream. Check out this post: Why is iostream::eof inside a loop condition considered wrong?
To separate, you can check the first char of the line is whether within ['0', '9'] or not.
Like this:
while( getline(myfile, line) )
{
if (line[0]>='0' && line[0]<='9')
{
// start with a number (do case b)
}
else
{
// other (do case a)
}
}

getline is not waiting for the input

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'.

cin.getline not executing c++

For some weird reason my input line cin.getline(oneLine, 80); is completely ignored when I put it in this else if block. I can't understand why because when I move it somewhere else in the program, it works.
else if (choice == "user-id")
{
cout << endl << "Enter a full name e.g. John Smith ";
char oneLine[80];
cin.getline(oneLine, 80);
cout << oneLine;
}
Here's the rest of my code. I'm new to C++ so I'm sure a lot of my conventions may be questionable at best.
int main( )
{
while (true)
{
int pause;
string choice = "proceed";
string nameGiven;
string userIdGiven;
string result;
using namespace std ;
while ((choice != "name") && (choice != "user-id"))
{
cout << "Would you like to search for a name or user-id? ";
cin >> choice;
if ((choice != "name") && (choice != "user-id"))
cout <<"Please enter a valid choice (name or user-id)" << endl;
}
if (choice == "name")
{
string dataType = "int";
while (true)
{
cout << endl << "Enter a valid user id (4 digit maximum) ";
cin >> userIdGiven;
if (valid(userIdGiven))
break;
else
cout << endl << "Not a valid number. " << endl;
continue;
}
result = findData(userIdGiven, dataType);
cout << "name: " << result;
}
else if (choice == "user-id")
{
cout << endl << "Enter a full name e.g. John Smith ";
char oneLine[80];
std::getline(oneLine, 80);
cout << oneLine;
}
string ans;
cout << endl << "Would you like to play again? (yes/no) " << endl;
cin >> ans;
if ( (ans == "yes") || (ans == "Yes") || (ans == "Y") || (ans == "y") )
continue;
else
break;
cin >> pause;
}
return 0;
}
Your std::cin object is in a bad state (std::cin.good() == false) from a previous input operation. For example, you might have tried to read a number, but there were only nun-numeric characters in the input buffer.
Always check for input success before continuing using a std::istream.
Note: Don't use the old input functions operating with char*, as they are more complicated and less safe to use than the new ones operating on std::string. In your case, use std::getline(std::istream&, std::string&, char = '\n').
twsaef's comment's substantively correct... you're streaming a string into choice, which consumes the characters up until but excluding the next whitespace character - you're probably typing a newline to terminate your input, so it's left in the buffer. Then you use getline which sees that newline and reads an empty string.
Easiest solution is to call getline() to read the initial string too, then check if choice is "name\n" or "user-id\n". Better - write a "trim" function to remove the whitespace from the line before comparison (boost string library has this already). Otherwise, you could use read and ignore characters from std::cin until you get a '\n'. Or even read a line then put in into a stringstream and read a string from there.... Lots of choices.
And, please check your stream state! Try to use:
if (std::cin >> x)
// x was parsed from stream... use it
else
// print an error so you know where things failed!
FWIW, I guessed what the problem would be (it's stupidly common) before seeing the update, and chuckled to myself at the other guesses (although they make very good points even if they missed the OP's problem).
The line of code is working correctly and as advertised. It doesn't happen to be working the way you want it to.
When you read from std::cin, that does not pause the program and wait for input. What causes the pause is the lack of sufficient input data for the read operation.
Input is fed to your program a line at a time. Remember, the console window is a program, too. It is responsible for translating the user's key-presses into text characters (bytes, really), handling things like the backspace key, and gathering it all up into lines.
So say you read an int with operator>>, and then read a line with getline. The program will not see an int until the user hits the Return key, because that triggers the console to feed a line of input to your program.
operator>> will skip leading whitespace, read the integer, and leave trailing whitespace alone. Newline characters are whitespace. There is a newline character in the input (at the end of the line, obviously).
getline() will not skip any leading whitespace, and read until the next newline. The very next character happens to be a newline, so getline() happily reads an empty line and the program proceeds with that.
So how do you fix that? Chances are, if you're reading all your input from cin, that you want the program to pause every time you come to a reading operation. The way to do that is to ensure that there is never any available data at that point, and the way to do that is to read everything that's available - i.e., the whole line - every time that you read something.
So, always read a full line from cin. As noted by wilx, please use the free function std::getline for this. Do not use the .getline member function of the stream. Use std::string to represent strings of text. That's what it's there for. It will make your life much, much easier. That also means that if you're expecting an integer and the user types "76 trombones", you get rid of the "trombones" data (and can decide whether you want to just throw it away, or yell at the user and make him re-enter a number without any funny commentary).
But then what? You just have a string, where you may have wanted an int. Fortunately, there is a simple solution for that. We can treat the string as a source of stream data, using the standard library class std::stringstream. We just construct a stringstream from the string, and then use it just like std::cin - i.e. we can read from it with operator>>, check the stream state to see if reading was successful, etc.
As noted by sbi, always check whether reading succeeded! If you try to read an int and the stream contains text like "hi mom", then (a) the int variable will not be altered (so if it was uninitialized it is still uninitialized, a very dangerous state to be in), and (b) the stream will go into a "failed" state and will not read any more until you clear it, and (c) even if you clear it, the data will still be there, which can trigger an infinite loop if you're not careful.
Fortunately, with the separate stringstream, we avoid all kinds of complications. If reading fails, then all those things happen to the stringstream object - not to std::cin. The getline operation will always succeed on std::cin unless perhaps the user explicitly indicates an end-of-file (control-D character on Linux, or control-Z on Windows). We can easily check if the stringstream is in the failed state, loop and just create another one - the old one will automatically get cleaned up.
We can even make a helper function like:
template <typename T>
// Attempt to read into to_read, and return whether successful.
bool read_primitive_from_input(std::istream& input, T& to_read) {
std::string line;
std::getline(std::cin, line);
std::istringstream iss(line);
return iss >> to_read;
}
std::stringstream is provided by the standard library header <sstream>. std::string comes from <string>, of course.