I want cin to read until '\n' but I cannot use getline - c++

I have a text file in the following format:
info
data1 data2
info
data1 data2 data3 data4...
The problem is: the count (and length) of the data may be very large and cause run-time problems when getline() is used. So I cannot read the entire line into a std::string. I tried the following:
for(int i=0; i<SOME_CONSTANT ; i++){
string info, data;
cin >> info;
while(cin.peek() != '\n' && cin >> data){
// do stuff with data
}
}
However cin.peek() did not do the trick. The info is read into data in the while loop and program messes things up. How can I fix this?

You can try reading character by character.
char ch;
data = "";
cin >> std::noskipws;
while( cin >> ch && ch != '\n' ) {
if ( ch == " " ) {
// do stuff with data
data = "";
continue;
}
data += ch;
}
cin >> std::skipws;

Use std::istream::getline instead of std::getline. You can choose your buffer size and delimiter.

Related

while Infinite loop in function

bool isDigital(char c) { return ('0' <= c && c <= '9'); }
void DigitalToken( char digitToken[50], char ch ) {
digitToken[0] = ch;
char input = '\0';
cin >> input;
int i = 0;
while ( ( input != ' ' ) && ( input != '\t' ) && ( input != '\n' ) ) { // got a infinite loop
i++;
digitToken[i] = input;
cin >> input;
} // while ( input != ' ' && input != '\t' && input != '\n' )
} // DigitalToken()
int main() {
char ch = '\0';
while ( cin >> ch ) {
if ( isDigital(ch) ) {
char* digitToken = new char[50]();
DigitalToken(digitToken, ch);
cout << digitToken;
delete[] digitToken;
} // else if
} // while
} // main()
I don't understand why I got a infinite loop in DitgitalToken function.
When I input 123, it should be output 123.
I watched it for a long time, but I still don’t know why and how to fix it.
Instead of cin >> input; use input = cin.get();.
You have to be careful while using cin with characters or strings. It treats spaces, tabs, newlines as end of the input and hence do not treat them as input themselves.
Your program blocks in the while loop on cin >> input; after it read "123". As #Arty suggested use cin.get() instead as whitespace is stripped by default. You can also use cin >> noskipws; prior to executing cin >> input;. See skipws.

Why I can't get the correct output when moving data from text file to array

I am getting weird output when I try to move information from textfile to array, anyone can help me to figure the problem? Much appreciate for that.
Information in textfile
here is my code
#include <iostream>
#include <windows.h>
#include <fstream>
using namespace std;
int main()
{
ifstream indata;
string name[10] , id[10] , gender[10];
int i = 0 , age[10];
double weight[10] , height[10];
indata.open("Staff.txt");
while(!indata.eof())
{
if(indata.eof()==true)
break;
else
{
getline(indata,name[i]);
indata >> id[i] >> gender[i] >> age[i] >> weight[i] >> height[i];
cout << name[i] <<" "<< id[i] <<" "<< gender[i] <<" "<< age[i] <<" "<< weight[i] <<" "<<
height[i] <<endl;
i++;
}
}
system("pause");
return 0;
}
Here is the output
The last formatted extraction of the iteration (indata >> height[i]) leaves the newline character in the buffer, so when the next iteration runs the std::getline will see that character, extract it and stop reading further characters. This messes up further input operations leading the output you see.
A quick fix would be to remove any leading whitespace before running std::getline. You also are incorrectly using the eof() method. Good practice is to run the input operation first and then check if it succeeded with fail().
So this is what it should look like:
while (std::getline(indata >> std::ws, name[i]) &&
indata >> id[i] >> gender[i] >> age[i] >> weight[i] >> height[i]) {
// ...
}
indata >> std::ws removes leading whitespace and putting the input operation in the condition of the while loop will invoke the inner boolean operator which calls fail().

How can I get the character '\n' from input file?

I am trying to get input data from a txt file on Linux / Mint. So, after compiling the code I run the following command: ./a.out output.txt
I need to fill a two-dimensional array but like a jagged array (the number of columns in each row is different). So I want to split it by looking character what is read from file. If the character is '\ n', I want to fill the second line. But I guess I can not read the '\ n' character. I hope I can explain the problem.
I'm writing the code, maybe it will be more clearer.
my input.txt file is:
my c++ code part is for getting input:
for (int i = 0; i<n; i++) {
char ch;
cin >> ch;
int j = 0;
while (ch != '\n') {
arr[i][j] = ch;
cin >> ch;
j++;
}
}
I want to that, if the character is equals the '\n' then program goes on to fill the array to next row.
arr[0][0] = 'a';
arr[0][1] = 'f'
arr[0][2] = 'h'
arr[1][0] = 'b'
arr[1][1] = 'e'
arr[1][2] = 'g'
arr[2][0] = 'c' .......)
When you do cin >> ch it will skip whitespace, which includes spaces, tabs and newline characters. Perhaps, you need to read entire lines using std::getline, and then process each line separately.
For example:
#include <iostream>
#include <sstream>
#include <string>
using namespace std;
int main()
{
char ch;
std::string line;
int ln = 0;
while (getline(cin, line)) // read entire line
{
istringstream is;
is.str(line);
while (is >> ch) // now read individual chars from that line
cout << "line: " << ln << " char: " << ch << endl;
ln++;
}
}
And your loop should be something like this:
std::string line;
for (int i=0; i<n; ++i)
{
char ch;
if (!std::getline(cin, line))
break;
std::istringstream is;
is.str(line);
for (int j=0; is >> ch; ++j)
arr[i][j] = ch;
}
You omitted details on how you declare your arr, but it doesn't seem like the code you've shown would handle it properly. Perhaps, it would be better to use vectors:
std::vector<std::vector<char> > arr;
std::string line;
char ch;
while (std::getline(cin, line)) // cin should probably be replaced with ifstream
{
std::istringstream is;
is.str(line);
arr.push_back(vector<char>());
for (int j=0; is >> ch; ++j)
arr.back().push_back(ch);
}

