C++ working with files, having trouble making a program - c++

I am trying to make a simple program that can continously add data to a .txt document. Take a look at my code:
#include <iostream>
#include <fstream>
using namespace std;
int main () {
ofstream playersW("players.txt");
ifstream playersR("players.txt");
int id;
string name, info = "";
float money;
while (playersR >> id >> name >> money) {
if (playersR.is_open()) {
info += to_string(id) + " " + name + " " + to_string(money) + "\n";
}
}
playersW << info;
playersR.close();
cout << "Enter player ID, Name and Money (or press 'CTRL+Z' + 'Enter' to quit):" << endl;
while (cin >> id >> name >> money) {
if (playersW.is_open()) {
playersW << id << " " << name << " " << money << endl;
}
}
playersW.close();
}
What I want is the program to first read the data that is stored in players.txt and then write it again and also add the new additional data to players.txt.
EDIT: With the code I have now, my program only writes in the file players.txt the new information that the user enters.

this is a simple program that can open the file players.txt in binary mode so it first reads the content and displays it then it asks the user to input new players until the user enters 0 or negative player id so the loop breaks and then it closes the file to save the new appended content:
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main ()
{
fstream players("players.txt");
int id;
string name, info = "";
float money;
while (players >> id >> name >> money)
cout << name << " " << id << " " << money << endl;
players.clear();
players.seekp(0, ios::end);
cout << "Enter player ID, Name and Money (or press 'CTRL+Z' + 'Enter' to quit):" << endl;
while(1)
{
cout << "id: ";
cin >> id;
cout << endl;
if(!cin || id <= 0)
break;
cout << "name: ";
cin >> name;
if(!cin)
break;
cout << endl;
cout << "money: ";
cin >> money;
if(!cin)
break;
cout << endl;
players << id << " " << name << " " << money << endl;
}
players.close();
return 0;
}

Related

Understanding File Handling I/O

I have written a simple program in two ways. The program is for getting data from a user, storing it in a txt file, retrieving the data and displaying it. The problem is that one approach works while the other does not. I dont understand why.
The one that works is this:
#include <iostream>
#include <fstream>
using namespace std;
class customer{
public:
// Declaring member variables and functions
string name, address, telNo;
int age;
void createCustomer();
void displayInfo(string inputName);
};
// Member function of customer to enter new customer details
void customer::createCustomer(){
customer c;
ofstream file;
file.open("customers.txt", ios::out);
cout << "Enter Name: ";
cin >> c.name;
cout << "Enter Age: ";
cin >> c.age;
cout << "Enter Address: ";
cin >> c.address;
cout << "Enter Telephone Number: ";
cin >> c.telNo;
file.write((char*)&c, sizeof(c));
file.close();
cout << "\n";
}
// Member function of customer to display customer information
void customer::displayInfo(string inputName){
customer c;
ifstream file;
file.open("customers.txt", ios::in);
if(!file){
cout << "Could Not Open customers.txt File\n";
return;
}
while(!file.eof()){
file.read((char*)&c, sizeof(c));
if (inputName == c.name){
cout << "\n";
cout << "Name-------------> " << c.name << endl;
cout << "Age--------------> " << c.age << endl;
cout << "Telephone Number-> " << c.telNo << endl;
cout << "Address----------> " << c.address << endl;
cout << "\n";
break;
}
}
file.close();
}
int main(){
customer c;
c.createCustomer();
c.displayInfo("name");
return 0;
}
It gives the following output:
Enter Name: name
Enter Age: 21
Enter Address: add
Enter Telephone Number: telno
Name-------------> name
Age--------------> 21
Telephone Number-> telno
Address----------> add
The one that doesnt work is this:
#include <iostream>
#include <fstream>
using namespace std;
class customer{
public:
// Declaring member variables and functions
string name, address, telNo;
int age;
void createCustomer();
void displayInfo();
};
// Member function of customer to enter new customer details
void customer::createCustomer(){
customer c;
ofstream file;
file.open("customers.txt", ios::out);
cout << "Enter Name: ";
cin >> c.name;
cout << "Enter Age: ";
cin >> c.age;
cout << "Enter Address: ";
cin >> c.address;
cout << "Enter Telephone Number: ";
cin >> c.telNo;
file.write((char*)&c, sizeof(c));
file.close();
cout << "\n";
}
// Member function of customer to display customer information
void customer::displayInfo(){
string inputName = "name";
customer c;
ifstream file;
file.open("customers.txt", ios::in);
if(!file){
cout << "Could Not Open customers.txt File\n";
return;
}
while(!file.eof()){
file.read((char*)&c, sizeof(c));
if (inputName == c.name){
cout << "\n";
cout << "Name-------------> " << c.name << endl;
cout << "Age--------------> " << c.age << endl;
cout << "Telephone Number-> " << c.telNo << endl;
cout << "Address----------> " << c.address << endl;
cout << "\n";
break;
}
}
file.close();
}
int main(){
customer c;
c.createCustomer();
c.displayInfo();
return 0;
}
All I have done is put the string inputName variable inside the function instead of passing it as an argument.
It gives only the following output:
Enter Name: name
Enter Age: 21
Enter Address: add
Enter Telephone Number: telno
If I remove the if condition:
while(!file.eof()){
file.read((char*)&c, sizeof(c));
//if (inputName == c.name){
cout << "\n";
cout << "Name-------------> " << c.name << endl;
cout << "Age--------------> " << c.age << endl;
cout << "Telephone Number-> " << c.telNo << endl;
cout << "Address----------> " << c.address << endl;
cout << "\n";
break;
//}
}
i get the following output:
Enter Name: name
Enter Age: 21
Enter Address: add
Enter Telephone Number: telno
Name-------------> 0∙⌂┼
Age--------------> 21
Telephone Number-> name
Address----------> §
Why are the name and address fields outputting random symbols and the telephone number field outputting value of the name field?
Neither program is correct. It's an error use read on a type like customer because it contains sub-objects that need constructing, namely the string members name, address and telNo. Calling read does not call any constructor for the objects you are reading and so this is invalid.
Since read does not work for strings it doesn't make any sense to use write on a class containing a string either because you won't be able to read back what you have written.
If you want to write a customer to a file you can do it something like this
file << c.name << ' ' << c.age << ' ' << c.telNo << ' ' << c.address << '\n';
and then something similar for reading (although you then you would have to be careful of any spaces in your data).

