I have got an assignment project to make a program using C++ which maintains a list of Students (their name, age, and GPA) in a text file. The program has the following functionality:
Insertion of record
Deletion of record
Searching of record
Updating a record
When deleting a record my code takes a string name as input and removes it from the text file. However the next two lines in the file (age & gpa for that student) are left. How do I remove those too?
Following is the code for my program.
#include <iostream>
#include <fstream>
using namespace std;
void writing();
void deleting();
void searching();
class student {
public:
int age = 0;
string name;
void SetGpa(float x)
{
gpa = x;
}
float GetGpa()
{
return gpa;
}
private:
float gpa = 0.0;
};
int main()
{
int opt;
cout << "Please Enter an option number to continue:\n ";
cout << "\nPress 1 for New Record insertion";
cout << "\nPress 2 for Record Deletion";
cout << "\nPress 3 for Searching a Record";
cout << "\nPress 4 for Updating a Record";
cout << "\nEnter option Number: ";
cin >> opt;
switch (opt)
{
case 1:
{
writing();
break;
}
case 2:
{
deleting();
break;
}
case 3:
{
searching();
break;
}
case 4:
{
deleting();
writing();
cout << "Record has been updated! ";
break;
}
}
}
void writing()
{
float a;
student moiz;
cout << "Please enter name of student: ";
cin >> moiz.name;
cout << "Please enter the age of student: ";
cin >> moiz.age;
cout << "Pleae enter the Gpa of student: ";
cin >> a;
moiz.SetGpa(a);
ofstream myfile;
myfile.open("record.txt", ios::app | ios::out);
myfile << endl << moiz.name << endl;
myfile << moiz.age << endl;
myfile << moiz.GetGpa();
myfile.close();
}
void deleting()
{
string line, name;
cout << "Please Enter the name of record you want to delete: ";
cin >> name;
ifstream myfile;
ofstream temp;
myfile.open("record.txt");
temp.open("temp.txt");
while (getline(myfile, line))
{
if (line != name)
temp << line << endl;
}
cout << "The record with the name " << name << " has been deleted if it exsisted" << endl;
myfile.close();
temp.close();
remove("record.txt");
rename("temp.txt", "record.txt");
}
void searching()
{
ifstream fileInput;
fileInput.open("record.txt");
string line, search;
cout << "Please enter the term to search: ";
cin >> search;
for (unsigned int curLine = 0; getline(fileInput, line); curLine++)
{
if (line.find(search) != string::npos)
{
cout << "found: " << search << " on line: " << curLine << endl;
}
else
{
cout << "Error! Not found on Line" << curLine << endl;
}
}
}
You can add an else clause to your statement checking the name, and introduce a counter of how many of the following lines should be skipped after name was found:
int skip = 0;
while (getline(myfile, line)) {
if ((line != name) && !(skip > 0)) {
temp << line << endl;
}
else {
if(skip == 0) {
skip = 2; // Skip the next two lines also
}
else {
--skip;
}
}
}
Related
For one of my options, I had to add a row of data to my struct array, I was able to update the array but it does not update the actual array. So I am trying to update my struct array by passing it as a reference. I placed the '&' sign before the name of the variable, but all my indexes within the function errored.. I'm still a newbie to programing and I'm not "allowed " to use any vectors according to my Professor. . I looked online and placed the '&' on the function name as well as on the prototype. I also changed it from void to the "data type" to return the updated array, but no luck... I hope this comes out clear....
#include<iostream>
#include<iomanip>
#include<fstream>
using namespace std;
struct Data {
string first_name;
string last_name;
int employee_id;
string phone_number;
};
void readFile( ifstream& , string, Data [],int&);
void getEmployeeDetail(Data [], int&);
void getEmployeeLast(Data [], int&);
Data getAddEmployee(Data &, int&);
void getRemoveEmployee();
void getManagerOnly();
void getStaffOnly();
const int SIZE = 15;
Data employee[SIZE];
int main() {
ifstream inputFile;
ofstream outputFile;
int count = 0;
int selection;
const int EMPLOYEE_DETAIL = 1,
EMPLOYEE_LAST = 2,
ADD_EMPLOYEE = 3,
REMOVE_EMPLOYEE = 4,
MANAGER_ONLY = 5,
STAFF_ONLY = 6,
QUIT = 7;
readFile( inputFile ,"employeeData.txt", employee,count);
do {
cout << "\t Please select your option.\n"
<< "1. List all employee details\n"
<< "2. List employee by last name\n"
<< "3. Add a new employee\n"
<< "4. Remove an employee\n"
<< "5. Show all managers only\n"
<< "6. Show all staff only\n"
<< "7. Quit\n"
<< "Please enter your selection.\n" << endl;
cin >> selection;
while (selection < EMPLOYEE_DETAIL || selection > QUIT) {
cout << " Pleasse enter a valid selection.\n";
cin >> selection;
}
switch (selection) {
case EMPLOYEE_DETAIL:
getEmployeeDetail(employee,count);
break;
case EMPLOYEE_LAST:
getEmployeeLast(employee, count);
break;
case ADD_EMPLOYEE:
getAddEmployee(employee, count);
break;
case REMOVE_EMPLOYEE:
getRemoveEmployee();
break;
case MANAGER_ONLY:
getManagerOnly();
break;
case STAFF_ONLY:
getStaffOnly();
break;
case QUIT:
cout << "Program ending\n";
break;
}
} while (selection != QUIT);
system("pause");
return(0);
}
void readFile(ifstream& inputFile, string data, Data employee[],int &count) {
inputFile.open(data);
if (!inputFile) {
cout << " Error in opening file\n";
exit(1);
}
else {
while (!inputFile.eof()) {
inputFile >> employee[count].first_name;
inputFile >> employee[count].last_name >> employee[count].employee_id >> employee[count].phone_number;
count++;
}
inputFile.close();
}
return;
};
void readFile(ifstream& inputFile, string data, Data employee[],int &count) {
inputFile.open(data);
if (!inputFile) {
cout << " Error in opening file\n";
exit(1);
}
else {
while (!inputFile.eof()) {
inputFile >> employee[count].first_name;
inputFile >> employee[count].last_name >> employee[count].employee_id >> employee[count].phone_number;
count++;
}
inputFile.close();
}
return;
};
void getEmployeeDetail( Data employee[], int& count) {
cout << "Firt Name" << "\t" << "Last Name " << "\t" << "Employee ID " << "\t" << "Phone Number \n";
cout << "--------------------------------------------------------------------------\n";
for(int i =0; i < count; i++)
cout <<employee[i].first_name<<"\t\t"<<employee[i].last_name<<"\t\t"<<employee[i].employee_id<<"\t\t"<<employee[i].phone_number<< "\n ";
cout << endl;
}
void getEmployeeLast(Data employee[], int& count) {
string searchName;
cout << "Please enter the last name of the employee you want to search for.\n";
cin >> searchName;
/*
for (int i = 0; i < count; i++)
if (searchName ==employee[i].last_name) {
cout << employee[i].last_name;
}
*/
string matchString = searchName;
for (int i = 0; i < count; i++) {
if (employee[i].last_name.find(matchString, 0) != std::string::npos) {
cout << employee[i].last_name << endl;
}
else {
cout << "No employee was located with that name.\n";
exit(1);
}
}
}
Data getAddEmployee(Data &employee, int& count) {
string firstName, lastName, phoneNumber;
int employeeID, size;
for (int i = 0; i < count; i++)
cout << employee[i].first_name << "\t\t\t" << employee[i].last_name << "\t\t" << employee[i].employee_id << "\t\t" << employee[i].phone_number << "\n ";
cout << endl;
cout << count <<"\n";
size = count + 1;
cout << size << "\n";
cout << "Please enter the new employee First Name.\n";
cin >> firstName;
cout << "Please enter the new employee Last Name.\n";
cin >> lastName;
cout << "Please enter the new employee's ID.\n";
cin >> employeeID;
cout << "Please enter the new employee Phone Number.\n";
cin >> phoneNumber;
employee[10].first_name = firstName;
employee[10].last_name = lastName;
employee[10].employee_id = employeeID;
employee[10].phone_number = phoneNumber;
for (int i = 0; i < size; i++) {
cout << employee[i].first_name << "\t\t\t" << employee[i].last_name << "\t\t" << employee[i].employee_id << "\t\t" << employee[i].phone_number << "\n ";
cout << endl;
}
return employee;
}
First of all, your naming could be better. Like employeeList instead employee to specify its a list/array of employee, also addEmployee instead of getAddEmployee.
Second, instead of pasting whole code, it's better to paste the relevant block of code based on your question to make it clearer.
The solution is, your array is basically already on global scope, you don't need to pass it. Can just directly modify the array.
struct Data {
string first_name;
string last_name;
int employee_id;
string phone_number;
};
void addEmployee();
const int SIZE = 15;
Data employeeList[SIZE];
int current = 0;
int main(){
Data emp1 = {"John", "Doe", 100, "12345"};
employeeList[0] = emp1;
current++;
addEmployee();
for(int i=0; i<current; i++){
Data emp = employeeList[i];
cout<<i+1<<" "<<emp.first_name<<" "<<emp.phone_number<<endl;
}
}
void addEmployee(){
Data emp2 = {"Sam", "Smith", 200, "67890"};
employeeList[current] = emp2;
current++;
}
Can try it here: https://onlinegdb.com/drhzEOpis
Ok. I'm trying to finish writing to a file and then reading from a file but I keep getting an error when I start the void readData(void).The error is "no matching token found." What could I do to make this work/ make it easier?
I'm not understanding how to use the void function, I think. I'm sure there are more issues because when I remove void readData(void) the error moves to void writeData(void).
//Specification: Append and display records in a address database
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
void menu(void);
void writeData(void);
void readData(void);
ifstream infile;
string cont = "Y";
string name;
string street;
string city;
string state;
string zip;
string choice;
const char FileName[] = "TestAddress.txt";
ofstream outfile("TestAddress.txt", ios::app);
int main() {
menu();
writeData();
readData();
return 0;
} //end main
void menu(void) {
cout << "Would you like to add to the records, display them, or exit?\n";
cout << "Enter a to add, d to display, or e to exit";
cin >> choice;
}
//allow user to choose to append records, display records or exit the program
//end menu
void writeData(void) {
while (choice != "a") {
cout << "Enter the address name: ";
getline(cin, name);
cout << "Enter the house number and street: ";
cin >> street;
cout << "Enter the city: ";
cin >> city;
cout << "Enter the state: ";
cin >> state;
cout << "Enter the zip code: ";
cin >> zip;
outfile << name << "#" << street << city << "#" << state << "#" << zip << endl;
cin.ignore();
cout << "Do you want add another addressor exit? (a/e)";
getline(cin, choice);
}
outfile.close();
//Write the Address Info to a file
//loop while user still has data to write to file
//eg outStream<<name<<”#”; //where # is the delimiter
}
//end write data
void readData(void) {
//read data from a file
//use the split function to break a
//deliminated line of text into fields
infile.open("TestAddress.txt");
ifstream inMyStream("TestAddress.txt");
while (choice != "d") {
if (inMyStream.is_open()) {
//set character to use as a line between record displays
string recBreaks = "#";
recBreaks.assign(20, '#');
int fieldCount = 0; //keep track of the number of fields read
int recordCount = 1; //keep track of the number of records read
//read the first field
fieldCount = 1;
string fieldBuffer;
getline(inMyStream, fieldBuffer, '#');
while (!inMyStream.eof()) {
//display the field
switch (fieldCount) {
case 1:
cout << recBreaks << endl;
cout << "record # " << recordCount << endl;
cout << "Name...." << fieldBuffer << endl; break;
case 2:
cout << "Street.." << fieldBuffer << endl; break;
case 3:
cout << "City...." << fieldBuffer << endl; break;
case 4:
cout << "State..." << fieldBuffer << endl; break;
case 5:
cout << "Zip....." << fieldBuffer << endl;
fieldCount = 0;
recordCount++; break;
}
//read the next field
getline(inMyStream, fieldBuffer, '#');
fieldCount++;
}
cout << recBreaks << endl;
inMyStream.close();
}//end read data
}
This program is supposed to call a read and write function from a menu, ask for inputs, save those inputs to a file then output the data to the screen. The menu works but I can only write to the file and save the data and exit. I cannot read or output what is saved to the file. Any help with this will be greatly appreciated. I should have three working functions, main(), writeData(), and readData().
#include < iostream >
#include < fstream >
#include < string >
using namespace std;
void menu(void);
void writeData(void);
void readData(void);
const char FileName[] = "TestAddress.txt";
string choice;
int main()
{
menu();
return 0;
}
void menu(void)
{
while (choice != "Q") {
cout << "What would you like to do?\nA. Read the existing data:\nB. Write new data to the list:\nQ.Quit\n";
cin >> choice;
if (choice == "A") {
readData();
}
else if (choice == "B") {
writeData();
}
else
break;
}
}
void writeData(void)
{
ofstream outFile("testAddress.txt");
string name;
string street;
string city;
string state;
int zip;
string cont = "y";
ifstream inFile;
while (cont != "q") {
cout << "Please enter the name:\n";
getline(cin, name);
cout << "Please enter the street:\n";
getline(cin, street);
cout << "Please enter the city:\n";
getline(cin, city);
cout << "Please enter the state:\n";
getline(cin, state);
cout << "Please enter the zip code:\n";
cin >> zip;
outFile << name << street << "#" << city << state << zip << endl;
cin.ignore();
cout << "Would you like to continue? Type q to quit:";
getline(cin, cont);
cin.ignore();
}
outFile.close();
inFile.open("testAddress.txt");
string fieldBuffer;
if (inFile.is_open()) {
while (inFile.eof()) {
getline(inFile, fieldBuffer, ',');
cout << fieldBuffer;
cout << endl;
}
}
}
//use # sign for delimiter
void readData(void)
{
ifstream inMyStream(FileName);
if (inMyStream.is_open()) {
string recBreaks = "";
recBreaks.assign(20, '*');
int fieldCount = 0;
int recordCount = 1;
fieldCount = 1;
string fieldBuffer;
getline(inMyStream, fieldBuffer, '#');
while (inMyStream.eof()) {
switch (fieldCount) {
case 1:
cout << recBreaks << endl;
cout << "Record #" << recordCount << endl;
cout << "Name...." << fieldBuffer << endl;
break;
case 2:
cout << "Street...." << fieldBuffer << endl;
break;
case 3:
cout << "City...." << fieldBuffer << endl;
break;
case 4:
cout << "State...." << endl;
break;
case 5:
cout << "Zip Code...." << endl;
fieldCount = 0;
recordCount++;
break;
getline(inMyStream, fieldBuffer, '#');
fieldCount++;
}
cout << recBreaks << endl;
inMyStream.close();
}
}
}
I have fixed a number of errors in this code, THANX to all who commented! Everything is working now except the readData function. When I input data to the file and run the readData function I get an infinite loop. Is there a break statement out of place?
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
void menu(void);
void writeData(void);
void readData(void);
const char FileName[] = "TestAddress.txt";
string choice;
int main()
{
menu();
return 0;
}
void menu(void)
{
while (choice != "Q")
{
cout << "What would you like to do?\nA. Read the existing data:\nB. Write new data to the list:\nQ.Quit\n";
cin >> choice;
if (choice == "A")
{
readData();
}
else if (choice == "B")
{
writeData();
}
else
break;
}
}
void writeData(void)
{
ofstream outFile("TestAddress.txt");
string name;
string street;
string city;
string state;
int zip;
string cont = "y";
ifstream inFile;
while (cont != "q")
{
cout << "Please enter the name:\n";
cin.ignore();
getline(cin, name);
cout << "Please enter the street:\n";
getline(cin, street);
cout << "Please enter the city:\n";
getline(cin, city);
cout << "Please enter the state:\n";
getline(cin, state);
cout << "Please enter the zip code:\n";
cin >> zip;
outFile << name<< "#" << street<< "#"<< city << "#" << state << "#" << zip << "#" << endl;
cin.ignore();
cout << "Would you like to continue? Type q to quit:";
getline(cin, cont);
cin.ignore();
}
outFile.close();
inFile.open("TestAddress.txt");
string fieldBuffer;
if (inFile.is_open())
{
while (!inFile.eof())
{
getline(inFile, fieldBuffer, '#');
cout << fieldBuffer;
cout << endl;
}
}
}
//use # sign for delimiter
void readData(void)
{
ifstream inMyStream(FileName);
if (inMyStream.is_open())
{
string recBreaks = "";
recBreaks.assign(20, '*');
int fieldCount = 0;
int recordCount = 1;
fieldCount = 1;
string fieldBuffer;
getline(inMyStream, fieldBuffer, '#');
while (!inMyStream.eof())
{
switch (fieldCount)
{
case 1:
cout << recBreaks << endl;
cout << "Record #" << recordCount << endl;
cout << "Name...." << fieldBuffer << endl;
break;
case 2:
cout << "Street...." << fieldBuffer << endl;
break;
case 3:
cout << "City...." << fieldBuffer << endl;
break;
case 4:
cout << "State...." << fieldBuffer << endl;
break;
case 5:
cout << "Zip Code...." << fieldBuffer << endl;
fieldCount = 0;
recordCount++;
break;
getline(inMyStream, fieldBuffer, '#');
fieldCount++;
}
cout << recBreaks << endl;
inMyStream.close();
}
}
}
I wrote a little c++ class that read a ASCII files each line can have
4 element (int, string, int, float)
1000 I 100 10.0
or 3 (int, string, int)
1001 E 100
which means that if the string is an I the fourth element exist, not otherwise.
I am trying to write a class to insert rows.
The code asks the user to insert the object properties and then writes to file
I want to add a check
if the string is "I" then should ask to insert the float otherwise leave empty.
#include <iostream>
#include <fstream>
using namespace std;
void writing();
void deleting();
void searching();
class orderbook
{
string text;
private:
double Price = (double) NULL;
public:
int Timestamp = 0;
string Operation;
long int Id;
orderbook(){};
orderbook(const string& name)
{
ifstream infile;
infile.open(name);
if(!infile.good())
{
cout << "File is not open";
}
else
{
string line;
while(getline(infile,line))
text = text + line + '\n';
}
};
string contetns()
{
return text;
};
void SetPrice(double x = NULL)
{
Price = x;
}
float GetPrice()
{
return Price;
}
void insert(const string& name)
{
long int Id;
double Price;
float a;
orderbook ob;
cout << "Please enter Timestamp : ";
cin >> ob.Timestamp;
cout << "Please enter the Operation type: ";
cin >> ob.Operation;
cout << "Please enter Id : ";
cin >> ob.Id;
if (ob.Operation == 'I')
{
cout << "Pleae enter the Price of order: ";
cin >> a;
ob.SetPrice(a);
}
else{
ob.SetPrice()
}
ofstream myfile;
myfile.open(name, ios::app | ios::out);
myfile << ob.Timestamp << "\t";
myfile << ob.Operation << "\t";
myfile << ob.Id << "\t";
// if (ob.GetType().GetProperty("Price") != null )
// {
// myfile << ob.GetPrice() << endl;
// }
// else
// {
// myfile << endl;
// }
myfile.close();
}
void deleting()
{
string line, record;
cout << "Please Enter the name of record you want to delete: ";
cin >> record;
ifstream myfile;
ofstream temp;
myfile.open("record.txt");
temp.open("temp.txt");
while (getline(myfile, line))
{
if (line.substr(0, record.size()) != record)
temp << line << endl;
}
cout << "The record with the name " << record << " has been deleted if it exsisted" << endl;
myfile.close();
temp.close();
remove("record.txt");
rename("temp.txt", "record.txt");
}
};
int main()
{
string filename;
cout<<"Please enter the full name of the data file: ";
cin>>filename;
orderbook ob(filename);
cout << "content: " << endl << ob.contetns() << endl;
ob.insert(filename);
cout << "content: " << endl << ob.contetns() << endl;
ob.deleting();
cout << "content: " << endl << ob.contetns() << endl;
}
I get this error
class_student.cpp:64:20: error: invalid operands to binary expression
('string'
(aka 'basic_string, allocator >') and 'int') if (ob.Operation == 'I')
So i set my array value as 100 and when i want to display my array,the others array with no value will also display. Any ways to remove it ? Thanks!
#include<iostream>
#include<iomanip>
#include<cstring>
#include<string>
#include<fstream>
#include<limits>
#include<sstream>
using namespace std;
char add();
char list();
struct Book //structure for the book
{
char title[50];
char author[50];
int price;
void display() {
cout << "Name:" << title << endl
<< "Author:" << author<< endl
<< "Price:" << price << endl << endl;
}
};
Book book[100];
void main()
{
int selection;
do {
cout << "Activity Selection: " << endl;
cout << "1. Add book" << endl;
cout << "2. List all books" << endl;
cout << "3. Search book" << endl;
cout << "4. Check total book purchased and total spent" << endl;
cout << "5. Quit" << endl;
cout << "Please enter your selection(1/2/3/4/5): ";
cin >> selection;
cin.ignore();
switch (selection)
{
case 1:
add();
break;
case 2:
list();
break;
case 3:
cout << "number 3" << endl;
break;
case 4:
cout << "number 4" << endl;
break;
default:
exit(1);
break;
}
} while (selection <= 4);
system("pause");
}
char add()
{
int i;
ofstream outFile;
outFile.open("Records.dat", ios::app);
if (!outFile.is_open())
{
cout << "Can’t open file.";
system("pause");
exit(1);
}
cout << "Please enter the book title:";
cin.getline(book[i].title, 51);
cout << "Please enter the author name of the book:";
cin.getline(book[i].author, 51);
cout << "Please enter the price of the book RM: ";
cin >> book[i].price;
cout << "\nThe book\""<< book[i].title <<"\"has been added to the system.\n" <<
endl;
outFile << book[i].title << "," << book[i].author << "," << book[i].price <<
endl;
outFile.close();
}
char list() //second solution but still doesnt work need some fixing here i think
{
int i;
string line, token;
ifstream inFile;
inFile.open("Records.dat", ios::in);
if (!inFile.is_open())
{
cout << "File could not open" << endl;
system("pause");
exit(1);
}
char data;
while (getline(inFile,line))
{
inFile.get(data);
if (!(data == 0));
cout << data;
}
cout << endl;
inFile.close();
}
when i debug something like this come out :
ss
this is the second solution i come out with but still does not work
char list()
{
int i , count = 0;
string line, token;
ifstream inFile;
inFile.open("Records.dat", ios::in);
if (!inFile.is_open())
{
cout << "File could not open" << endl;
system("pause");
exit(1);
}
char data;
while (getline(inFile, line))
{
stringstream ss(line);
getline(ss, token, ',');
stringstream(token) >> book[i].title;
getline(ss, token, ',');
stringstream(token) >> book[i].author;
getline(ss, token, ',');
stringstream(token) >> book[i].price;
i++;
}
cout << endl;
inFile.close();
for (int count = 0; count < i; count++)
book[i].display();
}
The problem is i dont really know how to display the array using the dat file and i successfully display it but theres error
You are reading the CSV as a text file and just printing it.
So, the solution is to make a record class, read it from stream, then check it whether it is empty or no.
#include <iostream>
#include <sstream>
using namespace std;
class Record {
private:
std::string title;
std::string shortTitle;
int number;
public:
Record(std::string title, std::string shortTitle, int number): title(title),
shortTitle(shortTitle),
number(number){
}
inline std::string getTitle() const { return title; }
inline std::string getShortTitle() const { return shortTitle; }
inline int getNumber() const { return number; }
};
// Make this function capable of handling any stream by making it template
// (anything that could be passed to a `getline` as a first parameter and have
// an operator >> overloaded that accepts an integer)
template<typename Stream>
Record readFromStream(Stream &str) {
std::string title;
std::string shortTitle;
int number;
std::string line;
// Read a line from the stream
getline(str, line);
// Make a new stream from that line
std::stringstream lineStream(line);
// Read until the comma
getline(lineStream, title, ',');
getline(lineStream, shortTitle, ',');
// The last one is an integer, simply read it
lineStream >> number;
return Record(title, shortTitle, number);
}
int main() {
Record rec = readFromStream(cin);
// Check for emptiness, if is NOT empty write it
if (rec.getTitle().size() && rec.getShortTitle().size()) {
cout << rec.getTitle() << "\n";
cout << rec.getShortTitle() << "\n";
cout << rec.getNumber() << "\n";
}
return 0;
}