C++ while loop Issues

I am trying to read lines of a file (cityName, hiTemp, loTemp) into a struct array. I was able to use >> to read the first several lines until I hit a city with a space in it's name.
I then tried using getline() to read the lines, but then my while loop stopped working.
I have no clue why this would happen.
int LoadData()
{
int count = 0;
string path;
cout << "Specify the input file path: ";
ifstream inFile;
cin >> path;
inFile.open(path.c_str());
if (!inFile.is_open())
{
cout << "Error - could not open file: " << path;
return (-1);
}
else
{
while (!inFile.eof())
{
cities[count].city = "";
getline(inFile, cities[count].city);
if (cities[count].city.length() == 0)
{
break;
}
char comma;
inFile >> (cities[count].high) >> comma >> cities[count].low;
cout << cities[count].city << " " << cities[count].high << " " << cities[count].low << endl;
count++;
}
inFile.close();
inFile.clear(std::ios_base::goodbit);
return count;
}
}
while (!inFile.eof())
For getting every line in the file, you should use:
while(getline(inFile, cities[count].city)) {
// ...
This works and is recommended over using the .eof() method.
You can also use this in your if-statement:
if (!getline(inFile, str))
break;
As an aside, you can read this site:
Why is “while ( !feof (file) )” always wrong? - StackOverflow post
It gives insight into why using the .eof() is not the preferred method to use in a while loop to check whether the end-of-file has been reached.
Use getline as loop condition. You can also replace the second read with a getline too and use a stringstream to parse it.
#include <sstream>
// ...
while(getline(inFile, cities[count].city)) {
if (cities[count].city.empty()) break;
// read next line with high and low values
string str;
if (!getline(inFile, str)) break; // error in file format
stringstream ss(str);
char comma;
ss >> cities[count].high >> comma >> cities[count].low; // parse it
}

Trying to use int in getline

cout << "How many questions are there going to be on this exam?" << endl;
cout << ">>";
getline(cin, totalquestions);
This small piece of code comes from a function in a class that I have created and I need totalquestions to be an int so that it can run through a for loop and keep asking the total amount of questions that I have asked.
question q;
for(int i = 0; i < totalquestions; i++)
{
q.inputdata();
questions.push_back(q);
}
Where does this piece of code comes to play? Does anyone have any idea to make this work?
Use
cin >> totalquestions;
Check the errors too
if (!(cin >> totalquestions))
{
// handle error
}
getline reads an entire line as a string. You'll still have
to convert it into an int:
std::string line;
if ( !std::getline( std::cin, line ) ) {
// Error reading number of questions...
}
std::istringstream tmp( line );
tmp >> totalquestions >> std::ws;
if ( !tmp ) {
// Error: input not an int...
} else if ( tmp.get() != EOF ) {
// Error: unexpected garbage at end of line...
}
Note that just inputting std::cin directly into
totalquestions does not work; it will leave the trailing
'\n' character in the buffer, which will desynchronize all of
the following input. It's possible to avoid this by adding a
call to std::cin.ignore, but this would still miss the error
due to trailing garbage. If you're doing line oriented input,
stick with getline, and use std::istringstream for any
necessary conversions.
Do this:
int totalquestions;
cout << "How many questions are there going to be on this exam?" << endl;
cout << ">>";
cin >> totalquestions;
Getline is meant for grabbing chars. It can be done with getline(), but cin is much easier.
One of the better ways of getting an int from user :-
#include<iostream>
#include<sstream>
int main(){
std::stringstream ss;
ss.clear();
ss.str("");
std::string input = "";
int n;
while (true){
if (!getline(cin, input))
return -1;
ss.str(input);
if (ss >> n)
break;
std::cout << "Invalid number, please try again" << std::endl;
ss.clear();
ss.str("");
input.clear();
}
Why is it better than using cin >> n ?
Actual article explaining why
As for your question, use the above code to get the int value and then use it in the loop.
Don't use getline:
int totalquestions;
cin >> totalquestions;