Reading from/writing to files using functions [closed] - c++

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
Hi I am working on a simple wage application. The following code contains a two option menu using switch statements. The code is also linked to a text file called "shop-account". The file simply contains the value 100.
For option 1 the user is suppose to be able to transfer an amount from the file. The user should be able to make as many transfers as they choose without overdrawing the account. And the code should be able to output the current balance. I believe I am suppose to be using the void function but I have never used it before and am really struggling. I was hoping someone could look at the code and tell me where I am going wrong. Thanks
int read_balance (void);
void write_balance (int balance);
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
int selection;
int total;
int balance;
int NewAmount;
do {
cout << "1. Transfer an amount" <<endl;
cout << "2. Quit" << endl;
cout << "Please enter menu number"<<endl;
cin >> selection;
switch(selection)
{
case 1:
cout << "You have choosen to transfer an amount" << endl;
cout << "How much do you wish to transfer from the shop account?"<<endl;
cin >> NewAmount;
balance -= NewAmount;
write_balance (balance);
cout << balance << endl;
break;
case 2:
return 0;
break;
default:
cout << "Ooops, invalid selection!" << endl;
break;
}
}while(selection != 2);
system("pause");
return 0;
}
int read_balance (void)
{
fstream f;
f.open("shop-account.txt");
f >> balance; //error: "balance" is unidentified
f.close();
return balance;
}
void write_balance (int balance)
{
fstream f;
f.open("shop-account.txt");
f << balance;
f.close();
}

Like others mentioned, you didn't declare the int balance in the right scope (function level scope, in this case).
In fact, it looks like you forgot call read_balance alltogether, so your calculations on balance used an indeterminate value, which is Undefined Behaviour.
Next up: declare your variables where they are used, that way you prevent this whole situation when you decide to extract pieces of code into subfunctions, and it gets easier to see where variables are used. Consequently, it gets easier to see whether the code is correct.
Next: Error handling. If you have none, your program is worthless. In fact, even when fixing the above issue,
simply entering invalid input once would run a loop and just keep substracting indeterminate values from the account balance and writing those wrong values to disk. That's probably not what you wanted.
making the shop-account.txt read-only was enough to fool the program into
transfer unlimited amounts without updating the file
having the wrong idea of the balance in the file (since it never checks)
Here is a cleaned-up version that does a minimum amount of checking, and adds an option to just 'check the account balance'. Seemed useful.
See it Live On Coliru
I hope some of this helps. For one thing, I hope your teacher was going to mention most of this :/
int read_balance(void);
void write_balance(int balance);
#include <iostream>
#include <limits>
int main()
{
while(std::cin.good())
{
std::cout << "0. Request balance" << std::endl;
std::cout << "1. Transfer an amount" << std::endl;
std::cout << "2. Quit" << std::endl;
std::cout << "Please enter menu number" << std::endl;
int selection = 2;
if(std::cin >> selection)
{
std::cout << "DEBUG: selection:" << selection << "\n";
switch(selection)
{
case 0:
std::cout << "The current account balance is " << read_balance() << std::endl;
break;
case 1:
{
std::cout << "You have choosen to transfer an amount" << std::endl;
std::cout << "How much do you wish to transfer from the shop account?"<<std::endl;
int amount = 0;
if (std::cin >> amount)
{
std::cout << "DEBUG: amount:" << amount << "\n";
int balance = read_balance();
if(amount<=0)
{
std::cout << "Amount must be positive\n";
}
else if(balance < amount)
{
std::cout << "Insufficient funds\n";
}
else
{
int new_balance = balance - amount;
write_balance(new_balance);
std::cout << "New account balance: " << new_balance << std::endl;
}
} else
{
// bad input cleared outside the switch
}
}
break;
case 2:
return 0;
break;
default:
std::cout << "Ooops, invalid selection!" << std::endl;
break;
}
}
if(std::cin.eof())
{
std::cout << "Bye\n";
return 0;
}
if(std::cin.fail())
{
std::cin.clear();
std::cin.ignore(99999, '\n');
std::cout << "Invalid input\n";
// note eof() can be true here
}
}
}
#include <fstream>
int read_balance(void)
{
std::ifstream f;
f.exceptions(std::ios::failbit | std::ios::badbit);
f.open("shop-account.txt");
int balance;
f >> balance;
f.close();
return balance;
}
void write_balance(int balance)
{
std::ofstream f;
f.exceptions(std::ios::failbit | std::ios::badbit);
f.open("shop-account.txt");
f << balance;
f.close();
}

your function does not have a balance varible declartion !! you have to add a balance declaration in your function
int read_balance(void)
{
fstream f;
f.open("shop-account.txt");
int balance;
f >> balance; //now it's defined
f.close();
return balance;
}

