reading multiple lines from a file using getline? - c++

I am trying to read in the data in a names.txt file and output the full name and ideal body weight for each person. Using a loop to read the names and feet and inches of each person from the file.
The file reads:
Tom Atto
6
3
Eaton Wright
5
5
Cary Oki
5
11
Omar Ahmed
5
9
I'm using the following code for this:
string name;
int feet, extraInches, idealWeight;
ifstream inFile;
inFile.open ("names.txt");
while (getline(inFile,name))
{
inFile >> feet;
inFile >> extraInches;
idealWeight = 110 + ((feet - 5) * 12 + extraInches) * 5;
cout << "The ideal weight for " << name << " is " << idealWeight << "\n";
}
inFile.close();
when i run this im getting output:
The ideal weight for Tom Atto
is 185
The ideal weight for
is -175

Add this statement in while loop after reading the two extraInches value.
inFile.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
It ignores the '\n' after the second integer you read in while loop. You may refer: Use getline and >> when read file C++

You are running into problems because after the line
inFile >> extraInches;
is executed in the first iteration of the loop, there is still a newline character in the stream. The next call to getline simply returns an empty line. The subsequent call
inFile >> feet;
fails but you don't check whether the call was successful.
Couple of things I want to mention in relation to your problem.
Mixing unformatted input, using getline, and formatted input, using operator>> is fraught with problems. Avoid it.
To diagnose IO related problems, always check the state of the stream after an operation.
In your case, you can use getline to read lines of text, and then use istringstream to extract numbers from the lines.
while (getline(inFile,name))
{
std::string line;
// Read a line of text to extract the feet
if ( !(inFile >> line ) )
{
// Problem
break;
}
else
{
std::istringstream str(line);
if ( !(str >> feet) )
{
// Problem
break;
}
}
// Read a line of text to extract the inches
if ( !(inFile >> line ) )
{
// Problem
break;
}
else
{
std::istringstream str(line);
if ( !(str >> inches) )
{
// Problem
break;
}
}
idealWeight = 110 + ((feet - 5) * 12 + extraInches) * 5;
cout << "The ideal weight for " << name << " is " << idealWeight << "\n";
}

Related

C++ programming I/O

I am trying to take input from a text file containing 1000 records.
10
1 100
2 101
3 123
4 124
.
.
.
1000 1234
I am using the code below to take the input in three variables d=10 (first line of the text file, a contains all the numbers in first column and b contains all the numbers in second column.
The problem I am facing with this code is it takes the last half of the file as input the first half is ignored.
output:
500 3211
501 3212
502 22121
.
.
.
1000 1234
char fileName[20];
cout << "Enter input test file name: ";
cin >> fileName;
ifstream readFile; //object of input file stream
readFile.open(fileName); //open a file
//Check for an error
if (readFile.fail())
{
cerr << "Error Opening File" << endl;
}
string c, d,a,b;
getline(readFile, c);
for (int i=0; i<1000;i++)
{
getline(readFile, readLine);
istringstream split(readLine);
getline(split, a);
getline(split, b);
cout <<serverNum<<" "<<a<<" "<<b<<endl;
}
can someone suggest me why am I facing this
A better way would be this:
#include <iostream> // std::cout, std::endl
#include <fstream> // std::ifstream
using namespace std;
int main()
{
// open your file
ifstream input_file("test.txt");
// create variables for your numbers
int first_num, left_num, right_num;
// determine the first number in your file
input_file >> first_num;
// while there is a number on the left, put that number into left_num
while(input_file >> left_num)
{
// put the corresponding right number into right_num
input_file >> right_num;
// now you can work with them
cout << left_num << ' ' << right_num << endl;
}
// close the file
input_file.close();
return 0;
}
Edit:
#Syed the problem could be that your command line doesn't have enough buffering and just overwrites your previous 500 lines. Just go to your cmd, click the top left corner, go to settings, layout, and increase the buffer. The code works, it must be your console.
Also since you answered with a list containing floats, you might want to consider changing left_num and right_num from int to float or double.

C++: cin with white spaces to strings without getline function

I am in the middle of a college project which kind of looks like a students' database.
Each line of the text file follows this "model":
age ; full_name ; avg
I need to read the text file and store everything in a vector of structs and I could do that if the name was only one word.
Well, obviously, age is an int, avg is a double, but what about the full name?
I can't just use file >> full_name;, with full_name being a string because it would stop reading to it once it gets to a whitespace. The getline() function would store everything in one place so I am not sure what to do.
Please share your knowlegde with this young mind x)
As many others pointed out, you can use std::getline to read chars till a delimiter.
Consider this snippet of code as a starting point:
int age;
std::string name;
double average;
// ... Open the file which stores the data ...
// then read every line. The loop stops if some of the reading operations fails
while ( input >> age &&
std::getline(input, name, ';') && // consume the first ;
std::getline(input, name, ';') && // read the name
input >> average ) {
// do whatever you need with the data read
cout << "age: " << age << " name: " << name << " average: " << average << '\n';
}

