reading in strings and doubles - c++

I'm having an issue reading in a string from a file and then a double from a file afterwards. My professor advised me to put a special getline after each input line, but it hasn't worked and I've deduced that this is the issue with the program. Is there a simpler way to take in doubles?
example of the input file is:
John Smith
019283729102380
300.00
2000.00
Andrew Lopez
293481012100121
400.00
1500.00
the code reads:
while(! infile.eof())
{
getline(infile,accname[count],'\n');
getline(infile, refuse, '\n');
getline(infile,accnum[count],'\n');
getline(infile, refuse, '\n');
infile>>currbal[count];
getline(infile, refuse, '\n');
infile>>credlim[count];
getline(infile, refuse, '\n');
count++;
}

EDIT: Updated in response to OP's clarification.
Based on the sample you provided, this should work:
while(1) {
std::string s1;
if(!std::getline(infile, s1))
break;
std::string s2;
if(!std::getline(infile, s2))
break;
double d1, d2;
if(!(infile >> d1 >> d2))
break;
accname[count] = s1;
accnum[count] = s2;
currball[count] = d1;
credlim[count] = d2;
count++;
}
This code will work for input like:
Adam Sandler
0112233
5 100
Ben Stein
989898
100000000
1
But it won't work for input like:
Adam Sandler
0112233
5 100
Ben Stein
989898
100000000
1

I think Rob Adams's, response has a minor bug when parsing multiple records. After extracting d2 for the first time, the example input stream will contain \nBen Stein\n989898\n100000000\n1, therefore the next call to std::getline() will extract an empty string instead of Ben Stein. So it seems necessary to consume an empty string at the end of each while loop iteration.
I think the following code sample provides a fix:
#include <iostream>
#include <sstream>
int main(int argc, char** argv) {
using std::stringstream;
stringstream infile(stringstream::in | stringstream::out);
infile << "John Smith\n";
infile << "019283729102380\n";
infile << "300.00\n";
infile << "2000\n";
infile << "Andrew Lopez\n";
infile << "293481012100121\n";
infile << "400.00\n";
infile << "1500.00\n";
std::string account_name;
std::string account_number;
double current_balance;
double credit_limit;
int count = 0;
while (std::getline(infile, account_name) &&
std::getline(infile, account_number) >> current_balance >>
credit_limit) {
std::cout << account_name << std::endl;
std::cout << account_number << std::endl;
std::cout << current_balance << std::endl;
std::cout << credit_limit << std::endl;
/*
accname[count] = account_name;
accnum[count] = account_number;
currball[count] = current_balance;
credlim[count] = credit_limit;
*/
count++;
// Consume the leading newline character, which seprates the credit limit
// from the next account name, when infile contains multiple records.
//
// For example, after consuming the record for John Smith, the stream will
// contain: "\nAndrew Lopez\n293481012100121\n400.00\n1500.00\n". If you
// don't consume the leading newline character, calling std::getline() to
// parse the next account name will extract an empty string.
std::string blank;
std::getline(infile, blank);
}
return 0;
}

string str;
while(!infile.eof())
{
getline(infile, accname[count]);// you do not need '\n' it will always read to
// end of the line
getline(infile, accnum[count]);
getline(infile, str);
currbal[count] = atof(str.c_str());
getline(infile, str);
credlim[count] = atof(str.c_str());
count++;
}
\*
for the file
John Smith
019283729102380
300.00
2000.00
Andrew Lopez
293481012100121
400.00
1500.00
*\

Related

Could you please verify if my code is correct for saving string to struct?

I am trying to file input information from a .txt file that has three inputs i.e(Mike Jones 60) and inserting them into a structure C++ to use for my output to screen.
struct Person {
string name;
int age;
};
void addData()
{
Person aPerson;
char fileName[80];
cout << "Please enter the file name: ";
cin.getline(fileName, 80);
//string fullName;
ifstream fin(fileName);
string tmp;
stringstream ss;
while (!fin.eof()) {
getline(fin, aPerson.name);
aPerson.name = tmp;
getline(fin, tmp);
ss << tmp;
ss >> aPerson.age;
ss.clear();
getline(fin, tmp);
ss.clear();
cout << aPerson.name << aPerson.age << endl;
}
}
This code will read data in this format:
Joe Bloggs
42
Franziska von Karma
23
Jeff Jefferson
84
Is that what your input data looks like?
If it's one line per person, and each person has exactly two words in their name, you can use the third parameter of getline to set a custom delimiter - instead of reading the whole line, it will read until it gets to a space.
Joe Bloggs 42
Jeff Jefferson 84
Amy Anderson 57
To process this data:
…
while (!fin.eof()) {
string firstname;
getline(fin, firstname, ' ');
string surname;
getline(fin, surname, ' ');
aPerson.name = firstname + " " + surname;
string age;
getline(fin, age);
ss << age;
ss >> aPerson.age;
cout << aPerson.name << aPerson.age << endl;
ss.clear();
}
If you can get the data in Comma-Separated Data format, or tab-separated, or anything-that's-not-a-space-separated, you can use that delimiter and extract the data in two steps not three.