read /write file in c++, choose option

I'm trying to write a code for signup / login while being able to write and read from the file. So far I am able to write in the file and asked for the users input and displayed in the file (signup).
My problem is now,
How do I do the login part, in which when the user chooses login, they are able to choose what username they want based on a selection of usernames and the input they have made while choosing the first option?
How can this information be read and displayed in the file?
Expected output for user login
Choose you username:
0:mike
1:Linda
2:Martha
Expected input from the user
your choice: "Key in choice"
So far the code displayed works, but I am not sure what to do for my next step.
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main() {
int option;
int age,height;
string name;
string database;
ofstream file_out;
ifstream file_in;
cout << " For sign up type 1" <<endl;
cout << " For log in type 2" <<endl;
cin >> option;
if ( option == 1 ) {
file_out.open("database.txt");
cout << "Input name: \n";
cin >> name;
cout << "Input age: \n";
cin >> age;
cout << " Input height: \n";
cin >> height;
//write file
file_out << name << endl;
file_out << age << endl;
file_out << height << endl;
file_out.close();
} else if (option == 2) {
//read file
file_in.open("database.txt");
cout << "choose your username: " << endl;
// input line of code
while ( getline(file_in, database));
//input line of code
cout << database << endl;
You can do something like this. Print all the usernames, but before printing out check if they are numbers with help of the stof function, if they are numbers we don't have to do anything, but if it is a string it will throw an exception, so in the catch block we print it and store it into dictionary/map for easy retrieval.
#include <fstream>
#include <iostream>
#include <map>
int main(void) {
std::fstream file;
file.open("secret.txt", std::ios::in);
std::map<int, std::string> map;
std::string username;
int count = 1;
while (!file.eof()) {
file >> username;
try {
std::stof(username);
} catch (...) {
std::cout << count << ". " << username << "\n";
map.insert(std::make_pair(count, username));
count++;
}
}
int choice;
std::cout << "Choose your username: ";
std::cin >> choice;
username = map.at(choice);
std::cout << "Your username is set to " << username;
return 0;
}

C++ Menu Ordering System won't accept multiple words when inputting to the txt file

My code below, whenever I input the menu items, will automatically end the program if I add more than one word such as "Tequila Sunrise" rather than "Tequila". How do I fix this to make it so I can add items with more than one word in the name?
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main() {
// Restaurant Side Title
cout << "Welcome to the Menu Ordering System. \n\n\n";
// Create a txt file to store the menu
fstream MenuWriteFile("drinksmenu.txt");
fstream MenuPricesFile ("drinksprices.txt");
// Write the menu to the file
string myDrinks;
double drinksPrices;
int i;
cout << "Please enter your first drink: ";
cin >> myDrinks;
MenuWriteFile << myDrinks << endl;
cout << "Price: ";
cin >> drinksPrices;
MenuPricesFile << drinksPrices << endl;
cout << "To add another drink type 1, if not type 0: ";
cin >> i;
while (i == 1) {
cout << "Please enter your next drink: ";
cin >> myDrinks;
MenuWriteFile << myDrinks << endl;
cout << "Price: ";
cin >> drinksPrices;
MenuPricesFile << drinksPrices << endl;
cout << "To add another drink type 1, if not type 0: ";
cin >> i;
}
MenuWriteFile.close();
MenuPricesFile.close();
// Create a text string, which is used to output the text file
string myText;
// Read from the text file
ifstream MenuReadFile("drinksmenu.txt");
while (getline (MenuReadFile, myText)) {
cout << "\n\n" << myText << "\n";
}
// Close the file
MenuReadFile.close();
return 0;
}
Use std::getline():
while (i == 1) {
cout << "Please enter your next drink: ";
std::getline(std::cin >> std::ws, myDrinks);
....

Program cannot run due to no operator "<<" matches these operands

I get an error of "no operator matches these operands" when using the part of the code outputFile << customerName << "your Monthly payments are " << monthlyPay << endl;. Overall, I need the code to Add the ability to save data to disk in one or more files and a menu should give the user the option to save or retrieve data. I have not gotten past the error to properly run the program. Can you please help fix error.
#include <iostream>
#include <string>
#include <cmath>
#include <iomanip>
#include <vector>
#include<fstream>
using namespace std;
void menu(void);
void writeData(void);
void readData(void);
const char FileName[] = "CourseProjectAvilaF.txt";
//Variables
vector <double> Loanlgth, Loanamt, interestRate, totalInterest;
vector <double> monthlyPay(100), loanTotal(100), creditScore(100);
vector <string> customerName;
int main()
{
menu();
return 0;
}
void menu(void)
{
const int INPUT_CUSTOMER = 1, DISPLAY_LOAN = 2, EXIT_PROGRAM = 3;
int option;
//Program
cout << "Thank you for choosing The Bank of UA for your loan requirements!\n\n";
do
{
cout << "UA Bank menu:\n\n"
<< "1. Enter your information\n"
<< "2. See your loan requirements\n"
<< "3. Exit program\n\n"
<< "Choose an option: ";
cin >> option;
while (option < INPUT_CUSTOMER || option > EXIT_PROGRAM)
{
cout << "Please enter a valid menu option: ";
cin >> option;
}
if (option == 1)
{
writeData();
}
if (option == 2)
{
readData();
}
} while (option != EXIT_PROGRAM);
}
//function to read customer information
void writeData(void)
{
fstream outputFile;
outputFile.open(FileName, fstream::app);
int index;
int numCustomers = 0;
cout << "Please enter the number of customers you would like\n"
<< " to enter loan information for: ";
cin >> numCustomers;
for (index = 0; index < numCustomers; index++)
{
string tempName;
double tempLoanamt, tempLoanlgth, tempcreditScore, tempinterestRate,
tempinterest;
cout << "Please enter your name: ";
cin >> tempName;
customerName.push_back(tempName);
cout << "Please enter the loan amount: $";
cin >> tempLoanamt;
Loanamt.push_back(tempLoanamt);
cout << "Please enter the length of the loan in months: ";
cin >> tempLoanlgth;
Loanlgth.push_back(tempLoanlgth);
cout << "What is your current credit score? ";
cin >> tempcreditScore;
creditScore.push_back(tempcreditScore);
//This will determine interest rate and overall loan amount when calculated
if (tempcreditScore <= 650)
tempinterestRate = .12;
else
tempinterestRate = .05;
interestRate.push_back(tempinterestRate);
//Calculations
tempinterest = Loanamt[index] * interestRate[index];
totalInterest.push_back(tempinterest);
loanTotal[index] = (Loanamt[index] + totalInterest[index]);
monthlyPay[index] = loanTotal[index] / Loanlgth[index];
// Out put files to write data to be saved
outputFile << customerName << "your Monthly payments are " << monthlyPay << endl;
outputFile << "Your total interest is " << totalInterest << endl;
outputFile << "You owe " << loanTotal << endl;
outputFile << "You have " << Loanlgth << " months to pay off your balance" << endl;
}
outputFile.close(); //Close file
}
//function loan information
void readData(void)
{
int index;
int numCustomers = 0;
ifstream inputFile;
inputFile.open(FileName, fstream::in);//Open the file with read mode
//Display monthly payment
cout << fixed << setprecision(2);
for (index = 0; index < numCustomers; index++)
{
cout << customerName[index] << " your total loan is " << loanTotal[index]
<< "\n"
<< "with a monthly payment of $" << monthlyPay[index] << "\n"
<< "for " << Loanlgth[index] << " months with an interest\n"
<< "rate of " << interestRate[index] << endl;
}
}
It's simple enough, you got it right everywhere else in your program.
When you want to access a particular element of a vector you use an index. Like this
outputFile << customerName[index] << "your Monthly payments are " << monthlyPay[index] << endl;
outputFile << "Your total interest is " << totalInterest[index] << endl;
outputFile << "You owe " << loanTotal[index] << endl;
outputFile << "You have " << Loanlgth[index] << " months to pay off your balance" << endl;
customerName and monthlyPay are vectors. You can't stream them directly. Instead you can do something like
for (auto const &name : customerName)
outputFile << name;

The while loop keeps executing no matter whatever the second user input is within the second case of the switch

The code has been updated in order to solve a different section of the whole picture within the coding process. Now I need help within the second case of the switch. The problem now is that the while loop always executes within the second function of the switch. I don't no if the array is verifying the number or the user input.. I could use while (string::npos != studID2[i].find_first_of(studID2[a])) I need some help here it is getting very complex and I am hitting a brick wall.
1)I need to verify each user input using a for loop and two arrays. I tried to increment the of the arrays in order to execute the while statement.
2) If the condition is true the while loop will execute telling the user that he must enter 3 different digits, the reason why I am using an array and a for loop is because the user gets to choose how many names and IDs he would like to input into the archive.
3) The for loop increments a++ in order to check to see if the last input is the same as the newest user input.
It is getting too complex here any help would be appreciated.
Number 4 is the expected error...
4) The second user input will always make the while loop run regardless of what digits you use.
5)The reason for so much code is because I am not completely sure where the problem begins and the problem ends...
6)I am using two arrays here in this problem.
7)There is another error if you change the a from 0 to 1 it will automatically close the program. The reason you would change the a to a 1 is so that a will increment by 1.
//I am trying to verify multiple inputs with a array and a for loop..
// The expected output is that the second ID you input in the second option of the switch case is going to execute the while loop.
//I am trying to execute the while loop properly within the second function of the switch case.
//I need help any form of help can be appreciated.
#include<iostream>
#include<string>
#include<fstream>
#include<sstream>
#include <cstddef>
#include <limits>
#include <cstdlib>
int name2 = 0;
int studentID = 0;
int email2 = 0;
int studentID2[100];
std::string let("abcdefghijklmnopqrstuvwxyz");
int numbers = (1, 3, 0);
std::string str;
std::string name;
std::string studID;
std::string studID2;
std::string email;
std::string emailbackup;
std::string studFinal;
std::stringstream concatenate;
std::stringstream concatenatetwo;
int x;
std::string fileName = "StudentArchive.txt";
void emailEntry();
void readDocument();
int readNumber();
void deleteInformation();
void getStudentinformation();
using std::cout;
using std::cin;
int main()
{
do {
std::cout << "What would you like to do?" << std::endl;
std::cout << "1)Would you like to see the archive?" << std::endl;
std::cout << "2)Would you like to register student information?" << std::endl;
std::cout << "3)Would you like to find a student within the registry?" << std::endl;
std::cout << "4)Delete all student information?" << std::endl;
std::cout << "5)Exit Program?" << std::endl;
std::cin >> x;
switch (x)
{
case 1:
readDocument();
break;
case 2:
emailEntry();
break;
case 3:
deleteInformation();
break;
case 4:
getStudentinformation();
break;
case 5:
cout << "Exiting Program." << std::endl;
system("PAUSE");
break;
}
} while (x != 5);
}
void emailEntry()
{
std::ofstream outfile;
outfile.open(fileName, std::ios_base::app);
int amountofStudent;
std::cout << "How many student Identities would you like to enter?" << std::endl;
std::cin >> amountofStudent;
cin.ignore();
Here is where the user chooses how many students he would like to enter into the registry. I am having difficulty verifying the user input regarding the studentIDs.
if (outfile.is_open()) {
for (int i = 0; i < amountofStudent; i++)
{
std::string studID2[100];
std::stringstream(name) >> name2;
cout << "Please enter your name.." << std::endl;
getline(cin, name);
outfile << name;
std::stringstream(name2) >> name;
while (std::string::npos != name.find_first_of("0123456789"))
{
cout << "You must have letter within user input." << std::endl;
cout << "Please enter your name." << std::endl;
getline(cin, name);
outfile << name;
}
//I need to check to see if the first 3 numbers are correct?
//The student ID must be at least 6 digits, and the first 3 numbers must be 130.
cout << "Please enter Your student I.D." << std::endl;
getline(cin, studID);
outfile << studID;
std::stringstream(studID) >> studentID;
while (/*std::string::npos != studID.find_first_of("130") */ studentID != 130 /*&& studID.length() <= 6*/)
{
std::stringstream(studentID) >> studID;
cout << "You must enter 130 as the first 3 digits" << std::endl;
getline(cin, studID);
std::stringstream(studID) >> studentID;
}
//==============
//std::stringstream(studentID2) >> studID2[i];
cout << "Please enter the second part of the student I.D. " << studentID << "-" << std::endl;
getline(cin, studID2[i]);
outfile << studID;
//outfile << studID2[i];
std::stringstream(studID2[i]) >> studentID2[i];
//cout << i;
This is the for loop, and array I need help with. Below this text is where I am having problems. I don't understand why the while loop won't execute I am trying to verify the first user input with the next user input. For example if the user enters 888 on the first input then tries to enter 888 on the second input they need to re-enter different digits or the input will go on forever. The main struggle is if the user chooses to enter multiple student accounts within this minor registry.
for (int a = 0; a < i; i++)
{
while (studID2[i] == studID2[a])
{
cout << "The numbers cannot be repeated you must re-enter the student ID." << std::endl;
std::stringstream(studentID) >> studID;
cout << "You must enter 130 as the first 3 digits" << std::endl;
getline(cin, studID);
std::stringstream(studID[i]) >> studentID;
//std::stringstream(studID2[i]) >> studentID2;
cout << "Please enter the second part of the student I.D. " << studentID << "-" << std::endl;
getline(cin, studID2[i]);
outfile << studID;
outfile << studID2[i];
//std::stringstream(studID2[i]) >> studentID2;
}
}
This is where the verification of the studentIDs end...
while (/*std::string::npos != studID.find_first_of("130") */ studID2[i].length() < 3 || studID2[i].length() > 3)
{
//stringstream(studentID) >> studID;
cout << "Add 3 more digits." << std::endl;
getline(cin, studID2[i]);
outfile << studID2[i];
}
concatenate << studentID << "-" << studID2 << std::endl;
studFinal = concatenate.str();
/*while (studID.length() != 6)
{
cout << "You must enter 130 as the first 3 digits and you must have 6 digits." << std::endl;
std::cin >> studID;
}*/
cout << "Please enter your email.." << std::endl;
std::stringstream(email) >> email2;
getline(cin, email);
outfile << email;
std::stringstream(email2) >> email;
while (email == emailbackup || email.empty())
{
cout << "Please enter your email..." << std::endl;
std::stringstream(email) >> email2;
getline(cin, email);
outfile << email;
std::stringstream(email2) >> email;
}
concatenatetwo << email << "#atlanticu.edu" << std::endl;
email = concatenatetwo.str();
emailbackup = email;
cout << "Your email is" << email << std::endl;
std::system("pause");
}
}
outfile.close();
}
Here is where the user deletes info..
void deleteInformation()
{
std::ofstream infile(fileName, std::ios::trunc);
if (infile.is_open()) {
cout << "You have now have no books." << std::endl;
system("PAUSE");
system("cls");
infile.close();
}
}
void getStudentinformation()
{
std::ifstream outfile;
outfile.open(fileName);
if(outfile.is_open())
{
int x;
cout << "1)Name" << std::endl;
cout << "2)studentNumber" << std::endl;
cout << "3)Exit" << std::endl;
cin >> x;
switch (x)
{
case 1:
cout << "Please enter the student's name.." << std::endl;
getline(cin, name);
cout << name << std::endl;
outfile >> name;
break;
case 2:
cout << "Please enter the first 3 digits of the student's ID number.. " << std::endl;
getline(cin, studID);
cout << "Please enter the last 3 digits of the student's ID number.. " << std::endl;
getline(cin, studID2);
outfile >> studID;
outfile >> studID2;
break;
case 3:
std::string choice;
cout << "Would you like to return to the main menus?" << std::endl;
cin >> choice;
break;
}
}
}
int readNumber()
{
int number;
cin >> number;
std::string tmp;
while (cin.fail())
{
cin.clear();
std::getline(cin, tmp);
cout << "Only numbers please: ";
cin >> number;
}
getline(cin, tmp);
return number;
}
Here is where the user reads the txt doc.
void readDocument()
{
std::ifstream infile;
infile.open(fileName);
if (infile.is_open()) {
std::string info;
while (getline(infile, info))
{
cout << info << std::endl;
}
infile.close();
}
else {
cout << fileName << " doesn't exists !" << std::endl;
}
std::system("PAUSE");
std::system("cls");
}
//std::ofstream outfile;
//outfile.open(fileName, ios_base::app);
//if(outfile.is_open()) {
// cout << "How many books do you want to add: ";
// int n = readNumber();
// while (n <= 0)
// {
// cout << "Only positive numbers, please: ";
// n = readNumber();
// }
// for (int i = 0; i < n; i++) {
// string title = "Book's Title: ";
// cout << title;
// title += readText();
// string author = "Author: ";
// cout << author;
// author += readText();
// string genre = "Book's Genre: ";
// cout << genre;
// genre += readText();
// cout << endl;
// outfile << title << endl;
// outfile << author << endl;
// outfile << genre << endl << endl;
// }
//}
// outfile.close();
// cout << "Books have been added to the library !" << endl;
// system("PAUSE");
// system("cls");
Think about your function signature.
void email(string emailbackup);
Do you actually want the caller to pass a string to the function email()?
Because you then define emailbackup inside the function again.
You want something like this probably...
...
case 2:
const string backup = "backup#email";
email(backup);
break;
...
void email(string emailbackup)
{
// string emailbackup; // delete this line
...
}
Also, remove using namespace std; and be consistent with your namespace usage. Why add using namespace cout, cin etc if you are calling them with the namespace explicitly i.e. std::cin, std::cout.
Either add using namespace std::cout and use cout rather than std::cout or vice versa. Don't mix it up. Same with std::string and string. Makes it look like you defined your own string...
Just one last thing, for the sake of readability I would suggest breaking this email function into smaller functions. For instance:
void email(string emailbackup)
{
...
int studentID = getStudentID();
string studentEmail = getStudentEmail();
...
}
int getStudentID()
{
int studentID;
cout << "Please enter Your student I.D." << std::endl;
std::cin >> studID;
stringstream(studID) >> studentID;
while (/*std::string::npos != studID.find_first_of("130") */ studentID != 130 /*&& studID.length() <= 6*/)
{
stringstream(studentID) >> studID;
cout << "You must enter 130 as the first 3 digits" << std::endl;
std::cin >> studID;
stringstream(studID) >> studentID;
}
return studentID;
}