How to store lines from a file as a variable - c++

I'd like to show the employee number name, occupation, and department of employees from a text file called organisation.txt, and save them in the variables declared in the class OrganisationRecord.
How can I do that?
#include <iostream>
#include <string>
#include <vector>
#include <fstream>
#define ORGANISATIONALRECORDSFILE "organisation.txt"
#define HRRECORDSFILE "HR_records.txt"
#define PAYROLLRECORDSFILE "payroll_records.txt"
using namespace std;
class OrganisationRecord
{
private:
public:
string name;
string occupation;
string department;
};
class HRRecord
{
private:
public:
string address;
string phonenumber;
string ninumber;
};
class PayrollRecord
{
private:
public:
string ninumber;
double salary;
};
class PayrollProcessing
{
private:
ifstream inputfile;
ofstream outputfile;
vector<OrganisationRecord> OrganisationRecords;
vector<HRRecord> HRRecords;
vector<PayrollRecord> PayrollRecords;
public:
void loadOrganisationRecords(string filename);
void loadHRRecords(string filename);
void loadPayrollRecords(string filename);
void displayEmployeeOfSalaryGTE(double salary);
//GTE = greater than or equal to
};
void PayrollProcessing::loadOrganisationRecords(string filename)
{
inputfile.open(ORGANISATIONALRECORDSFILE);
if (!inputfile)
{
cout << "the organisation records file does not exist" << endl;
return;
}
OrganisationRecord _organisationrecord;
int employeenumber;
while (inputfile >> employeenumber)
{
while (inputfile >> _organisationrecord.name)
{
cout << _organisationrecord.name;
cout << _organisationrecord.occupation;
cout << _organisationrecord.department <<endl;
}
OrganisationRecords.push_back(_organisationrecord);
}
}
int main(void)
{
PayrollProcessing database1;
database1.loadOrganisationRecords(ORGANISATIONALRECORDSFILE);
return 0;
}
organisation.txt
0001
Stephen Jones
Sales Clerk
Sales
0002
John Smith
Programmer
OS Development
0003
Fred Blogs
Project Manager
Outsourcing

When you use inputfile >> _organisationrecord.name it stops at the first whitespace character. Hence, only Stephen will be read and stored in organisationrecord.name.
You need to change your strategy a bit.
Read the contents of the file line by line. Stop when there are no more lines left.
Process each line as you seem fit.
Here's one way to deal with the input.
std::string line;
while ( std::getline(inputfile, line) )
{
// Extract the employeenumber from the line
std::istringstream str(line);
if ( !(str >> employeenumber) )
{
// Problem reading the employeenumber.
// Stop reading.
break;
}
if (!std::getline(inputfile, line) )
{
// Problem reading the next line.
// Stop reading.
break;
}
_organisationrecord.name = line;
if (!std::getline(inputfile, line) )
{
// Problem reading the next line.
// Stop reading.
break;
}
_organisationrecord.occupation = line;
if (!std::getline(inputfile, line) )
{
// Problem reading the next line.
// Stop reading.
break;
}
_organisationrecord.department = line;
std::cout << _organisationrecord.employeenumber << std::endl;
std::cout << _organisationrecord.name << std::endl;
std::cout << _organisationrecord.occupation << std::endl;
std::cout << _organisationrecord.department << endl;
OrganisationRecords.push_back(_organisationrecord);
}

Related

Printing a text file which is stored line by line

