Read text file into class member variables using getline - c++ - c++

I recently started learning c++ so I'm still learning. Basically I'm trying to read my text file when the string "NEW_EMPLOYEE" is found and then store every line into their respective member variables until an empty line is found in the text file to stop. The problem I'm having is how can I use getline to import each line into each variable of my class "Employee" all at once? Should I use istringstream instead?
My text file called "employee.txt"
NEW_EMPLOYEE
460713
John
Smith
64000
36
END_OF_FILE
My class Employee:
class Employee {
private: //Member variables
int ID;
string FirstName;
string LastName;
int Salary;
int Hours;
public:
Employee() {} //Default constructor
Employee(int& id, string& firstName, string& lastName, int& salary, int& hours) {
ID = id;
FirstName = firstName;
LastName = lastName;
Salary = salary
Hours = hours;
}
};
My main.cpp:
#include <iostream>
#include <fstream>
int main() {
Employee employee;
int id;
string firstName;
string lastName;
int salary;
int hours;
string line;
ifstream employeeFile;
employeeFile.open("employee.txt");
while(getline(employeeFile, line)) {
if(line == "NEW_EMPLOYEE") {
do {
//Don't know what to do here???
} while (!line.empty());
}
}
employeeFile.close();
return 0;
}

The straightforward approach would be to do something like that
while(employeeFile >> line){
if(line != "NEW_EMPLOYEE") continue;
int id,salary,hours;
string firstName, lastName;
employeeFile >> id >> firstName >> lastName >> salary >> hours;
Employee employee = Employee(id, firstName, lastName, salary, hours);
// Do what you want with employee
}
This assumes that the data are written in the file always in the same order. I also assumed that the lines contain no spaces since they're either numbers or names so I used >> operator. You can use getline instead if that's not the case.
If you always sure the data are in the same order then this should be enough. If that's not true, I'd recommend writing the object as JSON in the file, and use a JSON parser library to read the file directly into an object.

yes..straight forward approach can help you otherwise u can use simple method like ...
#include <iostream>
#include <fstream>
#include <stdlib.h>
#include <sstream>
using namespace std;
int main() {
string x[100];
int i=0;
// Employee employee;
int id;
string firstName;
string lastName;
int salary;
int hours;
string line;
string text;
ifstream employeeFile;
employeeFile.open("employee.txt");
while(!employeeFile.eof())
{
getline(employeeFile,text);
x[i++]=text;
}
// employeeFile.close();
stringstream(x[1]) >> id; //string to int
firstName = x[2];
lastName = x[3];
stringstream(x[4]) >> salary;
stringstream(x[5]) >> hours;
//cout<<id<<" "<<firstName;
}
Then you can call your method . But straight forward approach is moore perfect than this :)

Related

How to let a user add to and remove from "slots" in an array?

I have a project in my C++ class - we're supposed to make a "simple student management system" comprised of a class for the student attribute variables, and a main function with a branch statement that lets the user input names and IDs for the students. I know that I need to use an array to make "slots" for the students, and that my branch statements need to let the user input values into those slots, but I'm not exactly sure how to do it. Here is the code that I have so far.
#include <string>
#include <iostream>
#include <utility>
using std::string;
using std::cin;
using std::cout;
using std::endl;
struct Student {
private:
int id;
string name;
int birthday;
public:
Student()
{
id = 0;
birthday = 0;
}
Student(int id, string name, int birthday)
{
//set your parameters to the class variables
this->id = id;
this->name = name;
this->birthday = birthday;
}
void setID(int id)
{
this->id = id;
}
int getID() {
return id;
}
void setName(string name)
{
this->name = name;
}
string getName()
{
return name;
}
void setBirthday(int birthday)
{
this->birthday = birthday;
}
int getBirthday()
{
return birthday;
}
void output() {
cout << id << name << birthday << endl;
}
};
int main() {
Student arr[50];
cout << "Student Management System" << endl;
cout << "Press 'a' to add a student" << endl;
char a = 1;
int y = 1;
while (a == 'a') {
switch (y)
{
cout << "Input Student ID:";
cin >> id;
}
}
}
What I'm focusing on most is the fourth line from the bottom. I was told that I need to use my setters, so I said that I want what my user inputs to be treated as the value of the ID variable that I set in the class. However, when I wrote this out, I was given an error. Could someone tell me what the issue is?
You should try to get your switch statement working correctly. To use classes setters, you can store the user input to a temporary variable then from your one student you can call the member function. i.e. in your case:
arr[index].setID(tempInputVariable);
There is no id in your main function or as a global variable.
I suggest you overload operator >> to have your structure extract its members from the data stream:
struct Student
{
//...
public:
friend std::istream& operator>>(std::istream& input, Student& s);
};
std::istream& operator>>(std::istream& input, Student& s)
{
input >> s.id;
input >> s.name;
input >> s.birthday;
return input;
}
Although the above code doesn't use setters, it is the preferred method for inputting data.
The overload can be modified to use setters (kind of overkill):
std::istream& operator>>(std::istream& input, Student& s)
{
int id;
input >> id;
s.setID(id);
std::string name;
input >> name;
s.setName(name);
int birthday;
input >> birthday;
s.setBirthday(birthday);
return input;
}
If you don't like the overload, you can perform the steps in your main function:
//...
Student new_student;
//...
{
int student_id;
std::cout << "Input Student ID:";
std::cin >> student_id;
new_student.setID(student_id);
std::string student_name;
std::cout << "Input Student Name: ";
std::cin >> student_name;
new_student.setName(student_name);
int student_birthday;
std::cout << "Input Student Birthday: ";
std::cin >> student_birthday;
new_student.setBirthday(student_birthday);
}
Edit 1: The Database
You'll probably need to store or remember the students. This is easy using the first method above:
std::vector<Student> database;
Student s;
std::cout << "Enter student information (ID, Name and birthday, separated by spaces:\n";
std::cin >> s;
// Append to the database
database.push_back(s);
If you haven't learned std::vector you can try an array:
const size_t MAXIMUM_STUDENTS = 16;
Student database[MAXIMUM_STUDENTS];
size_t database_index = 0;
//...
Student s;
std::cout << "Enter student information (ID, Name and birthday, separated by spaces:\n";
std::cin >> s;
// Append to database
database[database_index] = s;
++database_index;