C++ read in a line of string as ints?

I am trying to read a line of string characters with numbers (e.g "30 40 50 20") and put them into a vector. I also need to avoid empty space and newlines. But when I read the input, it doesn't see the string "30", it sees the characters "3" and "4".
void Input() {
getline(cin,line, '\n');
for (int i = 0; i < line.length(); i++) {
if (! (isspace(line[i]))) {
cout << line[i] << ", ";
scores.push_back(line[i]);//(atoi(input));
}
}
cout << scores.size() << "! ";
}
A line like "30 40 50" won't give a vector size of 3, it will give a size of 6.
What are the optimal ways to get around this issue?
EDIT: I should have clarified in the original message that this is for a challenge, in which I am unable to include the string stream library in the original case.
I think you're doing the right thing grabbing the whole line before parsing, otherwise you get into a bit of a pickle. But you do actually have to do some parsing. Right now you're just pulling out individual characters.
The following isn't optimal but it'll get you started — continue using formatted stream extraction, but isolated to this line from the file.
So:
void Input()
{
getline(cin, line, '\n');
istringstream ss(line);
int val;
while (ss >> val)
scores.push_back(val);
cout << scores.size() << "! ";
}
Read the line and put into a std::istringstream, then read as "normally" using the >> operator from the string stream.
Putting the line into a std::istringstream and extracting the numbers from that is the best way.
Here's an alternative to a manual loop using the standard library:
std::istringstream numbers(line);
std::copy(std::istream_iterator<int>(numbers),
std::istream_iterator<int>(),
std::back_inserter(scores));
It is probably best to take advantage of an input stringsteam, example: http://www.cplusplus.com/reference/sstream/stringstream/stringstream/.
The extraction operator allows you to parse data from the stream to some variable of datatype T. Another advantage of input stringstreams is the ability to query whether the pass was successful, and in your case ignore whitespace characters by setting the skipws format flag.
Example:
int main () {
std::istringstream ss("30 40 50");
float val = 0.0f;
while( ss >> std::skipws >> val )
{
std::cout << val << "\n";
}
return 0;
}
Out: 30 40 50

problem with getline() function