Related

Prototype function is not the returning the values I want to main function; what's happening?

This is a class project but I am quite lost at this part. I am suppose to return 3 values to the main function. When I finally thought I had it, I just found out that the values I am inputting are not the values being returned. For example if I input 8 and 4 in the prototype function, when I return these values to the main function they are output as 1 and some long random number.
#include <iostream>
using namespace std;
// Declare prototype function
void OrderInfo();
int main(int A_SpoolsOrdered, int A_SpoolStock, double A_SpecialCharges)
{
OrderInfo();
cout << "\n";
cout << "Order Summary\n";
cout << "==================\n\n";
// Returning values
cout << "items ordered:\t" << A_SpoolsOrdered << "\n"; // OrderInfo input not matching final output
cout << "Items in stock:\t" << A_SpoolStock; // OrderInfo input not matching final output
}
void OrderInfo()
{
// Declare Variables
int SpoolsOrdered, SpoolStock;
double SpecialCharges;
char choice;
// Ask user for spools ordered and spools in stock and store it
cout << "How many spools were ordered? ";
cin >> SpoolsOrdered; // Value to return
cout << "How many spools are in stock? ";
cin >> SpoolStock; // Value to return
// Ask the user if there is any additional charges
cout << "Are special shipping charges required? <y or n>: ";
cin >> choice;
switch (choice)
{
case 'y': cout << "Enter the amount of any special shipping charges: ";
cin >> SpecialCharges; // Value to return
main(SpoolsOrdered, SpoolStock, SpecialCharges); //Attempt to return all values
break;
case 'n': break;
main(SpoolsOrdered, SpoolStock, SpecialCharges);
default: cout << "Invalaid input, run program again!\n";
break;
}
}
You're doing this backwards. The parameters of your OrderInfo should be int&, int&, double& Your prototype should look like:
void OrderInfo(int& A_SpoolsOrdered, int& A_SpoolStock, double& A_SpecialCharges);
Your main() function can either be int main() or int main(int argc, char** argv), or int main(int argc, char** argv, char** envp). You then call OrderInfo in your main function.
I think you are looking for something like this:
#include <iostream>
using namespace std;
// Declare prototype function
void OrderInfo(int& A_SpoolsOrdered, int& A_SpoolStock, double& A_SpecialCharges);
int main()
{
int A_SpoolsOrdered, A_SpoolStock;
double A_SpecialCharges;
OrderInfo(A_SpoolsOrdered, A_SpoolStock, A_SpecialCharges);
cout << "\nOrder Summary\n";
cout << "==================\n\n";
cout << "items ordered:\t" << A_SpoolsOrdered << "\n";
cout << "Items in stock:\t" << A_SpoolStock;
getch();
}
void OrderInfo(int& SpoolsOrdered, int& SpoolStock, double& SpecialCharges);
{
// Declare Variables
char choice;
// Ask user for spools ordered and spools in stock and store it
cout << "How many spools were ordered?\n";
cin >> SpoolsOrdered; // Value to return
cout << "How many spools are in stock?\n";
cin >> SpoolStock; // Value to return
// Ask the user if there is any additional charges
cout << "Are special shipping charges required? <y or n>:\n";
cin >> choice;
switch (choice)
{
case 'y': cout << "Enter the amount of any special shipping charges:\n";
cin >> SpecialCharges; // Value to return
break;
case 'n': break;
cout << "OK, no special shipping charges.\n"
default: cout << "Unknown value, assuming no special shipping charges.\n";
break;
}
}

How do I execute previously executed lines of code in C++