Need help reading data from .txt file into an array C++

#include <iostream>
#include <fstream>
#include <string>
struct textbook //Declare struct type
{
int ISBN;
string title;
string author;
string publisher;
int quantity;
double price;
};
// Constants
const int MAX_SIZE = 100;
// Arrays
textbook inventory[MAX_SIZE];
void readInventory()
{
// Open inventory file
ifstream inFile("inventory.txt");
// Check for error
if (inFile.fail())
{
cerr << "Error opening file" << endl;
exit(1);
}
// Loop that reads contents of file into the inventory array.
pos = 0; //position in the array
while (
inFile >> inventory[pos].ISBN
>> inventory[pos].title
>> inventory[pos].author
>> inventory[pos].publisher
>> inventory[pos].quantity
>> inventory[pos].price
)
{
pos++;
}
// Close file
inFile.close();
return;
}
Hello,
I need assistance with this function. The goal of this function is to read in the information from a txt file and read it in to an array struct for a textbook.
The text file itself is already set up in the correct order for the loop.
My problem is that for the title section, the title of a book might be multiple words like 'My first book" for example. I know that I have to use a getline to take the line as a string to feed it into the 'title' data type.
I am also missing a inFile.ignore() somewhere but I don not know how to put it into a loop.
Presuming the input format is:
ISBN title author publisher price quantity price
i.e., the data members are line white space separated, you could define operator>> for your struct textbook, which could look something like:
std::istream& operator>> (std::istream& is, textbook& t)
{
if (!is) // check input stream status
{
return is;
}
int ISBN;
std::string title;
std::string author;
std::string publisher;
int quantity;
double price;
// simple format check
if (is >> ISBN >> title >> author >> publisher >> quantity >> price)
{
// assuming you additionally define a (assignment) constructor
t = textbook(ISBN, title, author, publisher, quantity, price);
return is;
}
return is;
}
Then to read your file you simply do:
std::ifstream ifs(...);
std::vector<textbook> books;
textbook b;
while (ifs >> b)
{
books.push_back(b);
}
Regarding the use of getline() see this answer.

c++ program outputs series of numbers instead of cout