I trying to write a function which searches for an ID and prints the book name and author name. I have been able to match the ID, however not able to properly print the book and author name. Text file is stored as such:
ID
book name
author name
Following is the code for my search function:
void searching() {
string search, id, name;
ifstream myfile("books.txt");
bool found = false;
string line;
cout << "\nEnter ID to search : ";
cin >> search;
int srchlen = search.length();
if(myfile.is_open()) {
while(getline(myfile, line)) {
id = line.substr(0, srchlen);
if(id == search) {
found = true;
break;
} else {
found = false;
}
}
if(found == true) {
name = line;
cout << "ID\tNAME\tAUTHOR\n";
cout << name;
} else {
cout << "ID doesnt exist";
}
}
}
Here is how the text file looks like (there is a blank line between each book):
98
crime and punishment
Dostoevsky
70
The Da Vinci Code
Dan Brown
So there's a logical flaw in your code that makes it harder to do what you want. The book data is stored on three separate lines, but your code reads one line at a time. Logically you should be reading three lines at a time. By doing this you'll have all the information available for one book at the same time.
Like this
string id, title, author;
while (getline(myfile, id) && getline(myfile, title) && getline(myfile, author)) {
string blank;
getline(myfile, blank); // skip the blank line between books
id = id.substr(0, srchlen);
if (id == search) {
found = true;
break;
} else {
found = false;
}
}
if (found == true) {
cout << "ID\tNAME\tAUTHOR\n";
cout << id << ' ' << title << ' ' << author << '\n';;
} else {
cout << "ID doesnt exist";
}
Note that reading the blank line is not part of the while condition. We don't want not to consider a book just because it wasn't followed by a blank line. This might happen at the end of the file for example.
To make it easier to deal with the data, I recommend putting the information about a book into a class (struct) and to add operators for reading/writing one book at a time from/to an istream/ostream.
#include <algorithm>
#include <fstream>
#include <iostream>
#include <limits>
#include <string>
struct Book {
std::string id;
std::string title;
std::string author;
};
// operator for reading one book title from any istream
std::istream& operator>>(std::istream& is, Book& b) {
std::getline(is, b.id);
std::getline(is, b.title);
std::getline(is, b.author);
// ignore the blank line between books in the file:
is.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
return is;
}
// operator for writing one book title to any ostream
std::ostream& operator<<(std::ostream& os, const Book& b) {
return os << b.id << '\n' << b.title << '\n' << b.author << "\n\n";
}
int main() {
std::string search;
std::cout << "\nEnter ID to search : ";
std::cin >> search;
if(std::ifstream myfile("books.txt"); myfile) {
Book book;
// read one book at a time from the stream using the added
// operator>>
while(myfile >> book) {
if(book.id == search) {
// book found, write it to cout using the added
// operator<<
std::cout << book;
break;
}
}
}
}
By taking some advantages of C++ such as vector, you can make the code easier:
#include <iostream>
#include <vector>
#include <fstream>
const char *fileName = "books.txt";
// structure of the file
struct book {
int ID;
std::string author;
std::string bookName;
};
int main(void) {
std::ifstream file(fileName); // to read the file
std::vector<book> vec; // to find the content required
int ID; // the ID to find
book temp; // temporary 'book' to insert in vector
bool found = false;
// if the file was unable to open
if (!file.is_open()) {
std::cout << "Unable to open the file." << std::endl;
return -1;
}
// getting the content of the file
while (file >> temp.ID >> temp.bookName >> temp.author)
vec.push_back(temp);
std::cout << "Enter the ID to find: ";
std::cin >> ID;
// matching the IDs
for (size_t i = 0, len = vec.size(); i < len; i++)
// prints when ID asked to show is present in the file
if (vec[i].ID == ID) {
std::cout << "ID: " << vec[i].ID << " | Author: "
<< vec[i].author << " | Name: " << vec[i].bookName;
found = true;
break;
}
if (!found)
std::cout << "The ID does not exist." << std::endl;
return 0;
}
Supposing the books.txt contains:
// FORMAT: ID _ Book _ Author
10 BookABC John
20 BookXYZ Ben
30 CodingBook Rock
Then the output would be something like:
Enter the ID to find: 30
ID: 30 | Author: Rock | Name: CodingBook

How to read the 2nd, 3rd and 4th line of a text file. C++