I've started to learn how to code in C++ on my spare time, using different sites and apps that someone who has also learned C++ online provided me with. By now, I know the most basic commands. I've tried an exercise given by a program, and I'm given the information that someone is going on a vacation, and needs to know how much baggage he can bring with him. The limit to how many baggages he can carry is 45, and I have to display a different output if the baggages are below, above or the same as the limit (45 baggages). I have done some coding, and I ended up with this:
#include <iostream>
using namespace std;
int main()
{
const int limit = 45;
int bag;
cout << "Please type your number here: ";
cin >> bag;
string yn;
int keep = 0;
if (limit < bag)
{
cout << "You passed the limit." << endl;
};
if (limit == bag)
{
cout << "Just enough." << endl;
};
if (limit > bag)
{
cout << "You got space." << endl;
};
++keep;
while(keep > 0)
{
int keep = 0;
cout << "Do you want to try another number?" << endl;
cin >> yn;
cout << endl;
if(yn == "yes")
{
int bag = 0;
cout << "Please type your number here: ";
cin >> bag;
if (limit < bag)
{
cout << "You passed the limit." << endl;
};
if (limit == bag)
{
cout << "Just enough." << endl;
};
if (limit > bag)
{
cout << "You got space." << endl;
};
}
else
{
return 0;
}
}
}
I have developed it more than needed -as you can see-, out of my own interest in the problem. I have copied and pasted the 3 IF commands as seen above, and I believe that there is an easier way, with less code, do solve this. What I have thought of is if I could go back and execute some line of code again, either from a line and below (e.g. from line 45 and below), or specific lines of code (e.g. from line 45 to line 60).
I would appreciate it if you thought of another way to solve this problem and posted your code below.
Thank you for your reply.
We all started writing our first C++ program at some time, so allow me to give you some additional feedback:
First of all, avoid writing using namespace std;
Secondly, naming - what is bag, limit, keep and yn? Wouldn't it be much easier to read and understand if they were called bagSize, maximumPermittedBagSize, inputFromUser (you don't really need the variable keep, see below)?
Finally, here is a (roughly) refactored version your program, with duplication removed and comments added.
#include <iostream>
int main()
{
const int maximumPermittedBagSize = 45;
// Loops forever, the user exits by typing anything except 'yes' laster
while(true)
{
std::cout << "Please type your number here: " << std::endl;
//Declare (and initialize!) variables just before you need them
int bagSize = 0;
std::cin >> bagSize;
if (bagSize > maximumPermittedBagSize)
{
std::cout << "You passed the limit." << std::endl;
}
else if (bagSize == maximumPermittedBagSize )
{
std::cout << "Just enough." << std::endl;
}
else
{
std::cout << "You got space." << std::endl;
}
std::cout << "Do you want to try another number?" << std::endl;
std::string inputFromUser = "";
std::cin >> inputFromUser;
std::cout << std::endl;
//Leave the loop if the user does not answer yes
if(inputFromUser != "yes")
{
return 0;
}
}
}
You can simply run a while loop and do like this:
#include <iostream>
using namespace std;
int main()
{
const int limit = 45;
int bag;
string yn = "yes";
while(yn == "yes")
{
cout << "Please type your number here: ";
cin >> bag;
if (limit < bag)
{
cout << "You passed the limit." << endl;
}
else if (limit == bag)
{
cout << "Just enough." << endl;
}
else if (limit > bag)
{
cout << "You got space." << endl;
}
cout << "Do you want to try another number?" << endl;
cin >> yn;
cout << endl;
}
}