My current assignment is to create a simple
Student Class that takes the
first name
last name
student ID number
from an object and outputs the name as a single string and his/her ID number. The program also has to count every student and output the total number of students. In this program I'm given 4 students.
I've created the program, given below. Everything compiles correctly and runs but my output is strange. Instead of giving me the students' ID and name, it gives me the number "-858993460". I have no idea why my program's doing this and a long search on the internet hasn't helped me much.
Student.h
#include <iostream>
#include <string>
using namespace std;
class Student
{
private:
string firstName;
string lastName;
int id;
string name;
public:
static int numberOfStudents;
Student();
Student(string theFirstName, string theLastName, int theID);
string getName();
int getID();
};
Student.cpp
#include "Student.h"
#include <iostream>
#include <string>
using namespace std;
//initialize numberOfStudents to 0
int Student::numberOfStudents = 0;
//initialize default constructor
Student::Student()
{
numberOfStudents++;
}
//initialize overloaded constructor
Student::Student(string theFirstName, string theLastName, int theID)
{
theFirstName = firstName;
theLastName = lastName;
theID = id;
numberOfStudents++;
}
//getName
string Student::getName()
{
return firstName += lastName;
}
//getID
int Student::getID()
{
return id;
}
main.cpp(this is my driver file)
#include "Student.h"
#include <iostream>
#include <string>
using namespace std;
int main()
{
Student st1("Hakan", "Haberdar", 1234), st2("Charu", "Hans", 2345), st3("Tarikul", "Islam", 5442), st4;
cout << "We created " << Student::numberOfStudents<<" student objects." << endl;
cout << st1.getID()<<" "<<st1.getName()<<endl;
cout << st2.getID()<<" "<<st2.getName()<<endl;
cout << st3.getID()<<" "<<st3.getName()<<endl;
cout << st4.getID()<<" "<<st3.getName()<<endl;
system("pause");
};
This is what my output is supposed to look like:
We created 4 student objects.
1234 Hakan Haberdar
2345 Charu Hans
5442 Tarikul Islam
0
This is what my output instead looks like:
We created 4 student objects.
-858993460
-858993460
-858993460
-858993460
I think my problem has something to do with my getName() function, but I'm not sure and I don't know what to try.
Student::Student(string theFirstName, string theLastName, int theID)
{
theFirstName = firstName;
theLastName = lastName;
theID = id;
numberOfStudents++;
}
Your assignments are the wrong way round. You're assigning the as yet uninitialised members to the arguments. Instead you should have:
Student::Student(string theFirstName, string theLastName, int theID)
{
firstName = theFirstName;
lastName = theLastName;
id = theID;
numberOfStudents++;
}
This mistake would have been avoided if you had used a member initialization list instead:
Student::Student(string theFirstName, string theLastName, int theID)
: firstName(theFirstName), lastName(theLastName), id(theID)
{
numberOfStudents++;
}
Not sure if the following is the reason for your issues, but it does seem wrong...
return firstName += lastName;
What this does is modifies firstname by appending last name to it, then returning modified string.
I think you meant to do something like
return firstName << ' ' << lastName;
Change your code to.
Student::Student(string theFirstName, string theLastName, int theID)
{
firstName = theFirstName;
lastName = theLastName;
id = theID;
numberOfStudents++;
}
Your code returning the value of id! which is not initialized.
So the code will return garbage.

return value to main

In the code below I am trying to have the variable fullName be populated with whatever I enter during the operation of the function namecheck. I am not sure where I am going wrong. Please help and thank you for it.
#include <cstdlib>
#include <iomanip>
#include <iostream>
#include <cmath>
#include <string>
#include <fstream>
using namespace std;
string namecheck();
int main()
{
cout<<fixed;
string firstName;
string lastName;
string fullName;
char action;
int pin;
int pinTry =1;
int actionsTaken =0;
int joeyPin = 4433;
int mildredPin = 2849;
double joeyTotal = 3742.55;
double mildredTotal = 19.36;
double withdraw;
double deposit;
namecheck();
cout<<fullName;
}
string namecheck(){
string firstName;
string lastName;
string fullName;
string completeName;
double joeyTotal = 3742.55;
double mildredTotal = 19.36;
cout<<"Welcome to Blah National Bank!\n";
cout<<"What is your first name?\n";
cin>>firstName;
if (firstName == "END"){
cout<<"User totals: \n"
<<"Joey Stowy:\t"<<setprecision(2)<<joeyTotal<<endl<<endl
<<"Mildred Moredebt:\t"<<setprecision(2)<<mildredTotal<<endl<<endl;
}
if (firstName != "END"){
cout<<"What is your last name?\n";
cin>>lastName;
}
fullName = firstName+" "+lastName;
return fullName;
}
Change:
namecheck();
cout<<fullName;
to:
fullname = namecheck();
cout<<fullName()
.
When you call namecheck() in main, assign the result to fullName:
fullName = namecheck();

breaking up input from a file c++

I have a file that contains employee information on each line (id, department, salary, and name). Here is an example line:
45678 25 86400 Doe, John A.
Right now I am reading in each word using fstream, which works until I get to the name part. My question is what is the easiest way to capture that name as a whole?
Data >> Word;
while(Data.good())
{
//blah blah storing them into a node
Data >> Word;
}
You probably want to define a struct to hold the data for an employee, the define an overload of operator>> to read one of those records from your file:
struct employee {
int id;
int department;
double salary;
std::string name;
friend std::istream &operator>>(std::istream &is, employee &e) {
is >> e.id >> e.department >> e.salary;
return std::getline(is, e.name);
}
};
int main() {
std::ifstream infile("employees.txt");
std::vector<employee> employees((std::istream_iterator<employee>(infile)),
std::istream_iterator<employee>());
// Now all the data is in the employees vector.
}
#include <fstream>
#include <iostream>
int main() {
std::ifstream in("input");
std::string s;
struct Record { int id, dept, sal; std::string name; };
Record r;
in >> r.id >> r.dept >> r.sal;
in.ignore(256, ' ');
getline(in, r.name);
std::cout << r.name << std::endl;
return 0;
}
I would create a record and define the input operator
class Employee
{
int id;
int department;
int salary;
std::string name;
friend std::istream& operator>>(std::istream& str, Employee& dst)
{
str >> dst.id >> dst.department >> dst.salary;
std::getline(str, dst.name); // Read to the end of line
return str;
}
};
int main()
{
Employee e;
while(std::cin >> e)
{
// Word with employee
}
}