I am trying to read each line of a text file in C++. I have it working for the first line in a text file, but how do I read the others? Also, I am a C++ super noob, please don't roast me.
Code:
void Grade::readInput()
{
ifstream infile("Grades.txt");
if (infile.good())
{
string sLine;
getline(infile, sLine);
cout << "This is the val " << sLine << endl;
}
infile.close();
}
This is the output I want:
This is the val 12
This is the val 17
This is the val 1
This is the val 29
I'll give you some hints - this is probably more like CodeReview.SE now...
I would recommend
separating the reading from printing
treating the grades as numbers (e.g. int or double) so you can actually work with them, and have some validation that you're not reading non-sense
Use idiomatic loops, don't just if (infile.good()) - e.g. you can't tell whether you've reached end-of-file before you try to read
Fixing up the interface, I'd suggest something like this
struct Grade {
void readInput(std::string fname);
void print(std::ostream& os = std::cout) const;
private:
static constexpr auto max_line_length = std::numeric_limits<ssize_t>::max();
std::vector<int> grades;
};
Note that readInput reads into grades without printing anything. Note also that it takes the name of the file to read as the argument, instead of hardcoding some filename.
int main() {
Grade grading;
grading.readInput("grades.txt");
grading.print();
}
This would be the main program.
The simplified/extended version of readGrades could be:
void Grade::readInput(std::string fname) {
std::ifstream infile(fname);
infile.ignore(max_line_length, '\n'); // ignore the first line
int grade = 0;
while (infile >> grade) {
grades.push_back(grade);
infile.ignore(max_line_length, '\n'); // ignore rest eating newline
}
}
Note how we ignore lines or parts thereof that we are not interested in. For extra control consider disabling white-space skipping:
infile >> std::nowskipws;
The print function could be a simple:
void Grade::print(std::ostream& os) const {
os << "Grades:";
for (int g : grades) {
os << " " << g;
}
os << std::endl;
}
Full Demo
Live On Coliru
#include <fstream>
#include <string>
#include <vector>
#include <iostream>
struct Grade {
void readInput(std::string fname);
void print(std::ostream& os = std::cout) const;
private:
static constexpr auto max_line_length = std::numeric_limits<ssize_t>::max();
std::vector<int> grades;
};
int main() {
Grade grading;
grading.readInput("grades.txt");
grading.print();
}
void Grade::readInput(std::string fname) {
std::ifstream infile(fname);
infile.ignore(max_line_length, '\n'); // ignore the first line
int grade = 0;
while (infile >> grade) {
grades.push_back(grade);
infile.ignore(max_line_length, '\n'); // ignore rest eating newline
}
}
void Grade::print(std::ostream& os) const {
os << "Grades:";
for (int g : grades) {
os << " " << g;
}
os << std::endl;
}
Prints
Grades: 12 17 1 29
Given grades.txt:
Ignore the first line
12
17
1
29
A simple version:
std::string line1;
std::string line2;
std::string line3;
std::string line4;
std::getline(infile, line1);
std::getline(infile, line2);
std::getline(infile, line3);
std::getline(infile, line4);
With a loop:
static const unsigned int LINES_TO_READ = 3;
std::string line1_ignored;
std::getline(infile, line1_ignored);
for (unsigned int i = 0; (i < LINES_TO_READ); ++i)
{
std::string text_line;
if (std::getline(infile, text_line))
{
std::cout << text_line << std::endl;
}
else
{
break;
}
}
Both versions read the first line. Ignore the contents in the variable if you wish.
The simple method reads each text line, into separate variables.
The second reads text lines using a known-quantity loop.

C++ Validate Emails Via Substrings