Some kind of 'goto' function for C++ [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 years ago.
Improve this question
#include <iostream>
using namespace std;
int main()
{
float a, b, result;
char operation, response;
cin >> a >> operation >> b;
switch(operation)
{
case '+':
result = a + b;
break;
case '-':
result = a - b;
break;
case '*':
result = a * b;
break;
case '/':
result = a / b;
break;
default:
cout << "Invalid operation. Program terminated." << endl;
return -1;
}
// Output result
cout << "The result is " << result << endl;
system("sleep 200");
cout << "Do you want to make another opertaion? (Y/N)" << endl;
cin >> response;
if(response=='Y')
{
here
}
else if(response=='N')
{
cout << "The program will now close" << endl;
system("sleep 500");
return -1;
}
return 0;
}
Where the word 'here' is written, I want to insert a code that gets you to the beggining of the code.
You can use the loop do... while(condition)
Like :
do{
cin >> a >> operation >> b;
switch(operation)
{
...
}
// Output result
cout << "The result is " << result << endl;
system("sleep 200");
cout << "Do you want to make another opertaion? (Y/N)" << endl;
cin >> response;
}while(response=='Y');
If the response isn't 'Y' the loop ends, if it is the loop begin again
All though goto is highly frowned upon in C++, it does exist.
Much like assembly, your put a label in your code and then tell it to 'jump' there using goto. However, the same way jump works in assembly, this may break you out of all loops to the point that you jump to.
#include <iostream>
using namespace std;
int main()
{
label:
float a, b, result;
char operation, response;
cin >> a >> operation >> b;
//condensed for neatness
// Output result
cout << "The result is " << result << endl;
system("sleep 200");
cout << "Do you want to make another opertaion? (Y/N)" << endl;
cin >> response;
if(response=='Y')
{
goto label;
}
else if(response=='N')
{
cout << "The program will no`enter code here`w close" << endl;
system("sleep 500");
return -1;
}
return 0;
}
What most people would do is use a do{}while(condition==true) loop or just an infinite loop while(true).
For this 'neater' code, what you would do is
#include <iostream>
using namespace std;
int main()
{
do{
float a, b, result;
char operation, response;
cin >> a >> operation >> b;
//condensed for neatness
// Output result
cout << "The result is " << result << endl;
system("sleep 200");
cout << "Do you want to make another opertaion? (Y/N)" << endl;
}while(cin.get() == 'Y');
cout << "The program will no`enter code here`w close" << endl;
system("sleep 500");
return -1;
return 0;
}
If this is being called from another location, I would highly recommend using do while rather than goto, as it can cause issues.
The only real problem with goto is that it's not elegant and makes code confusing to read. You should use loops and returns where possible, and only use goto if you see no other way to make this work optimally.

Bank System not working

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.

Object is initializing to unwanted value

I have been working on a trivial assignment to get used to coding. I am designing an ATM machine and at the moment it is composed of 2 classes:
BankAccount.cpp
Constructor for different types of account
Only has balance as a member
Transaction.cpp
Performs a method on the BankAccount (i.e make deposit, make withdrawl & get balance)
Problem: BankAccount is automatically initialized to a balance of 10 which is undesired. So for example, if I made a checking account and chose to deposit $10, balance would print out $20.
//BankAccount.h
//This class will simply take in a bank account
//with a balance, other classes will use a bank account object
//such as saving/checkings and perform operations on the
//balance
#ifndef BANK_ACCOUNT_H
#define BANK_ACCOUNT_H
class BankAccount {
private:
float balance;
public:
BankAccount ();
float getBalance ();
void makeDeposit ();
void makeWithdrawl ();
};
#endif
//BankAccount.cpp
#include "BankAccount.h"
#include <iostream> //remove once done *not to self
using namespace std; //remove once done *note to self
BankAccount::BankAccount() {
balance = 0.00;
}
float BankAccount::getBalance() {
return balance;
}
void BankAccount::makeDeposit() {
cout << "How much would you like to deposit: ";
float deposit_value;
cin >> deposit_value;
balance += deposit_value;
}
void BankAccount::makeWithdrawl() {
cout << "How much would you like to withdrawl: ";
float withdrawl_value;
cin >> withdrawl_value;
balance -= withdrawl_value;
}
//Transaction.h
#ifndef TRANSACTION_H
#define TRANSACTION_H
class Transaction {
private:
BankAccount m_bao;
public:
Transaction(BankAccount&);
void displayOptions();
void printReciept();
};
#endif
//Transaction.cpp
#include "BankAccount.h"
#include "Transaction.h"
#include <iostream>
using namespace std;
Transaction::Transaction(BankAccount& bao) {
m_bao = bao;
}
void Transaction::displayOptions() {
cout << "\nPlease make a choice\n\n";
cout << "1: Make Deposit\n";
cout << "2: Make Withdrawl\n";
cout << "3: Check Balance\n";
int choice;
cin >> choice;
switch (choice) {
case 1:
m_bao.makeDeposit();
break;
case 2:
m_bao.makeWithdrawl();
break;
case 3:
m_bao.getBalance();
break;
}
}
void Transaction::printReciept() {
cout << "Current balance is now: " << m_bao.getBalance() + '\n';
}
int main () {
BankAccount checking;
Transaction q(checking);
q.displayOptions();
q.printReciept();
}
I am sure the answer is right in front of my eyes, but my brain is just fried right now. I will continue to look for the solutions and let you guys know if my problem has been solved yet.
[EDIT]
Alright, now I am trying to make it so that the customer can choose to perform transactions on either Checking or Savings account. Currently I got it looking like this in my main():
int main () {
BankAccount checking(0.00);
BankAccount savings(0.00);
Transaction c(checking);
Transaction s(savings);
for(int i = 0; i < 10 ; i++) {
cout << "Make an option" << endl;
cout << "1. Checking " << endl;
cout << "2. Savings" << endl;
int choice;
cin >> choice;
if (choice == 1) {
c.prompt();
c.printReciept();
}
else {
s.prompt();
s.printReciept();
}
}
}
It works fine, but I would like to make this process more OOP-alized, if that makes sense :)
One option I was trying to look into was making a prompt function which would belong to Transaction.cpp. This would do everything that is done in main, except initializing the objects of course.
Your problem is this line:
cout << "Current balance is now: " << m_bao.getBalance() + '\n';
Which the compiler sees as:
cout << "Current balance is now: " << (m_bao.getBalance() + '\n');
'\n' is 10 as an int, so you get this:
cout << "Current balance is now: " << (m_bao.getBalance() + 10);
You probably meant to do this:
cout << "Current balance is now: " << m_bao.getBalance() << '\n';
Remember that in C++, + almost always means "add these two numbers".