for loop file data is repeating and skipping other lines c++ - 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);
// ^^^^^^^^^^^^^^^^^

Related

Reading from a file, and looping over the file to write to an array

I am writing a banking program to practice my c++ skills, and I am stuck on reading/writing from/to a file. I am storing some basic info (name, account number, pin, balance) to a file, and want to be able to read from that file anytime I open the program. I made a simple class called client:
class client
{
public:
int acctNum;
string firstName;
string lastName;
float balance;
int pin;
}
I save the info to a txt file formatted by account number, pin, first name, last name, and balance:
1 88 Doug Dimmadome 5
My loop over the input file only reads in the account number though, and continuously does so with no end (inFile is the variable name for my ifstream, and clientList is my variable name for an array of clients):
while (!inFile.eof()) {
inFile >> acc;
cout << acc << endl;
clientList[acc].acctNum = acc;
inFile >> clientList[acc].pin;
inFile >> clientList[acc].firstName;
inFile >> clientList[acc].lastName;
inFile >> clientList[acc].balance;
}
What am I doing wrong in my loop so that it doesn't properly loop over all the data in the file?
------EDIT------
I'm adding my variable declaration and opening my file:
client clientList[maxClients];
client currTrans;
int choice = NULL;
char atm = 'y';
ifstream inFile;
ofstream file;
const string fileName = "clientList.txt";
int acc;
inFile.open(fileName);
if (!inFile.is_open()) {
cout << "File could not open.";
return 1;
}
And my client constructor:
client::client() {
acctNum = NULL;
firstName = "";
lastName = "";
balance = NULL;
pin = NULL;
}
I think I figured it out through a combination of #Sam Varshavchik and #PaulMcKenzie:
I used the debugger to figure out where my program was failing, it was continuously reading the same line so it had nowhere to exit the loop.
I changed how I was detecting the end file by listing the account number twice and checking to make sure that a new piece of data was read on each loop:
while (**inFile >> beg**) {
inFile >> acc;
cout << acc << endl;
clientList[acc].acctNum = acc;
inFile >> clientList[acc].pin;
inFile >> clientList[acc].firstName;
inFile >> clientList[acc].lastName;
inFile >> clientList[acc].balance;
}
So now my data in my text file looks like this:
1
1 22 Doug Dimmadome 300
2
2 66 Dif Difadif 400
34
34 123 Mike Wasowski 666
44
44 67 Dale Dalers 600
99
99 44 Mitch Turtle 0.02

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.

Load information from file and assign each line to instance of class

This is what a line in my text file looks like:
1 1 10 20 20 50 donut frank 0.75 1.50 100.00
each seperate class variable is seperated by a space. My code never makes it to the while loop. Can someone explain what is happening and how I might fix it?
void load_inventory(vector<Item*> &items, string filename){
ifstream infile;
infile.open(filename.c_str());
istringstream stin;
string line;
cout << "WORKS" << endl;
if(!infile){
cout << "there was an error opening the file" << endl;
return;
}
while(!infile.eof()){
cout << "INSIDE THE LOOP" << endl;
Item* item = new Item();
getline(infile, line);
stin.str(line);
item->setMonth(stin);
item->setId(stin);
item->setNum(stin);
item->setDesired(stin);
item->setLife(stin);
item->setVolume(stin);
item->setName(stin);
item->setSupplier(stin);
item->setCost(stin);
item->setPrice(stin);
item->setSales(stin);
items.push_back(item);
stin.clear();
stin.seekg(0);
}
}
The problem was that you were passing the string stream to your Item functions rather than the actual value. Try this:
std::ifstream infile(filename);
std::string line;
int month, id, num, desired, life, volume;
std::string name, supplier;
float cost, price, sales;
while (std::getline(infile, line))
{
std::istringstream iss(line);
if (
iss >> month >> id >> num >> desired >> life >> volume
>> name >> supplier >> cost >> price >> sales)
{
Item* item = new Item();
// vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
item->setMonth(month);
item->setId(id);
item->setNum(num);
item->setDesired(desired);
item->setLife(life);
item->setVolume(volume);
item->setName(name);
item->setSupplier(supplier);
item->setCost(cost);
item->setPrice(price);
item->setSales(sales);
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
items.push_back(item);
}
}
Note that you should be using a container that manages the memory for you, like std::unique_ptr. Also, the constructor to your Item class should take parameters for the values.

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);
}
}

reading in strings and doubles

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
*\