I'm trying to take the profile info(username, email, etc.) from one directory and put it in another. I've been debugging the code for this program, and while there are no errors, the program won't run, saying that the program "has stopped working". I have already looked on this website and others for any possible answers, and found none.
#include <string>
#include <cstring>
#include <iostream>
#include <istream>
#include <ostream>
#include <fstream>
#include <iomanip>
#include <filesystem>
using namespace std;
class path{
public:
string parent_directory;
string root_directory;
};
class Data{
public:
string userName;
string nickName;
string fName;
string arena_FName;
string lName;
string arena_LName;
string email;
string arenaEmail;
friend std::istream& operator>>(std::istream& input, Data& d);
};
std::istream& operator>>(std::istream& input, Data& d){
std::getline(input, d.userName);
std::getline(input, d.nickName);
//...
std::getline(input, d.arenaEmail);
return input;
}
int main(){
ifstream myfile("myfunk.txt", ios::in);
ofstream arena("arena.txt");
myfile.open("myfunk.txt", ios::in);
if(myfile){
cout << "Input file open." << endl;
}
arena.open("arena.txt", ios::out | ios::app);
if(arena){
cout << "Output file open." << endl;
}
cout << "file opening test: success" << endl;
int x = 0;
int y = 4101; //Total number of users in the directory.
int z = 0; //For inputting the required lines of info for each profile.
int profile = 0;
bool valid = false;
string role;
//string arenaRole;
bool post = false;
string line;
string p = "This PC/..."; //Path to the folder of the individual pictures.
//myVar.save("...");
string p = "...";
path path1;
path root_directory;
path parent_directory;
//bool is_directory(const std::filesystem::path& p, std::error_code& ec) noexcept; //Checks if current location is a directory.
//bool postPic;
const unsigned int MAXIMUM_DATA = 4100u;
Data database[MAXIMUM_DATA];
cout << "All variables but the filesystem have been accepted! Please install this program on the network." << endl;
while(x < y){
cout << "Primary loop functioning" << endl;
if(post = true){
getline(myfile, line); //Grab and read next line.
myfile >> line;
line = userName[x];
arena << "Username: " << userName[x] << "\n";
z++;
getline(myfile, line);
myfile >> line;
line = role[x];
arena << "Role: " << role[x] << "\n";
z++;
getline(myfile, line);
line = nickName[x];
myfile >> nickName[x];
arena << "nickname: " << nickName[x] << "\n";
z++;
getline(myfile, line);
line = fName[x];
myfile >> fName;
arena << "First Name: " << fName[x] << "\n";
z++;
getline(myfile, line);
line = lName[x];
myfile >> lName;
arena << "Last Name: " << lName[x] << "\n";
z++;
getline(myfile, line);
myfile >> line;
line = email[x];
arena << "Email: " << email[x] << "\n";
getline(myfile, line);
z = 0; //Next profile...
}
int data;
while(myfile >> data){
if(nickName[x] = NULL){
myfile >> "<Error> Some required information is missing! Contact user! </Error> /n";
valid = false;
post = false;
x++;
}
if(email[x] != NULL){
std::string str("#");
std::string str2(".com");
std::string str3(".net");
std::string str4(".edu");
if(std::size_t found = email[x].find(str) & (std::size_t found = email[x].find(str2) || std::size_t found = email[x].find(str3) || std::size_t found = email[x].find(str4)){
valid = true;
if(valid = true){
post = true;
}
}
else{
valid = false;
post = false;
x++;
}
}
}
}
}
}
x++;
}
//x++;
myfile.close(); //Closes the file in the directory.
arena.close(); //Closes the file in Arena.
return 0;
}
Let's rework your code.
First, let's create a data structure for the data:
class Data
{
public:
string userName;
string nickName;
string fName;
string arena_FName;
string lName;
string arena_LName;
string email;
string arenaEmail;
};
If you need an array for the data, it would be declared as:
const unsigned int MAXIMUM_DATA = 4100u;
Data database[MAXIMUM_DATA];
Next, let's overload the extraction operator>> to make reading easier:
class Data
{
public:
//...
friend std::istream& operator>>(std::istream& input, Data& d);
};
std::istream& operator>>(std::istream& input, Data& d)
{
std::getline(input, d.userName);
std::getline(input, d.nickName);
//...
std::getline(input, d.arenaEmail);
return input;
}
This simplifies your input loop to:
std::vector<Data> database;
Data d;
while (my_file >> d)
{
database.push_back(d);
}
You can query the amount of data read in by using the std::vector::size() method, i.e. database.size().
Also, you don't need a separate structure for a file path. A simple std::string will suffice. I recommend using forward slash, '/', because it is recognized by both Windows and *nix operating systems and won't be interpreted as an escape character.

Please Help "EXC_BAD_ACCESS(Code 2)"

