Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 2 years ago.
Improve this question
I need some help about class functions because whatever i tried gave me errors. I tried to create pointers which holds my main variables but still couldn't figure out even i read a lot of topics and watched videos about them. I have something wrong with my logic but can not find that actually. After i get my arrays i want to use them in class part. For example when i switch case to 0 i want to show all contacts. For that i have to carry my arrays into the class but i couldn't. I will use them for editing, adding persons or deleting them. So i need my counters too. As i said. If there is a way can someone please at least give an example for me? Thanks a lot.
#include <iostream>
#include <string>
#include <conio.h>
#include <fstream>
#include <stdio.h>
#include <stdlib.h>
using namespace std;
void printline(char, int);
class person{
private:
int order;
string name;
string surname;
string phonenumber;
public:
void setName(string isim){
name=isim;
}
string getName(){
return name;
}
void setSurname(string soyad){
surname=soyad;
}
string getSurname(){
return surname;
}
void setPhonenumber(string numara){
phonenumber=numara;
}
string getPhonenumber(){
return phonenumber;
}
};
int main() {
person kisi;
FILE* myFile;
int i = 0;
int j = 0;
int k = 0;
int choice;
int mOrder;
char* mName[20],mSurname[20],mPhone[20];
myFile = fopen("phoneData.txt", "r");
if (myFile != NULL)
while (fscanf(myFile, "%d%s%s%s", &mOrder, mName, mSurname, mPhone) != EOF)
i++;
fclose(myFile);
// this is where we find i and now i can create my arrays.
int *orderArray;
char *nameArray[i];
char *SurnameArray[i];
char *PhoneArray[i];
orderArray = (int *) malloc(i * sizeof(int));
for (int n=0;n<i;n++)
{
nameArray[n] = (char*) malloc(20 * sizeof(char));
SurnameArray[n] = (char *) malloc(20 * sizeof(char));
PhoneArray[n] = (char *) malloc(20 * sizeof(char));
}
myFile = fopen("phoneData.txt", "r");
if (myFile == NULL)
{
printf("There is no file.\n");
}
else
{
int m=0;
while (fscanf(myFile, "%d%s%s%s", &orderArray[m], nameArray[m], SurnameArray[m], PhoneArray[m]) != EOF){
m++; //this is the part where we read the txt file correctly and seperate it into the parts.
}
fclose(myFile);
//i made this part just to see if my arrays work or not. They worked.
/*
for (int j=0;j<i;j++)
{
cout<<orderArray[j]<<" "<<nameArray[j]<<" " << SurnameArray[j]<<" "<<PhoneArray[j]<<endl;
}
*/
}
// menü burası olacak
/*
cout << "--- Welcome to the PhoneBook ---" << endl;
printline('-', 32);
cout << "0. Show all the contacts on PhoneBook" << endl;
cout << "1. Add a contact to PhoneBook" << endl;
cout << "2. Search a contact on PhoneBook" << endl;
cout << "3. Edit a contact on PhoneBook" << endl;
cout << "4. Delete a contact from PhoneBook\n" << endl;
cout << "Please make a choice: " << endl;
cin >> choice;
*/
//switch cases will be there.
/*
switch(choice){
case 0:
showContacts();
break;
case 1:
addContacts();
break;
case 2:
searchContacts();
break;
case 3:
editContacts();
break;
case 4:
deleteContacts();
break;
}
*/
return 0;
}
void printline(char ch, int size)
{
for(int i=0; i<size; i++)
cout << ch;
cout << "\n";
}
Please take this as one example of possible millions of other solutions.
I will edit the answer later and put explanations and comments. Now I nned to do other stuff
#include <iostream>
#include <fstream>
#include <sstream>
#include <algorithm>
#include <iterator>
#include <vector>
#include <string>
struct Person {
unsigned int index{};
std::string name{};
std::string surname{};
std::string phoneNumber{};
friend std::istream& operator >> (std::istream& is, Person& p) {
if (std::string line{}; std::getline(is, line)) {
std::istringstream iss{ line };
iss >> p.index >> p.name >> p.surname >> p.phoneNumber;
}
return is;
}
friend std::ostream& operator << (std::ostream& os, const Person& p) {
return os << p.index << '\t' << p.name << '\t' << p.surname << '\t' << p.phoneNumber;
}
};
struct PhoneBook {
std::vector<Person> persons{};
friend std::istream& operator >> (std::istream& is, PhoneBook& p) {
p.persons.clear();
std::copy(std::istream_iterator<Person>(is), {}, std::back_inserter(p.persons));
return is;
}
friend std::ostream& operator << (std::ostream& os, const PhoneBook& p) {
std::copy(p.persons.begin(), p.persons.end(), std::ostream_iterator<Person>(os, "\n"));
return os;
}
};
struct PhoneBookAdministration {
PhoneBook phoneBook{};
std::string phoneBookFileName{};
void load(const std::string& fileName) {
phoneBookFileName = fileName;
if (std::ifstream phoneBookFileStream(fileName); phoneBookFileStream)
phoneBookFileStream >> phoneBook;
else std::cerr << "\nError: Could not open " << fileName << "\n\n";
}
void saveAs() {
std::cout << "\n\nSave As\n\nPlease enter a filename:\n";
if (std::string fileName{}; std::cin >> fileName) {
phoneBookFileName = fileName;
save();
}
}
void save() const {
if (std::ofstream phoneBookFileStream(phoneBookFileName); phoneBookFileStream) {
phoneBookFileStream << phoneBook;
}
else std::cerr << "\nError: Could not open " << phoneBookFileName << "\n\n";
}
void show() const {
std::cout << "\n\nContents of phone book:\n" << phoneBook << "\n\n";
}
void addEntry() {
std::cout << "\n\nAdd entry to phone book\nEnter name, surname and phone number:\n";
if (std::string n{}, s{}, p{}; std::cin >> n >> s >> p)
phoneBook.persons.emplace_back(phoneBook.persons.size(), n, s, p);
}
void searchContact() const {
std::cout << "\n\nSearch entry in phone book\nEnter name to search for:\n";
if (std::string n{}; std::cin >> n) {
if (auto pos = std::find_if(phoneBook.persons.begin(), phoneBook.persons.end(), [&n](const Person& p) {return p.name == n; }); pos != phoneBook.persons.end())
std::cout << "\n\nPerson '" << n << "' found:\n" << *pos << '\n';
else std::cout << "\n\nPerson '" << n << "' not found\n";
}
}
void editContact() {
std::cout << "\n\nEdit contact. Here is the phone book\n" << phoneBook << "\n\nPlease enter the index of an entry:\n";
if (size_t index{}; std::cin >> index && index < phoneBook.persons.size()) {
std::cout << "\n\nEnter name, surname and phone number:\n";
if (std::string n{}, s{}, p{}; std::cin >> n >> s >> p)
phoneBook.persons[index] = { phoneBook.persons[index].index, n, s, p };
}
else std::cout << "\n\nError, problem with given index\n";
}
void deleteContact() {
std::cout << "\n\nDelete contact. Here is the phone book\n" << phoneBook << "\n\nPlease enter the index of an entry:\n";
if (size_t index{}; std::cin >> index && index < phoneBook.persons.size())
phoneBook.persons.erase(phoneBook.persons.begin() + index);
}
};
int main() {
PhoneBookAdministration pba{};
pba.load("r:\\pb.txt");
bool runProgram{ true };
while (runProgram) {
// Show menu
std::cout <<
"\n\n\nMain Menu\n"
"You have the follwing options:\n"
" 1 - Save\n"
" 2 - Save as\n"
" 3 - Show\n"
" 4 - Add Entry\n"
" 5 - Search\n"
" 6 - Edit entry\n"
" 7 - Delete entry\n"
" 0 - Exit program\n\n"
"Please select:\n";
if (int selection{}; std::cin >> selection) {
switch (selection) {
case 1:
pba.save();
break;
case 2:
pba.saveAs();
break;
case 3:
pba.show();
break;
case 4:
pba.addEntry();
break;
case 5:
pba.searchContact();
break;
case 6:
pba.editContact();
break;
case 7:
pba.deleteContact();
break;
case 0:
std::cout << "\n\nExiting . . .\n\n";
runProgram = false;
break;
default:
std::cout << "\n\nWrong selection. Please try again\n";
break;
}
}
else std::cerr << "\n\nError: Problem with selection\n";
}
return 0;
}
Related
I have a program that takes input for names and outputs the last names in a string. The task I have now is to include FileIO in it. Specifically, "get user input for the filename, and then read the names from the file and form the last name string."
When I run the program, the console will show the name string from the text file. But only initially. As you keep entering names, that string disappears. Also, my user input for file name seems to be doing nothing, because I can enter anything and it still show the string of last names from the text file.
Here is what I have so far. Included all of it, just to make sure.
#include <iostream>
#include <string>
#include <vector>
#include <sstream>
#include <fstream>
using namespace std;
// function declerations
int Menu();
void getName(vector<string> &names, int &count);
void displayName(vector<string> &names, int count);
string getLastNames(vector<string> &names, int count);
int main()
{
vector<string> names;
int count = 0;
int choice = Menu();
ifstream File;
string line;
cout << "Enter file name: ";
getline(cin,line);
File.open("File.txt");
while(File.good()){
getline(File,line);
cout << line << endl;
}
File.close();
while (choice != 0)
{
// switch statement to call functions based on users input
switch (choice)
{
case 1: {
getName(names, count);
} break;
case 2: { displayName(names, count); } break;
case 3: {
cout << getLastNames(names, count) << endl;
} break;
case 0: {
return 0;
} break;
}
choice = Menu();
}
return 0;
}
// function definition for vector of strings
void getName(vector<string> &names, int &count)
{
string name;
// get input for name
cout << "Enter name: ";
getline(cin, name);
// find position of space in string
int pos = name.find(' ');
// reverse order of name
if(pos != -1) {
string first = name.substr(0, pos);
string last = name.substr(pos+1);
name = last + "," + first;
}
// add name to end of vector
names.push_back(name);
count++;
}
// give user option of what to do
int Menu() {
int choice;
cout << "1. Add a name" << endl;
cout << "2. Display names " << endl;
cout << "3. Show all Last Names" << endl;
cout << "0. Quit" << endl;
cout << "Enter a option: ";
cin >> choice;
// if outside of above choices, print 'choice not on list'
while (choice < 0 || choice > 3)
{
cout << "Choice not on list: ";
cin >> choice;
}
cin.ignore();
return choice;
}
// defining function that gets last names
string getLastNames(vector<string> &names, int count) {
stringstream ss;
for (int i = 0; i<count; i++)
{
int pos = names[i].find(',');
if (pos != -1) {
ss << "\"" << names[i].substr(0, pos) << "\", ";
} else {
ss << "\"" << names[i] << "\", ";
}
}
return ss.str();
}
// display the names
void displayName(vector<string> &names, int count)
{
if (count == 0)
{
cout << "No names to display" << endl;
return;
}
for (int i = 0; i<count; i++)
{
cout << names[i] << endl;
}
}
I'm not quite getting a structure search. I have a task, I need to search for students by full name, year of birth, group number or course number. I can search by group number or course number, but the search by full name and date of birth is problematic.
Here are my code and my input file. (I'm sorry if my code is unprofessional, I'm just learning and I need to pass this task, but I'm having no luck and I have no one to turn to for help)
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
struct Student
{
string name;
string yearob;
int course;
int group;
};
ostream& operator<<(ostream& out, const Student obj)
{
out << obj.name << " " << obj.yearob << " " << obj.group << " " << obj.course;
return out;
}
int main()
{
setlocale(LC_ALL, "");
int search = 0;
string name_s, yearob_s;
int course_s, group_s;
int chek = 1;
while (chek == 1)
{
cout << "Enter 1 to start, 0 to exit > ";
cin >> chek;
switch (chek)
{
case(0):
break;
case(1):
{
int leng = 0;
string s;
ifstream fle("input.txt");
while (getline(fle, s))
{
leng += 1;
}
Student* list = new Student[leng];
int a = 0;
fle.close();
ifstream file("input.txt");
string ss, buff;
while (getline(file, s))
{
buff.assign(s);
list[a].course = buff[0] - '0';
buff.erase(0, 2);
ss += buff[0];
ss += buff[1];
list[a].group = stoi(ss);
ss.clear();
buff.erase(0, 3);
for (int i = 0; i < 4; i++)
list[a].yearob += buff[i];
buff.erase(0, 5);
list[a].name.assign(buff);
a += 1;
buff.clear();
}
cout << "What parameter should be used to find students: 1 - by name, 2 - by year of birth, 3 - by course, 4 - by group number: ";
cin >> search;
switch (search) {
case(1):
cin >> name_s;
for (int i = 0; i <= leng; i++) {
if (list[i].name.find(name_s, 10)) {
cout << list[i].name << ", " << list[i].course << " course, " << list[i].group << " group, " << list[i].yearob << " year of birth; " << endl;
}
else {
continue;
}
}
case(2):
cin >> yearob_s;
for (int i = 0; i <= leng; i++) {
if (list[i].yearob.find(yearob_s, 5)) {
cout << list[i].name << ", " << list[i].course << " course, " << list[i].group << " group, " << list[i].yearob << " year of birth; " << endl;
}
else {
continue;
}
}
case(3): {
cin >> course_s;
for (int i = 0; i <= leng; i++) {
if (course_s == list[i].course) {
cout << list[i].name << ", " << list[i].course << " course, " << list[i].group << " group, " << list[i].yearob << " year of birth; " << endl;
}
else {
continue;
}
}
}
case(4):
cin >> group_s;
for (int i = 0; i <= leng; i++) {
if (group_s == list[i].group) {
cout << list[i].name << ", " << list[i].course << " course, " << list[i].group << " group, " << list[i].yearob << " year of birth; " << endl;
}
else {
continue;
}
}
}
file.close();
continue;
}
default:
{
cout << "Input error" << endl;
continue;
}
}
}
}
Input file:
2 01 1999 Cody Hoyt
2 01 2002 Danielle Robyn Diaz
3 01 1999 Mayra Marie Collins
2 05 2000 Marc Nunez
4 05 2000 Tricia Gilmore
5 04 2001 Dale Lucas
1 01 1998 Ruby Merritt
2 01 2001 Tabitha Jenkins
4 02 1995 George Kris Oneill
2 03 1999 Bonnie Blair
Just maybe a shorter version of your code. I provide it not as a solution to your main question (because the following code is pretty advanced), but as an example of how you could avoid repeating code and making big nested constructions.
Here I moved out the code of reading students from a file into a separate function, and inside it should easily read each student using operator>> from a file. Similarly you can define operator<< to specify in which format you want students to be printed.
The repetitive code of printing filtered students is moved into a single function, that iterates all students and prints only pass a given test. You then give this test as a lambda function in each branch of switch operator
#include <iostream>
#include <string>
#include <fstream>
#include <vector>
#include <functional>
using namespace std;
struct Student
{
string name;
string yearob;
int course;
int group;
};
ostream& operator<<(ostream& out, const Student& stud)
{
out << stud.name << ", " << stud.course << " course, " << stud.group << " group, " << stud.yearob << " year of birth; " << endl;
return out;
}
istream& operator>>(istream& in, Student& stud)
{
in >> stud.course >> stud.group >> stud.yearob >> stud.name;
return in;
}
vector<Student> read_students_file(const string& filename) {
vector<Student> students;
ifstream file(filename);
while (file)
{
students.push_back({}); // insert empty student
file >> students[students.size() - 1]; // fill student
}
file.close();
return students ;
}
void print_filtered(const vector<Student>& students, function<bool(const Student&)> should_print) {
for (const Student& student : students) {
if (should_print(student)) {
cout << student;
}
}
}
int main()
{
setlocale(LC_ALL, "");
while (true)
{
cout << "Enter 1 to start, 0 to exit > ";
int check;
cin >> check;
if (check == 0) {
break;
} else if (check != 1) {
continue;
}
vector<Student> students = read_students_file("input.txt");
cout << "What parameter should be used to find students: 1 - by name, 2 - by year of birth, 3 - by course, 4 - by group number: ";
int search_variant;
cin >> search_variant;
switch (search_variant) {
case(1): {
string find_name;
cin >> find_name;
print_filtered(students,
[&](auto& student){ return student.name == find_name; });
break;
}
case(2): {
string find_yearob;
cin >> find_yearob;
print_filtered(students,
[&](auto& student){ return student.yearob == find_yearob; });
break;
}
case(3): {
int find_course;
cin >> find_course;
print_filtered(students,
[&](auto& student){ return student.course == find_course; });
break;
}
case(4): {
int find_group;
cin >> find_group;
print_filtered(students,
[&](auto& student){ return student.group == find_group; });
break;
}
default: {
cout << "Input error" << endl;
continue;
}
}
}
}
I know this program is long, but any help would be much appreciated. When I try to read in an object from a file, I always end up with a segmentation fault. I've commented the line where the problem is. It's under 'case d' in the switch statement.
The objects I'm writing out the text file is polymorphic, which might be part of why I'm getting segmentation faults, but I'm not sure.
#include <iostream>
#include <string.h>
#include <vector>
#include <unistd.h>
#include <fstream>
#include "employee.h"
int main(int argc, char* argv[])
{
std::string command, choice, name;
float wage, percent;
int hours = 1;
std::ofstream file;
std::ifstream infile;
std::vector<Employee*> database;
while (command[0] != 'q')
{
clear();
menu();
std::cout << "Enter command: ";
std::cin >> command;
try
{
if(command.size() != 1)
throw "Not a character.";
else
{
switch(command[0])
{
case 'n':
std::cout << "Enter the name of the new employee: ";
//std::cin >> name;
std::cin.clear();
std::cin.ignore();
getline(std::cin, name);
std::cout << "Hourly (h) or salaried (s): ";
std::cin >> choice;
if(choice.size() != 1)
throw "Not a valid choice.";
else
if(choice == "h")
{
std::cout << "Enter hourly wage: ";
std::cin >> wage;
if(!wage)
throw "Not an option";
else{
Employee *emp = new PartTimeEmployee(wage, name);
database.push_back(emp);
continueWithProgram();
break;
}
}else if(choice == "s")
{
std::cout << "Enter salaried wage: ";
std::cin >> wage;
if(!wage)
throw "Not an option";
else{
Employee *emp = new FullTimeEmployee(wage, name);
database.push_back(emp);
continueWithProgram();
break;
}
}else{
throw "Not an option";
}
case 'c':
if(database.size() < 1)
throw "No employees in database.";
else
{
for(int i = 0; i < database.size(); i++)
{
std::cout << "Enter number of hours worked by " << database[i]->getName() << ": ";
std::cin >> hours;
std::cout << "Pay: $" << database[i]->computePay(hours) << std::endl;
}
continueWithProgram();
}
break;
case 'r':
std::cout << "Enter percentage to increase: ";
std::cin >> percent;
std::cout << "\nNew Wages\n---------" << std::endl;
for(int i = 0; i < database.size(); i++)
{
database[i]->raiseWage(percent);
std::cout << database[i]->getName() << "\t\t" << "$" << database[i]->toString(database[i]->getWage()) << std::endl;
}
continueWithProgram();
break;
case 'p':
std::cout << "\nEmployee Database: " << database[0]->count << " Personnel\n-----------------\n";
for(int i = 0; i < database.size(); i++)
{
std::cout << database[i]->getName() << std::endl;
}
continueWithProgram();
break;
case 'd':
infile.open("emp.txt", std::ios::in);
Employee *temp;
if(infile.is_open())
{
while(!infile.eof())
{
infile >> *temp; // PROBLEM IS HERE...
database.push_back(temp);
}
}else{
std::cout << "Error occured. File not found." << std::endl;
}
infile.close();
std::cout << "*Data has been downloaded*" << std::endl;
continueWithProgram();
break;
case 'u':
file.open("emp.txt", std::ios::trunc);
if(file.is_open()){
for(int i = 0; i < database.size(); i++)
file << *database[i];
}
file.close();
std::cout << "*Data has been uploaded*\n";
continueWithProgram();
break;
default:
if(command[0] == 'q')
break;
else
{
throw "Not a command";
break;
}
}
}
}catch(const char* message)
{
std::cout << message << std::endl;
std::cin.clear();
std::cin.ignore();
continueWithProgram();
}
catch(...)
{
std::cout << "Error occured." << std::endl;
std::cin.clear();
std::cin.ignore();
continueWithProgram();
}
}
return 0;
}
______________________________________________________-
Header File:
*This is where the operator overload is, which I'm sure is not part of the problem.
#include <iostream>
#include <fstream>
#include <string.h>
#include <vector>
#include <unistd.h>
class Employee
{
protected:
float wage;
std::string name;
public:
static int count;
Employee(float wage, std::string name)
{
this->wage = wage;
this->name = name;
count++;
}
virtual float getWage() = 0;
virtual void setWage(float wage) = 0;
virtual float computePay(int hours = 0) = 0;
virtual float raiseWage(float percent = 0) = 0;
virtual std::string toString(int value) = 0;
std::string getName(){return name;}
void setName(std::string name){this->name = name;}
friend std::ofstream& operator<<(std::ofstream &out, Employee &emp);
friend std::ifstream& operator>>(std::ifstream &in, Employee &emp);
};
class FullTimeEmployee : public Employee
{
public:
FullTimeEmployee(float annualSalary, std::string name) : Employee(annualSalary, name)
{
getWage();
}
float getWage() {return wage;}
void setWage(float wage) {this->wage = wage;}
float computePay(int hours = 0) {return (wage / 52);}
std::string toString(int value){return std::to_string(value) + "/year";}
float raiseWage(float percent = 0)
{
wage = wage + (wage * (percent / 100));
return wage;
}
};
class PartTimeEmployee : public Employee
{
public:
PartTimeEmployee(float wage, std::string name) : Employee(wage, name)
{
getWage();
}
float getWage() {return wage;}
void setWage(float wage) {this->wage = wage;}
std::string toString(int value){return std::to_string(value) + "/hour";}
float computePay(int hours)
{
if(hours <= 40)
return wage * hours;
else
{
hours -= 40;
return ((wage * 40) + ((wage * 1.5) * hours));
}
}
float raiseWage(float percent = 0)
{
wage = wage + (wage * (percent / 100));
return wage;
}
};
std::ofstream& operator<<(std::ofstream &out, Employee &emp)
{
out << emp.name << std::endl << emp.wage << std::endl;
return out;
}
std::ifstream& operator>>(std::ifstream &in, Employee &emp)
{
in >> emp.name;
in >> emp.wage;
return in;
}
int Employee::count = 0;
void menu()
{
std::cout << "-----------------------------------" << std::endl;
std::cout << "|Commmands: n - New Employee |" << std::endl;
std::cout << "| c - Compute Paychecks |" << std::endl;
std::cout << "| r - Raise Wages |" << std::endl;
std::cout << "| p - Print Records |" << std::endl;
std::cout << "| d - Download Data |" << std::endl;
std::cout << "| u - Upload Data |" << std::endl;
std::cout << "| q - Quit |" << std::endl;
std::cout << "-----------------------------------" << std::endl;
}
void clear() {std::cout << "\033[2J\033[1;1H";}
int continueWithProgram()
{
std::string anw;
while(anw[0] != 'y' || anw[0] != 'Y')
{
std::cout << "\nDo you want to continue?(y/n) ";
std::cin >> anw;
return 0;
if(anw.size() != 1)
{
throw "Not a character";
}else if (anw[0] == 'n' || anw[0] == 'N')
exit(0);
}
}
You must add subtype information (Ex: 'f' or 'p', denoting partime and fulltime) somewhere in your file-format. If you really want do deserialize a Pointer from the file you might change both operators.
(However I strongly recommend to use an other approach and fix memory leaks):
operator<< should first print an extra line consisting of just one character denoting the subtype of Employ that is serialized.
using PEmployee = *Employee;
std::ifstream& operator>>(std::ifstream &in, PEmployee &emp)
{
char subType;
float wage;
std::string name;
in >> subType;
in >> name; // FIXIT - we suspect file in not eof
in >> wage;
if(subType == 'f')
emp = new FullTimeEmploy(wage, name);
else
emp = new PartTimeEmploy(wage, name); // FIXIT: we suspect subType == 'p'
return in;
}
And in the while-Loop beneath case 'd': you should call the new operator by infile >> temp;
I hope this works and answers your question.
I do not recommend this approach, calling new as side-effect from an operator rises the question who (which part of the Prog) is responsible for cleaning up (i.e. calling delete). It might work in small Progs but usually it will results in a mess.
Memory leaks: If you use new and delete, be always aware where in Your Prog the allocated memory will be freed. It is not done by the Run-time environment, C++ is not a managed language. HINT: std::vector<Employee*> wont call delete on the stored pointers, it just frees its workload (Employee*). It's the pointer itself not the pointee, i.e. the Object you accuired with new .
PS:
A more straight forward aproach is to change only the operator<< and evaluate the subtype inside the while-Loop beneath case 'd': First read the subtype-char, switch subtype, create the according subclass (Ex: temp = new PartTimeEmployee(); and call the unchanged operator>> with the newly created temp.
For this approach you'll need standart Constructors like PartTimeEmployee::PartTimeEmployee(); for all your subclasses.
I have been having some trouble on my code for my final project. I have looked everwhere and I am having a hard time so I thought I would ask on here. I need to make sure that when all the names are listed in this phonebook that they will come out in alphabetical order but as of yet I am unsure how to do that. Here is the program that i currently have! Thank you!
#include <iostream>
#include <iomanip>
#include <fstream>
#include <string>
using namespace std;
struct Contact {
string name, number, notes;
};
Contact contactList[100];
int rec_num = 0;
int num_entries;
string toUpper (string S) {
for (int i= 0; i < S.length(); i++)
S[i] = toupper(S[i]);
return S;
}
void ReadFile () {
string S;
fstream input("PhoneData.txt");
while (!input.eof() && !input.fail()){
input >> contactList[rec_num].name >> contactList[rec_num].number;
getline(input, S);
contactList[rec_num].notes = S;
rec_num++;
}
cout << "Book read." << endl;
num_entries = rec_num;
input.close();
return;
}
// stores phonebook for future runs of the program
void StoreFile () {
fstream F ("PhoneData.txt");
rec_num = 0;
while (rec_num < num_entries){
F << contactList[rec_num].name << " " << contactList[rec_num].number << " " << contactList[rec_num].notes << " " << endl;
rec_num++;
}
cout << "Phonebook stored." << endl;
return;
}
// adds contact
void add_name(string name, string number, string notes){
contactList[num_entries].name = name;
contactList[num_entries].number = number;
contactList[num_entries].notes = notes;
num_entries++;
return;
}
// finds contact
void retrieve_name(string name){
for (int i = 0; i < num_entries; i++){
if (toUpper(contactList[i].name) == toUpper(name)) {
cout << "Phone Number: " << contactList[i].number << endl << "Notes: " << contactList[i].notes << endl;
return;
}
}
cout << "Name not found" << endl;
return;
}
// updates contact info
void update_name(string name){
string new_number;
string new_notes;
cout<<"New Phone Number"<<endl;
cin>> new_number;
cout<<"New Notes"<<endl;
cin>> new_notes;
for (int i = 0; i < num_entries; i++){
if (toUpper(contactList[i].name) == toUpper(name)) {
contactList[i].number = new_number;
contactList[i].notes = new_notes;
return;
}
}
}
// deletes contact
void delete_name(string name){
int INDEX=0;
for (int i = 0; i < num_entries; i++){
if (toUpper(contactList[i].name) == toUpper(name)) {
INDEX=i;
for ( int j=INDEX; j < num_entries; j++ ){
contactList[j].name = contactList[j+1].name;
contactList[j].number = contactList[j+1].number;
contactList[j].notes = contactList[j+1].notes;
}
}
}
return;
}
void listAllContacts() {
int i = 0;
while (i < num_entries) {
cout << "-- " << contactList[i].name << " " << contactList[i].number << endl << "-- " << contactList[i].notes << endl << endl;
i++;
}
}
int main(){
string name, number, notes;
string FileName;
char command;
FileName = "PhoneData.txt";
ReadFile ();
cout << "Use \"e\" for enter, \"f\" for find, \"l\" for list, \"d\" for delete, \"u\" for update, \"s\" for send message, \"q\" to quit." << endl << "Command: ";
cin >> command;
while (command != 'q'){
switch (command){
case 'e': cin >> name; cout << "Enter Number: ";
cin >> number; cout << "Enter Notes: ";
cin.ignore(); getline(cin, notes);
add_name(name, number, notes); break;
case 'f': cin >> name; retrieve_name(name); break;
case 'l':
listAllContacts(); break;
case 'u': cin>> name; update_name (name);break;
case 'd' : cin>> name; delete_name (name); break;
}
cout << "\nCommand: "; cin >> command;
}
StoreFile();
cout << "All set !";
return 0;
}
Given
Contact contactList[100];
int num_entries;
you can use std::sort to sort the list of contacts. std::sort has two forms. In the first form, you can use:
std::sort(contanctList, contactList+num_entries);
if you define operator< for Contact objects.
In the second form, you can use:
std::sort(contanctList, contactList+num_entries, myCompare);
if you define myCompare to be callable object that can compare two Contact objects.
To use the first form, change Contact to:
struct Contact {
string name, number, notes;
bool operator<(Contact const& rhs) const
{
return (this->name < rhs.name);
}
};
If you want to the comparison of names to be case insensitive, convert both names to either uppercase or lowercase and them compare them.
For some reason my bank script isn't working. More specifically, the search() does not work. I kind of understand why it doesn't, probably because of if(obj.returnId() == n), but I have no clue how to fix it. When I search an account, it will only allow me to find the last account made, not any of the previous ones. Here is my code:
#include "stdafx.h"
#include <iostream>
#include <string>
#include <string.h>
#include <fstream>
#include <Windows.h>
#include <conio.h>
using namespace std;
bool loop = true;
class account
{
int id;
char name[40];
char password[40];
public:
void getData()
{
cout << "\nEnter your name: ";
cin >> name;
cout << "\nEnter ID: ";
cin >> id;
cout << "\Enter pass: ";
cin >> password;
}
void showData()
{
cout << "\nName: ";
puts(name);
cout << "\nID: " << id;
cout << "\n";
}
int returnId()
{
return id;
}
};
void createAccount()
{
account obj;
ofstream fileCreate;
fileCreate.open("accounts.dat", ios::binary|ios::app);
obj.getData();
fileCreate.write((char*)&obj,sizeof(obj));
fileCreate.close();
}
void display()
{
account obj;
ifstream fileRead;
fileRead.open("accounts.dat", ios::binary);
while(fileRead.read((char*)&obj, sizeof(obj)))
{
obj.showData();
}
fileRead.close();
}
void search(int n)
{
account obj;
ifstream fileRead;
fileRead.open("accounts.dat", ios::binary);
while(fileRead.read((char *) &obj, sizeof(obj)) );
{
fileRead.seekg(0,ios::beg);
if(obj.returnId() == n)
{
obj.showData();
}
else {
cout << "\nUser not foud!\n";
}
}
fileRead.close();
}
void main()
{
cout << "Welcome to the Bank.\n\n";
while (loop==true)
{
char choice[10];
cout << "Please select an option:\n";
cout << "------------------------------------------------\n";
cout << "(a)Log into an account\n(b)Create an account\n(s)Search an account\n(e)Exit\n";
cout << "------------------------------------------------\n";
cout << "Choice: ";
cin >> choice;
choice[0] = tolower(choice[0]);
cout << "\n------------------------------------------------\n\n";
switch (choice[0])
{
case 'a':
display();
break;
case 's':
int n;
cout << "Enter the ID of the account: ";
cin >> n;
search(n);
break;
case 'b':
createAccount();
break;
case 'e':
loop = false;
break;
default:
system("CLS");
cout << "The option \"" << choice[0] << "\" is invalid.\n\n\n\n";
break;
}
};
cout << "\n\n\n";
cout << "Click anything to exit.";
getch();
}
Your problem is the semicolon at the end of this line:
while(fileRead.read((char *) &obj, sizeof(obj)) );
That makes this loop have an empty body. So you basically read the whole file and throw away the results, except for the last entry.
get rid of this also:
fileRead.seekg(0,ios::beg);
I don't know why you need that, it would only make you read the first entry over and over.
The other error is that you should only say 'User not found' when you've tested all the accounts and they all failed. Your loop (when you've removed the semi-colon) is saying 'User not found' after every failed test.
You probably don't find the entry you are looking for because each time you have read an entry from the file, you reset the position to the beginning. This means that your loop will run forever, reading the same entry over and over again and never finding the entry you search for.
the seek might be the problem:
while(fileRead.read((char *) &obj, sizeof(obj)) ) //;
{
// seek to start?
//fileRead.seekg(0,ios::beg);
...
}
have a look at http://www.boost.org/doc/libs/1_51_0/libs/serialization/doc/index.html
aside, use
cout << "text" << endl;
for platform-agnostic newlines.