Reading Comma Delimited Text File Into Array

I am trying to write a program in C++ that emulates a college enrollment system, where the student enters their ID, and the program searches a text file for their information, and loads a struct based on the text file. I have gotten to a point where I am having trouble getting their enrolled courses into the struct's array. Using the getline function, using the ',' as the delim will also carry over the next line until the next comma. What would be the correct algorithm for this?
This is the file setup that contains fake student information:
918273645,Steve,Albright,ITCS2530,MATH210,ENG140
123456789,Kim,Murphy,ITCS2530,MATH101
213456789,Dean,Bowers,ITCS2530,ENG140
219834765,Jerry,Clark,MGMT201,MATH210
(Bullets added for layout; not in the file)
For example, the user enters "123456789" for their ID, and Kim Murphy's information is then read. Upon the first iteration of getline, "ITCS2530" is read and put into the variable, and is then loaded into the struct; no problem there. However, the last course in the list has the newline character before the next comma, so the next iteration reads "MATH101/nl213456789" and puts the entire string into the variable and tries to load that into the struct.
The first column is their ID, then their First name, last name, and then their currently-enrolled courses after that. Notice that the number of enrolled courses can vary.
Here is the code that I am currently working on:
student login()
{
string ID;
student newStudent;
string enrolled;
int i = 0;
while (true)
{
cout << "Enter Student ID: ";
cin >> newStudent.ID;
cout << endl;
if (newStudent.ID.length() == 9)
break;
else
cout << "That ID is invalid - IDs are 9 digits" << endl;
}
ifstream inFile;
ofstream outFile;
inFile.open("registration.txt");
if (inFile.is_open())
//Check if file is open
{
while (!inFile.eof())
//While not at end of file
{
getline(inFile, ID, ',');
//Search for ID
if (ID == newStudent.ID)
{
getline(inFile, newStudent.fName, ',');
//Assign fName and lName
getline(inFile, newStudent.lName, ',');
while (enrolled != "\n")
{
getline(inFile, enrolled, ',');
if (enrolled == "\n")
{
cout << "Not currently enrolled in a class." << endl;
}
else
{
newStudent.courses[i] = enrolled;
i++;
}
}
cout << newStudent.lName << ", Welcome to the MCC Enrollment System!" << endl;
for (i = 0; i <= NUM_OF_COURSES; i++)
{
cout << "Enrolled courses: " << newStudent.courses[i] << endl;
}
cout << endl;
break;
//Stops searching
}
else
//Ignores rest of line - used to skip to the next line
{
getline(inFile, ID, '\n');
}
if (inFile.eof())
//If ID was not found
{
inFile.close();
cout << "Enter First Name: ";
//Begin entry of new student
cin >> newStudent.fName;
cout << endl;
cout << "Enter Last Name: ";
cin >> newStudent.lName;
cout << endl;
outFile.open("registration.txt", ios::app);
if (outFile.is_open())
{
outFile << newStudent.ID << "," << newStudent.fName << "," << newStudent.lName << "\n";
}
}
}
}
return newStudent;
}
Thanks in advance for any help.
The problem is that std::getline takes exactly one character as a delimiter. It defaults to a newline but if you use another character then newline is NOT a delimiter any more and so you end up with newlines in your text.
The answer is to read the entire line into a string using std::getline with the default (newline) delimiter and then use a string stream to hold that line of text so you can call std::getline with a comma as a delimiter.
Something like this:
#include <fstream>
#include <sstream>
#include <iostream>
#include <vector>
int main()
{
std::ifstream inFile("registration.txt");
if (inFile.is_open())
{
std::string line;
while( std::getline(inFile,line) )
{
std::stringstream ss(line);
std::string ID, fname, lname;
std::getline(ss,ID,','); std::cout<<"\""<<ID<<"\"";
std::getline(ss,fname,','); std::cout<<", \""<<fname<<"\"";
std::getline(ss,lname,','); std::cout<<", \""<<lname<<"\"";
std::vector<std::string> enrolled;
std::string course;
while( std::getline(ss,course,',') )
{
enrolled.push_back(course); std::cout<<", \""<<course<<"\"";
}
std::cout<<"\n";
}
}
return 0;
}
In this example I am writing the text to the screen surrounded by quotes so you can see what is read.
split(string, seperator)
split("918273645,Steve,Albright,ITCS2530,MATH210,ENG140", ",")
split("123456789,Kim,Murphy,ITCS2530,MATH101", ",")
split("213456789,Dean,Bowers,ITCS2530,ENG140", ",")
split("219834765,Jerry,Clark,MGMT201,MATH210", ",")
I know very little C++, but I remember this command.

Getline Issue in C++