im writing a C++ program that reads info about books from an external text file, stores the info in an array and writes a new file with the titles and prices of each book. at compile time there is no error but when I run the program I get a bunch of memory locations that pop up on the screen and an error
"thread 1: EXC_BAD_ACCESS(Code 2)"
if it matters im using xcode on an intel mac. The code is below with a few screen shots of the problem. Thanks
The Code:
//main.cpp
include <iostream>
include <fstream>
include "Book.h"
include "textbook.h"
include "Name.h"
using namespace std;
int main()
{
string title, authorf, authorl, publisher, isbn, subject;
int pages, i = 0, j = 0;
float price, rentalp;
char code;
static int bookCount = 0, textbookCount = 0;
ifstream file1, file2;
ofstream newFile;
file1.open("/Users/TVaughn/Documents/School Stuff/Fall 2012/CS 246/In Class Programs/Book/Book/Data.txt", ios::in); //Opening the data.txt file to read from.
newFile.open("/Users/TVaughn/Documents/School Stuff/Fall 2012/CS 246/In Class Programs/Book/Book/Title.txt", ios::out); //Creating a new file to store titles & prices of all the books.
book bookList[3];
while (!file1.eof()) {
getline (file1, title, ',');
getline (file1, authorf, ',');
getline (file1, authorl, ',');
getline (file1, publisher, ',');
getline (file1, isbn, ',');
file1 >> pages;
file1.ignore();
file1 >> price;
file1.ignore();
file1 >> code;
file1.ignore(10, '\n');
book b1(title, authorf, authorl, publisher, pages, isbn, price, code);
bookList[i] = b1; //initalizing the first element of the array to b1
newFile << "Title: " << bookList[i].getTitle() << "\n" << "Price: " << bookList[i].getPrice() << "\n\n"; //storing the title and price of all the books in a new file called titles.
bookList[i].PrintBook();
i++;
bookCount++;
}
file1.close();
file2.open("/Users/TVaughn/Documents/School Stuff/Fall 2012/CS 246/In Class Programs/Book/Book/TextbookData.txt", ios::in); //Opening the TextbookData.txt file to read from.
textbook TbookList[2];
while (!file2.eof()) {
getline (file2, title, ','); //retrieving info from data.txt and storing that info into variables so the variable may be passed as arguments in my textbook object b2.
getline (file2, authorf, ',');
getline (file2, authorl, ',');
getline (file2, isbn, ',');
file2 >> pages;
file2.ignore();
file2 >> price;
file2.ignore();
getline(file2, subject, ',');
file2 >> code;
file2 >> rentalp;
file2.ignore(10, '\n');
textbook b2(title, authorf, authorl, publisher, pages, isbn, price, code, subject, rentalp);
TbookList[j] = b2; //initalizing the first element of the array to b2.
newFile << "Title: " << bookList[j].getTitle() << "\n" << "Price: " << bookList[j].getPrice() << "\n\n";
TbookList[j].PrintBook();
j++;
textbookCount++;
}
file2.close();
newFile.close();
cout << "Number of books: " << bookCount << "\nNumber of textbooks: " << textbookCount << endl;
book b3("C++ Data Structures", "Nell B.", "Dale", "Jones & Bartlett Publishers", 781, "9780763741587", 107.67, 'A'); //This line is used to test the exception handeling.
try {
b3.setPrice(price);
b3.setPages(pages);
}
catch (book::negativeNumber) {
cout << "Negative price was entered \n\n" << "End of program \n";
}
return 0;
}
//book.h
#include <iostream>
#include "Name.h"
#include <string>
using namespace std;
#ifndef BOOK_H
#define BOOK_H
class book
{
private:
string title;
Name aurthor;
string publisher;
string ISBN;
int pages;
float price;
char code;
public:
class negativeNumber{};
void setTitle(string);
void setAurthor(string f, string l);
void setPublisher(string);
void setISBN(string);
void setPages(int);
void setPrice(float);
void setCode(char);
string getTitle();
Name getAurthor();
string getPublisher();
string getISBN();
int getPages();
float getPrice();
char getCode();
void PrintBook();
book(); //default constructor
book(string, string, string, string, int, string, float, char);
~book(); //Destructor
};
#endif
//Book.cpp
#include <iostream>
#include <string>
#include "Book.h"
#include "Name.h"
using namespace std;
book::book() {
title = "Southern Charm";
Name::Name();
publisher = "Impact Publishers";
pages = 223;
ISBN = "234-232-10009045";
price = 14.99;
code = 'L';
}
book::book(string the_title, string f, string l, string the_pub, int page_num, string the_ISBN, float the_price, char the_c)
{
title = the_title;
//Name(f, l);
aurthor.setfName(f);
aurthor.setlName(l);
publisher = the_pub;
pages = page_num;
ISBN = the_ISBN;
price = the_price;
code = the_c;
}
book::~book()
{
}
void book::setTitle(string t)
{
title = t;
}
void book::setAurthor(string f, string l)
{
aurthor.setfName(f);
aurthor.setlName(l);
}
void book::setPublisher(string pub)
{
publisher = pub;
}
void book::setISBN(string ISBN_num)
{
ISBN = ISBN_num;
}
void book::setPages(int p) {
if (pages > 0)
pages = p;
else
throw negativeNumber();
}
void book::setPrice(float cost) {
if (price >= 0) //This is called exception handling.
price = cost;
else
throw negativeNumber();
}
void book::setCode(char c) {
code = c;
}
string book::getTitle() {
return title;
}
Name book::getAurthor(){
return aurthor;
}
string book::getPublisher() {
return publisher;
}
string book::getISBN(){
return ISBN;
}
int book::getPages() {
return pages;
}
float book::getPrice() {
return price;
}
char book::getCode() {
return code;
}
void book::PrintBook() {
cout << "Title: " << getTitle() << "\n" << "Aurthor: ";
getAurthor().printName();
cout << "Publisher: " << getPublisher() << "\n" << "Pages: " << getPages() << "\n" << "ISBN: " << getISBN() << "\n" << "Price: " << getPrice() << "\n" << "Code: " << getCode() << "\n \n \n";
}
Here are a few points that jumped out at me:
My mantra: Thou shalt check reading worked after thy read.
Use of std::ios_base::eof() is only good to determine why the previous read failed.
You actual problem is: what happens if there are more than 3 books? (no need to answer: I know what happens...)
Expert programmers struggle with getting long functions right. Beginners stand no chance! Split your code into digestable and coherent chunks!
Fix the problems and retry.