I am a beginner at C++ and I'm trying to use the getline() function for the first time.
When I wrote this code, 2 errors showed up.
What is this code supposed to do?
It is supposed to read 4 numbers from read.txt then calculate it to find the mean and write the output in output.txt.
The 4 numbers (in read.txt) are all on separate lines like this:
6
12
15
19
Here is the code:
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main ()
{
ifstream readFile;
ofstream sendFile;
readFile.open ("read.txt");
sendFile.open ("output.txt");;
float mean;
int num, num2, num3, num4;
getline(readFile, num), getline(readFile, num2), getline(readFile, num3), getline(readFile, num4);
readFile >> num >> num2 >> num3 >> num4;
sendFile << "1. The mean of " << num << ", " << num2 << ", " << num3 << ", and " << num4 << "is " << (num + num2 + num3 + num4) / 4;
readFile.close();
sendFile.close();
system ("PAUSE") ;
return 0;
}
Here are the errors:
IntelliSense: no instance of overloaded function "getline" matches the argument list 20
IntelliSense: too few arguments in function call 20
std::getline() takes two arguments: a stream and the std::string object into which to read the next line (and an optional third argument, the delimiter). You are passing an int instead of a std::string.
You should probably use the ordinary formatted extraction:
if (readFile >> num >> num2 >> num3 >> num4) {
// extraction succeeded!
}
else {
// extraction failed; handle the error here
}
getline reads into std::string, it can't read into ints. Just use readFile >> num >> num2 >> num3 >> num4; as you already have, and delete the line with getlines.
On another note, you don't need to close the files explicitly here as the destructors of file stream objects will take care of that for you.
std::getline is a useful tool for reading a single line of text or reading text up to a specific character, and writing it to a std::string where it can then be read further. By default it uses newline i.e. '\n' as the delimiter but you can change this.
With regards to using a stream to read in a number of integers then output their mean, why not just read to the end of the file, thus:
int count = 0, total = 0, num;
while( instr >> num )
{
++count;
total += num;
}
float mean = (count > 0 ) ? total / num : std::numeric_limits<float>::quiet_NaN();
outstr << mean;
You could make that a function, taking istream & instr and ostream & outstr
Suppose now we want to change that to read multiple lines, each with numbers delimited by space or tab. In our output we write all the means on their own line.
Now do something like this:
std::string line;
while( std::getline( bigInStr, line ) )
{
std::istringstream iss(line);
outputMean( iss, outstr );
outstr << '\n';
}
although you might want to not actually output the NaN but just leave that line blank in the output. A function calculating the mean probably would want to use a NaN as a return value if it has to return a float. We could calculate the variance, skewness and kurtosis at the same time if we want whilst iterating.
Then you would output these as multiple values on the line and you would have to pick your own delimiter. My own preference is to use tab ('\t') in this situation.
_

input from txt file to arrays

I have a text file with a line like:
James Dean 10 Automotive 27010.43
and I need to read that file and put each of the 4 above into arrays.
char nameArray[MAX][NAME_MAX];
int yearArray[MAX];
char departmentArray[MAX][DEP_MAX];
double payArray[MAX];
while(i < MAX && infile) {
infile.getline(nameArray[i], 20);
infile >> yearArray[i];
infile.getline(departmentArray[i], 15);
infile >> payArray[i];
cout << nameArray[i] << " " << yearArray[i] << " " << departmentArray[i] << " " << fixed << setprecision(2) << payArray[i] << endl;
i++;
}
The code is cut down just to give you an idea of what I am trying to do, but when I run this, I get something like:
James Dean -858993460 -92559631349317830000000000000000000000000000
000000000000000000.00
Thanks for the help.
==== Edit ==========================================
I changed from getline to get, thanks for that. I have to use get and not >> because some of the lines I am reading in are more than just "James Dean", they are up to 20 char long...ex: "William K. Woodward" is another one.
So, if I just use get, then it reads the first line in fine, but then I get the same messed up text for the second line.
Here is the code:
infile.get(nameArray[i], 20);
infile >> yearArray[i];
infile.get(departmentArray[i], 15);
infile >> payArray[i];
The getline functions takes an input stream and a string to write to. So, two getline calls read in two lines. Your input mechanism is broken. Either, use getline or the stream extraction operator (i.e. >>) but not both.
If you plan to use getline you need to parse the string (which is effectively one line of input) into tokes, and then store them in appropriately typed arrays. The second and fourth tokens are numbers, hence you will need to convert these from string to int or double.
The operator >> approach:
string name, surname;
int year;
double pay;
while (infile) {
infile >> name >> surname >> year >> department >> pay;
namearray[ i ] = name + " " + surname;
// ...
payarray[ i ] = pay;
++i;
}
The getline approach:
string line;
while (getline(infile, line)) {
parse(line, tokens);
namearray[ i ] = token[ 0 ] + " " + token[ 1 ];
// ...
payarray[ i ] = strTodouble(token[ 4 ]);
++i;
}
// parse definition
void parse(string line, vector<string>& token) {
// roll your own
}
double strToDouble(string s) {
// ...
}
I dont see where you define infile but I will assume that it is an ifile . In that case you should use it the same way u use cin to get input.
Why do you do a getline () ?
That function will stop only at an '\n' char or at an EOF char. So it means, you start reading the int after the end of the line, some random data.
Correct me if i'm wrong, but are there 20 or 19 characters in that first string (James Dean) before the number (10) ?