I have a text file that displays the following:
John Smith 21 UK
David Jones 28 FRANCE
Peter Coleman 18 UK
and I am trying to strip each individual element into a vector array. I have tried using the getline function with a tab delimiter but it stores every element. For example:
getline (f, line, '\t');
records.push_back(line);
How can I seperate it line by line? The idea is to perform a search and output the corresponding line. A search for Jones will print out the second line for example.
This is what I have so far but as you can see, it's not giving me the desired outcome:
string sString;
string line;
string tempLine;
string str;
vector<string> records;
cout << "Enter search value: " << endl;
cin >> sString;
cout << "\nSEARCHING\n\n";
ifstream f("dataFile.txt");
while (f)
{
while(getline (f, tempLine))
{
getline (f, line, '\t');
records.push_back(line);
}
for(int i=0; i < records.size(); i++)
{
if(sString == records[i]) {
cout << "RECORD FOUND" << endl;
for(int j=0; j < records.size(); j++)
{
cout << j;
cout << records[j] << "\t";
}
}
}
}
f.close();
The first getline extracts a complete line from the input.
The second extracts one field from the next line. If you want
to recover the lines broken down into fields, you should do:
std::vector<std::vector<std::string>> records;
std::string line;
while ( std::getline( f, line ) ) {
records.push_back( std::vector<std::string>() );
std::istringsream fieldParser( line );
std::string field;
while ( std::getline( fieldParser, field ) ) {
records.back().push_back( field );
}
}
This will result in a vector of records, where each record is
a vector of fields. More often, you would want to use a struct
for the record, and do a bit more parsing on the line, e.g.:
struct Field
{
std::string firstName;
std::string lastName;
int age;
std::string country;
};
std::vector<Field> records;
std::string line;
while ( std::getline( f, line ) ) {
std::istringsream fieldParser( line );
Field field;
fieldParser >> field.firstName >> field.lastName >> field.age >> field.country >> std::skipws;
if ( !fieldParser || fieldParser.get() != EOF ) {
// Error occurred...
} else {
records.push_back( field );
}
}
(Something this simple will only work if none of the fields may
contain white space. But it's simple to extend.)
You are doing getline into tempLine which eats a whole line, then you are doing a different getline in the loop as well. That's a big part of why it doesn't work--you are simply throwing away tempLine which contains a lot of your data.

for loop file data is repeating and skipping other lines c++

I'm almost done with my program that reads in contact data, except when I read it in, certain lines repeat and skip other lines. For example, this is what happens currently:
Name: Herb SysAdmin
Address: 27 Technology Drive
Age: 27 Technology Drive
Phone: 25
Type: WORK
It repeats address, but skips phone. Code below.
int EnterContact(string contacts, ListofContacts list)
// first number from the file depicting
{
// constant
ifstream inFile; //input file stream object
inFile.open("contacts.txt");
// variables
std:: string name,
address,
phone,
contactType;
string line;
int age;
int conNum = 0;
inFile >> conNum;
cout << endl;
cout << "There are " << conNum << " contacts in this phone." << endl;
for (int x = 0; x < conNum; x++)
{
getline(inFile, line);
getline(inFile, name);
getline(inFile, address);
inFile >> age >> phone >> contactType;
list[x] = Contact(name, address, age, phone, GetType(contactType));
}
//close the file
inFile.close();
return conNum;
}
any ideas or if i'm just missing a line of code it'd be greatly appreciated.
my input file looks like this:
3
Herb SysAdmin
27 Technology Drive
25
850-555-1212
WORK
Sally Sallster
48 Friendly Street
22
850-555-8484
FRIEND
Brother Bob
191 Apple Mountain Road
30
850-555-2222
RELATIVE
This code:
for (int x = 0; x < conNum; x++)
{
getline(inFile, line);
getline(inFile, name);
getline(inFile, address);
inFile >> age >> phone >> contactType;
list[x] = Contact(name, address, age, phone, GetType(contactType));
}
is wrong because you're mixing formatted input with unformatted input without clearing the newline left after the extraction into conNum and subsequently into contactType.
To fix it, use std::ws:
getline(inFile >> std::ws, line);
// ^^^^^^^^^^^^^^^^^

Sending a String and Int to Function via Text File

I am trying to read in a text file that has a name and age on each line such as this
Tom
55
Bob
12
Tim
66
I then need to pass it to a function which takes in a string and an int such as:
sortDLL.Insert(name, age);
However, I am unsure how to do this. I tested it out with the following and it works (bypassing the text file):
string tom = "tom";
string bob = "bob";
string tim = "tim";
int a = 55;
int b = 12;
int c = 66;
sortDLL.Insert(tom, a);
sortDLL.Insert(bob, b);
sortDLL.Insert(tim, c);
But when I try to read in the text file and send it, the program doesn't run properly. This is what I am currently trying, and I have messed around with a few other things, but have had no luck:
ifstream infile ("names.txt");
while(getline(infile, line));
{
istringstream ss(line);
if (ss >> name)
cin >> name;
else if (ss >> wt)
cin >> wt;
sortDLL.Insert(name, wt);
}
infile.close();
Like always, any help to get this to work would be greatly appreciated, thanks!
I think the correct code should look like this. Remember you have to read 2 line per 1 insert.
while(getline(infile, line))
{
stringstream ss(line);
ss >> wt;
if(ss.fail()) {
name = line;
continue;
}
else {
// cout << name << ":" << wt << endl;
sortDLL.Insert(name, wt);
}
}