how to insert data from a text file into an array of struct

I need to read data from a text file, and insert the data in an array of struct. The data file is in the following format:
productname price quantity
my main concern is to read the product name, which consist of one, and two words. Should I approach product name as a c-string or as a string literal?
any help appreciated
#include <iostream>
#include <fstream>
using namespace std;
const int SIZE = 15; //drink name char size
const int ITEMS = 5; //number of products
struct drinks
{
char drinkName[SIZE];
float drinkPrice;
int drinkQuantity;
};
int main()
{
//array to store drinks
drinks softDrinks[ITEMS];
//opening file
ifstream inFile;
inFile.open("drinks.txt");
char ch;
int count = 0; //while loop counter
if(inFile)
{
while(inFile.get(ch))
{
//if(isalpha(ch)) { softDrinks[count].drinkName += ch; }
//if(isdigit(ch)) { softDrinks[count].drinkPrice += ch; }
cout << ch;
}
cout << endl;
count++;
}
else
{
cout << "Error opening file!\n";
system("pause");
exit(0);
}
system("pause");
return 0;
}
Since you ask for "any help", here's my view: Forget everything you wrote, and use C++:
#include <fstream> // for std::ifstream
#include <sstream> // for std::istringstream
#include <string> // for std::string and std::getline
int main()
{
std::ifstream infile("thefile.txt");
std::string line;
while (std::getline(infile, line))
{
std::istringstream iss(line);
std::string name;
double price;
int qty;
if (iss >> name >> price >> qty)
{
std::cout << "Product '" << name << "': " << qty << " units, " << price << " each.\n";
}
else
{
// error processing that line
}
}
}
You could store each line of data in a std::tuple<std::string, int, double>, for example, and then put those into a std::vector as you go along.