I am a beginner C++ programmer. I'm trying to create a program that takes logs a user into a program, Everything compiled perfectly, but when I try to run it I get an Xstring error saying this was 0x7FF6F0AACFF0".
I suppose the error could have come from the fact that I am very new to using files in code, and I needed to use them in this program as they were the only way the login and password data could be permanently saved.
I have rewritten this project over 5 times and this is the most functional variant so far. I tried using the ofstream and ifstream but I abandoned them because only one password & login was saved per file; so I think that the main error is probably contained in the Processing and Array_filler functions, all I need is a point in the right direction and I'll probably be able to resolve it.
C++:
#include <iostream>
#include <stdlib.h>
#include <fstream>
#include <string>
using namespace std;
//bug_1 need to fix the error where the code doesn't recognize a returning user
//Project_1 need to implement a subsystem that recommends a random password & Login
//Project_2 need to implement a subsystem that requires a strong password
string Word_blip[90] = {};
string Pass_blop[90] = {};
string password;
string logWord;
string Login_1;
string Pass_1;
int KILL_SWITCH = 1;
int y = 0;
void Array_filler();
void Start_up();
void Yupper_pupper();
void processing();
void New_Login();
int main() {
Start_up();
if (KILL_SWITCH == 0) {
return EXIT_SUCCESS;
}
Yupper_pupper();
processing();
}
void Start_up() {
Array_filler();
cout << "Login:";
cin >> logWord;
cout << "Password:";
cin >> password;
for (y; y >= 90; y++) {
cout << "Preparing" << endl;
}
system("cls");
if (Word_blip[y] == logWord) {
cout << "Login accepted, welcome user:" << endl;
} else if (Word_blip[y] != logWord) {
New_Login();
}
}
void New_Login() {
string i_1_5;
cout << "Login not recognized, would you like to sign up?" << endl;
cin >> i_1_5;
if (i_1_5 == "yes") {
void Yupper_pupper();
} else if (i_1_5 == "no") {
cout << "Have a good day!" << endl;
KILL_SWITCH = 0;
} else {
cout << "That's not a valid answer ;-) please retry" << endl;
New_Login();
}
}
void Yupper_pupper() {
system("cls");
cout << "Please Sign in with your new username & Password." << endl;
cout << "New Login:";
cin >> Login_1;
cout << "New password:";
cin >> Pass_1;
void processing();
}
void processing() {
/* acts like "ofstream" or "ifstream combined; with the
ios::in and ios::out replacing the sort of "read out file"
ofstream meant with "ios::in"and the "input into file" that
ifstream provided with ios::out*/
fstream Urfile("Logins.txt", ios:: in );
string Placeholder_1;
if (Urfile.is_open()) {
getline(Urfile, Placeholder_1);
/* While Urfile = "While the file is open" Urfile = true
When the file runs out of information the file will close
making the statement false and ending the loop ;-)*/
while (Urfile) {
Placeholder_1 = Word_blip[0];
}
Urfile.close();
} else {
cout << "ERROR_OPENING_URFILE_ABORTING_PROGRAM_1" << endl;
abort();
}
fstream Myfile("Passwords.txt", ios:: in );
string Placeholder_2;
if (Myfile.is_open()) {
getline(Myfile, Placeholder_2);
while (Myfile) {
Placeholder_2 = Pass_blop[0];
}
Myfile.close();
} else {
cout << "ERROR_OPENING_MYFILE_ABORTING_PROGRAM_1" << endl;
abort();
}
Start_up();
}
void Array_filler() {
/*This function is responsible for clearing out the file
and replacing everything inside with the contents of Pass_blip and Word_blop
. Don't worry! none of the data will be lost because it was all written to the
arrays to be processed alongside the new inputs*/
fstream Urfile("Login.txt", ios::out);
if (Urfile.is_open()) {
for (int i = 0; Word_blip[i] != "\n"; i++) {
Urfile << Word_blip[i] << endl;
}
Urfile.close();
} else {
cout << "ERROR_OPENING_URFILE_ABORTING_PROGRAM_2" << endl;
abort();
}
fstream Myfile("Passwords.txt", ios::out);
if (Myfile.is_open()) {
for (int i = 0; Pass_blop[i] != "\n"; i++) {
Myfile << Pass_blop[i] << endl;
}
Myfile.close();
} else {
cout << "ERROR_OPENING_MYFILE_ABORTING_PROGRAM_2" << endl;
abort();
}
}
Related
Ok so, this is gonna be a long one...
Explanation of what the project is supposed to do:
My final project is a bank teller system that stores all the account related data on a text files.
The file in question, "accounts.txt", is where all the account data is stored. It is read and write, and behaves strangely when an ofstream is introduced...
The "accounts.txt" file is formated as follows
01481
554-00-8336
Jane Jones
1483 N. RealmSecond Ave., Burlington, VT 05401
564 425 5052
02650
727-22-1072
Jennifer Armstrong
1450 W. Main Rd., Burlington, VT 05401
202 545 5485
it continues repeating the same ordered sets of information...
One of the core parts of the program relies on reading these values into 5 separate arrays, each pertaining to type of data (name, address, etc).
I am going to dump the entire program because I think it might be necessary to fix the problem, just understand that the main function in question is addAccount() and is located at the bottom.
Note that the purpose of this function is to read the entire accounts.txt file line by line into memory, determine at what point the arrays used to store the file are being filled with empty data (we were told by the course instructor to make the array size 100, meaning that most of the data read into the array is empty space) get the desired account information from the user, update the file in memory, and rewrite the file...
also note that the file format was predetermined by the course instructor
The code:
#include <iostream>
#include <iomanip>
#include <fstream>
#include <string>
using namespace std;
const int TELLERS_SIZE = 5;
const int ACCOUNTS_SIZE = 100;
const string TELLERS_FILE = "tellers.txt";
const string ACCOUNTS_FILE = "accounts.txt";
int beginMenu();
bool login(string fileName);
int baseMenu();
void searchAccount(string fileName);
void addAccount(string fileName);
int main() {
int beginSelection;
do {
beginSelection = beginMenu();
if (beginSelection == 2) {
return 0;
}
bool loginIsTrue = login(TELLERS_FILE);
while (loginIsTrue) {
int baseSelection = baseMenu();
if (baseSelection == 1) {
addAccount(ACCOUNTS_FILE);
}
if (baseSelection == 4) {
searchAccount(ACCOUNTS_FILE);
}
if (baseSelection == 8) {
loginIsTrue = false;
}
}
} while (beginSelection == 1);
}
// Print the fisrt menu and return selection
int beginMenu() {
// Establish return value and validation
int menuSelection;
string userInput;
bool menuSelectionIsValid = false;
// Print options
do {
cout << "\n";
cout << "[1] Login" << "\n";
cout << "[2] Quit" << "\n";
cout << "Please enter a selection";
cout << "\n";
getline(cin, userInput);
// Validate input
if (userInput == "1") {
menuSelectionIsValid = true;
menuSelection = 1;
}
else if (userInput == "2") {
menuSelectionIsValid = true;
menuSelection = 2;
}
else {
cout << "Invalid input!" << "\n";
}
} while (!menuSelectionIsValid);
return menuSelection;
}
// Perform login and return true or false
bool login(string fileName) {
// Establish variables
string username[TELLERS_SIZE];
string password[TELLERS_SIZE];
string usernameInput;
string passwordInput;
bool loginIsValid = false;
// Establish fin
ifstream fin(fileName);
if (!fin.is_open()) {
cout << "File cannot be opened " << fileName << "\n";
return false;
}
// Read tellers.dat
for (int i = 0; i < TELLERS_SIZE; i++) {
fin >> username[i];
fin >> password[i];
}
// Read user input
cout << "\n";
cout << "Username: ";
getline(cin, usernameInput);
cout << "Password: ";
getline(cin, passwordInput);
// Verify login information
for (int i = 0; i < TELLERS_SIZE; i++) {
if (username[i] == usernameInput && password[i] == passwordInput) {
cout << "Login succesful" << "\n";
loginIsValid = true;
return true;
}
}
// Inform user of error
cout << "Invalid username or password!" << "\n";
return false;
}
// Print base functions menu and return selection
int baseMenu () {
// Establish return value and validation
int menuSelection;
string userInput;
bool menuSelectionIsValid = false;
do {
// Print options
cout << "\n";
cout << "[1] Add Account" << "\n";
cout << "[2] Remove Account" << "\n";
cout << "[3] Update Account" << "\n";
cout << "[4] Search Account" << "\n";
cout << "[5] Make A Deposit" << "\n";
cout << "[6] Make A Withdrawal" << "\n";
cout << "[7] Check Balance" << "\n";
cout << "[8] Logout" << "\n";
cout << "Please enter a selection";
cout << "\n";
getline(cin, userInput);
// Validate input
if (userInput == "1") {
menuSelectionIsValid = true;
menuSelection = 1;
}
else if (userInput == "2") {
menuSelectionIsValid = true;
menuSelection = 2;
}
else if (userInput == "3") {
menuSelectionIsValid = true;
menuSelection = 3;
}
else if (userInput == "4") {
menuSelectionIsValid = true;
menuSelection = 4;
}
else if (userInput == "5") {
menuSelectionIsValid = true;
menuSelection = 5;
}
else if (userInput == "6") {
menuSelectionIsValid = true;
menuSelection = 6;
}
else if (userInput == "7") {
menuSelectionIsValid = true;
menuSelection = 7;
}
else if (userInput == "8") {
menuSelectionIsValid = true;
menuSelection = 8;
}
else {
cout << "Invalid input!" << "\n";
}
} while (!menuSelectionIsValid);
return menuSelection;
}
// Locate account and print relevant information
void searchAccount(string fileName) {
// Establish arrays
string accountNumber[ACCOUNTS_SIZE];
string accountSSN[ACCOUNTS_SIZE];
string accountName[ACCOUNTS_SIZE];
string accountAddress[ACCOUNTS_SIZE];
string accountPhone[ACCOUNTS_SIZE];
// Establish validation variables
string userInput;
bool accountFound = false;
// Establish and validate fin
ifstream fin(fileName);
if (!fin.is_open()) {
cout << "File cannot be opened " << fileName << "\n";
}
// Get desired account number
cout << "\n";
cout << "Account number: ";
getline(cin, userInput);
// Read information from file
for (int i = 0; i < ACCOUNTS_SIZE; i++) {
getline(fin, accountNumber[i]);
getline(fin, accountSSN[i]);
getline(fin, accountName[i]);
getline(fin, accountAddress[i]);
getline(fin, accountPhone[i]);
}
// Search for account
for (int i = 0; i < ACCOUNTS_SIZE; i++) {
if (accountNumber[i] == userInput && userInput != "") {
accountFound = true;
}
// Display account information
if (accountFound == true) {
cout << "Account Found" << "\n";
cout << "Displaying account information" << "\n" << "\n";
cout << accountNumber[i] << "\n";
cout << accountSSN[i] << "\n";
cout << accountName[i] << "\n";
cout << accountAddress[i] << "\n";
cout << accountPhone[i] << "\n";
break;
}
}
// Inform user that account doesnt exist
if (accountFound == false) {
cout << "Unable to find account: " << userInput << "\n";
}
}
void addAccount(string fileName) {
string accountNumber[ACCOUNTS_SIZE];
string accountSSN[ACCOUNTS_SIZE];
string accountName[ACCOUNTS_SIZE];
string accountAddress[ACCOUNTS_SIZE];
string accountPhone[ACCOUNTS_SIZE];
ifstream fin(fileName);
// ofstream fout(fileName);
string userAccountNumber;
string userAccountSSN;
string userAccountName;
string userAccountAddress;
string userAccountPhone;
bool accountNumberIsTaken = true;
for (int i = 0; i < ACCOUNTS_SIZE; i++) {
getline(fin, accountNumber[i]);
getline(fin, accountSSN[i]);
getline(fin, accountName[i]);
getline(fin, accountAddress[i]);
getline(fin, accountPhone[i]);
}
do {
accountNumberIsTaken = false;
cout << "\n";
cout << "Enter desired account number: ";
getline(cin, userAccountNumber);
for (int i = 0; i < ACCOUNTS_SIZE; i++) {
if (userAccountNumber == accountNumber[i] || userAccountNumber == "") {
cout << "That account number is already in use" << "\n";
accountNumberIsTaken = true;
break;
}
}
} while (accountNumberIsTaken);
/*
cout << "Enter SSN: ";
getline(cin, userAccountSSN);
cout << "Enter full name: ";
getline(cin, userAccountName);
cout << "Enter address: ";
getline(cin, userAccountAddress);
cout << "Enter phone number: ";
getline(cin, userAccountPhone);
for (int i = 0; i < ACCOUNTS_SIZE; i++) {
if (accountNumber[i] == "") {
cout << "empty space found at" << i;
accountNumber[i] = userAccountNumber;
accountSSN[i] = userAccountSSN;
accountName[i] = userAccountName;
accountAddress[i] = userAccountAddress;
accountPhone[i] = userAccountPhone;
break;
}
}
for (int i = 0; i < ACCOUNTS_SIZE; i++) {
fout << accountNumber[i] << "\n";
fout << accountSSN[i] << "\n";
fout << accountName[i] << "\n";
fout << accountAddress[i] << "\n";
fout << accountPhone[i] << "\n";
}
*/
}
The issue:
The base code, without anything commented out, does not work at all.
Both the accountSearch() and addAccount() functions which rely on reading "accounts.txt" will report that an account number clearly present on "accounts.dat" is not present.
After commenting out ofstream fout(fileName); and the lower part of the addAccount() that relies on writing to the file AND making a slight change to the "accounts.txt" file and saving changes, things start working again
This project is being written in Visual Studio 2019.
Apologies if this is a poor explanation. Please ask for clarification if necessary.
You can't have filename opened as both an ifstream and an ofstream at the same time! So, move your declaration/constructor for fout to after the code for reading fin, like this:
void addAccount(string fileName) {
string accountNumber[ACCOUNTS_SIZE];
string accountSSN[ACCOUNTS_SIZE];
string accountName[ACCOUNTS_SIZE];
string accountAddress[ACCOUNTS_SIZE];
string accountPhone[ACCOUNTS_SIZE];
ifstream fin(fileName);
// ofstream fout(fileName); /// CANNOT BE HERE!
string userAccountNumber;
///... Here, have all your reading and input code (as it is) …
///...
///... Finished reading, etc., so CLOSE "fin" then get the "fout" …
fin.close();
ofstream fout(fileName); // NOW we can create the output stream!
///... and use your existing code to do the writing
for (int i = 0; i < ACCOUNTS_SIZE; i++) {
fout << accountNumber[i] << "\n";
fout << accountSSN[i] << "\n";
fout << accountName[i] << "\n";
fout << accountAddress[i] << "\n";
fout << accountPhone[i] << "\n";
}
fout.close(); /// When finished, CLOSE the file!
}
I am doing something that requires a password.
right now I am able to create files and store custom user input in that but I cant seem to find anywhere how to store a variable with the user created value, and make it so that the next time the program starts it will be able to read that file and understand the value.
#include "stdafx.h"
#include "string"
#include "iostream"
#include "fstream"
#include "windows.h"
using namespace std;
int main() {
string user;
string pass;
string entry;
std::ifstream f("test.txt");
if (f.fail()) {
std::ofstream outfile("test.txt");
cout << "Please make a username.\n";
cin >> user;
cout << "Please make a password.\n";
cin >> pass;
outfile << user << std::endl;
outfile << pass << std::endl;
outfile.close();
cout << "Please restart.\n";
int x = 3000;
Sleep(x);
}
else {
cout << "please enter username\n";
cin >> entry;
if (entry == user) {
cout << "Welcome";
int x = 3000;
Sleep(x);
}
else if (entry != user) {
cout << "Nope";
int x = 3000;
Sleep(x);
}
}
return 0;
}
You haven't added the necessary code to read the saved user name and password. In the else part of the function, add
f >> user;
f >> pass;
as the first two lines.
else {
// Read the user name and password from the file.
f >> user;
f >> pass;
cout << "please enter username\n";
cin >> entry;
if (entry == user) {
cout << "Welcome";
int x = 3000;
Sleep(x);
}
else if (entry != user) {
cout << "Nope";
int x = 3000;
Sleep(x);
}
}
You can use string::find function to search your string in a file after ifstream.
if (string1.find(string2) != std::string::npos)
{
std::cout << "found\n";
}
else
{
std::cout << "not found\n";
}
We did a very similar type of code in C++ class but my version isn't working right, even though it is line-by-line (almost) the same.
My code is meant to save a user's Pokemon and they can add and delete as they please. My display function is working but my add and delete function are not. All the files are opening, but it's not overwriting the file like it's supposed to. Really unsure of what to do, I'm very much a beginner and I don't know much.
Here is what I've got so far:
string name[100];
string type[100];
int level[100];
string newPokemon;
string newType;
int newLevel;
ifstream fin;
ofstream fout;
int numberOfPokemon = 0;
//Input Pokemon Info
cout << "Name of Pokemon: ";
getline(cin, newPokemon);
cin.ignore(100, '\n');
cout << "Pokemon type: ";
getline(cin, newType);
cin.ignore(100, '\n');
cout << "Pokemon level: "; //weird gap between "Pokemon type" and "pokemon level". I have to press enter twice from "pokemon type" to get to "pokemon level"
cin >> newLevel;
cin.ignore(5, '\n');
fin.open("pokemon.txt");
//Put file in array
if (fin.is_open())
{
while (isalnum(fin.peek()) && numberOfPokemon < 100)
{
getline(fin, name[numberOfPokemon]);
getline(fin, type[numberOfPokemon]);
fin >> level[numberOfPokemon];
fin.ignore(100, '\n');
if (name[numberOfPokemon] != newPokemon)
numberOfPokemon++;
}
fin.close();
}
//Output file
fout.open("pokemon.txt");
if (fout.is_open())
{
for (int i = 0; i < numberOfPokemon; i++)
{
fout << name[i] << "\n";
fout << type[i] << "\n";
fout << level[i] << "\n";
}
//Tack on new piece
fout << newPokemon << "\n";
fout << newType << "\n";
fout << newLevel << "\n";
fout.close();
cout << "Add Successful\n";
}
else
{
cout << "Add Failure\n";
}
and now my delete function:
string name[100];
string type[100];
int level[100];
int pokemonCount = 0;
string deletedPokemon = "";
bool found = false;
ifstream fin;
cout << "Which Pokemon would you like to delete?" << endl;
getline(cin, deletedPokemon);
cin.ignore(5, '\n');
fin.open("pokemon.txt");
if (fin.is_open())
{
while (isalnum(fin.peek()))
{
getline(fin, name[pokemonCount]);
getline(fin, type[pokemonCount]);
fin >> level[pokemonCount];
fin.clear();
fin.ignore(100, '\n');
if (deletedPokemon == name[pokemonCount])
{
pokemonCount--;
found = true;
}
pokemonCount++;
}
fin.close();
cout << "ya the file opened" << endl; //always appears
}
ofstream fout;
fout.open("pokemon.txt");
if (fout.is_open())
{
for (int i = 0; i < pokemonCount; i++)
{
fout << name[i] << "\n";
fout << type[i] << "\n";
fout << level[i] << endl;
}
fout.close();
cout << "pokemon removed\n";
cout << "the file opened."; //it is returning that the file opened in both occasions in this function but nothing is happening!
}
else
{
cout << "removal failure";
cout << "The file didn't open";
}
return found;
at the end of this function (if I chose to delete one), it will offer the "Would you like to add a Pokemon?" but it wont let me input an answer and it will just end the program.
The default behaviour of ofstream::open is to simply open the file for reading and writing. If you want to overwrite the file, you need to specify it in your call to open.
fout.open("pokemon.txt", ios_base::in|ios_base::out|ios_base::trunc);
Make sure your file is not marked as read-only under properties.
Also, there is a bug in your delete function:
The bfound should be replace with nDelete pokemon and when you write out the file:
if (deletedPokemon == name[pokemonCount])
{
pokemonCount--;
found = true;
nDeleteIndex = i;
}
....
for (int i = 0; i < pokemonCount; i++)
{
if(i == nDeleteIndex)
continue;
fout << name[i] << "\n";
fout << type[i] << "\n";
fout << level[i] << endl;
}
Right now it will re-write all your pokemons without skipping the one you want to delete!
Also, what happens if the user has 155 pokemons for a full index. You want to use:
std::vector<string> names;
....
string szPokemon;
getline(fin, name[numberOfPokemon]);
names.push_back(szPokemon);
Thus you no longer have a limit !
Here is much cleaner code, its much more maintainable and whenever you add/remove a field from the pokemon (Shiny? Male/Female ? Unique ?) you will be able to easily do it inside the CPokemonObject instead of having to copy paste the code 100 times.
#include "stdafx.h"
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <vector>
using namespace std;
#define POKEMON_FILE "Pokemon.txt"
class CPokemon
{
public:
string szName;
string szType;
int nLevel;
CPokemon() : szName("Pika"), nLevel(10), szType("Lightning")
{};
void Read(ifstream &file)
{
file >> szName;
file >> szType;
file >> nLevel;
};
void Write(ofstream &file)
{
file << szName << endl;
file << szType << endl;
file << nLevel << endl;
};
void CreatePokemon()
{
//Input Pokemon Info
cout << "Name of Pokemon: ";
getline(cin, szName);
cout << "Pokemon type: ";
getline(cin, szType);
cout << "Pokemon level: "; //weird gap between "Pokemon type" and "pokemon level". I have to press enter twice from "pokemon type" to get to "pokemon level"
cin >> nLevel;
}
};
void WritePokemons(vector<CPokemon>& Pokemons)
{
ofstream fout;
fout.open(POKEMON_FILE);
//check the file open
if (!fout.is_open())
{
cout << "removal failure";
cout << "The file didn't open";
return;
}
//Write out all the pokemons
for (unsigned int i = 0; i < Pokemons.size(); i++)
Pokemons[i].Write(fout);
fout.close();
}
void ReadPokemons(vector<CPokemon>& Pokemons)
{
ifstream fin;
fin.open(POKEMON_FILE);
if (fin.is_open())
{
while (isalnum(fin.peek()))
{
CPokemon Pokemon;
Pokemon.Read(fin);
Pokemons.push_back(Pokemon);
}
fin.close();
cout << "ya the file opened" << endl; //always appears
}
}
bool DeletePokemon()
{
vector<CPokemon> Pokemons;
string szPokemonToDelete = "";
cout << "Which Pokemon would you like to delete?" << endl;
cin >> szPokemonToDelete;
//Read all pokemons
ReadPokemons(Pokemons);
ofstream fout;
fout.open("pokemon.txt");
//check the file open
if (!fout.is_open())
{
cout << "removal failure";
cout << "The file didn't open";
return false;
}
bool bFound = false;
for (unsigned int i = 0; i < Pokemons.size(); i++)
{
//Skip the pokemon to delete
if(Pokemons[i].szName == szPokemonToDelete)
{
bFound = true; //we found the pokemon to delete
continue;
}
Pokemons[i].Write(fout);
}
fout.close();
return bFound;
}
void AddPokemon()
{
vector<CPokemon> Pokemons;
//Read all pokemons from the file
ReadPokemons(Pokemons);
//Create the new porkemon
CPokemon Pokemon;
Pokemon.CreatePokemon();
//Add the pokemon to the list
Pokemons.push_back(Pokemon);
//Output file
WritePokemons(Pokemons);
}
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.
I can write into a relative file1, then when I try to read the content and display it on the screen (to check if data are actually into the file), I do not have the records which I believe are already present in the file. I am using Dev-C++. Any help will be appreciated. The code is below;
#include <iostream> // cin, cout
#include <iomanip>
#include <fstream>
#include <conio.h>
using namespace std;
#define SIZE 10
struct client // Client record
{
int account; // from 1 to SIZE
char name[20];
double balance;
};
void make_file(char filename[], int number_of_records)
{
cout << "\nMAKE_FILE: Creating a blank relative file " << filename
<< " containing " << number_of_records << " records.";
ofstream OS(filename, ios::out);
if(!OS) {cerr << "File open error." << endl; exit(1);}
client blank={0, "", 0.0}; // Create an empty client record
while(number_of_records--)
OS.write((char *)&blank, sizeof(blank));
cout << "\nFile created.";
OS.close();
}
int main(void)
{
client c;
void *ptr;
int n=0;
char *fname = "credit.txt";
make_file(fname, SIZE);
fstream iof("credit.txt",ios::in | ios::out);
if(!iof)
{
cerr<<"File open error! "<<endl;
exit(1);
}
cout<<"\n\nenter the 10 customers into the file: "<< fname<<endl<<endl;
while(0 < c.account) // && c.account <= maxrec)
{
iof.seekp((c.account-1) * sizeof(client)); // position the pointer
iof.write((char *)&c, sizeof(c));
cout << "Account[1.."<< SIZE
<< "], Name, Balance (0 0 0 to exit)= ";
cin >> c.account >> c.name >> c.balance;
}
cout << "\n\nSHOW_FILE: The contents of file " << fname;
iof.seekg (0, ios::beg);
while(iof.read((char *)&c, sizeof(c))) //where I think the problem is
{
cout <<'\n'<< setw(3)<< ++n << setw(6) << c.account <<setw(20)
<< c.name << setw(10) << c.balance ;
// << " | " << IS.eof() << " " << ptr;
}
iof.close();
cout << "\n\n";
system("pause");
return 0;
}
A relative file is a file in which each record is identified by its ordinal position in the file allowing for random as well as sequential access.
Relative Files
Relative file organization
http://cayfer.bilkent.edu.tr/~cayfer/ctp108/relative.htm
You need to use binary reading/writing.
fstream iof("credit.txt",ios::in | ios::out | ios::binary);
In your code, in first loop, c.account is not initialitzed. Perhaps you are overwriting file with uninitialized values:
while(0 < c.account) // <--- c.account is not initialized!!
{
iof.seekp((c.account-1) * sizeof(client)); // position the pointer
iof.write((char *)&c, sizeof(c)); // <-- overwriting data??
You're program intrigued me since I haven't done too much work with iostream. If you were ever working with data that had to be edited on a per record basis you'd use some type of database or specialized library that would encapsulate you from all this stuff, such as an xml library. Since your data is so small it's easier to just load all of it into your application using an array of your data structs. After, when you've got new user input, it's easiest clear the file, and the write the data fresh. Here is what I did.
#include <stdio.h>
#include <tchar.h>
#include <iostream> // cin, cout
#include <iomanip>
#include <fstream>
#include <conio.h>
using namespace std;
#define SIZE 10
#define BUFFER_SIZE 100
#define NAME_SIZE 20
struct client // Client record
{
int account; // from 1 to SIZE
char name[NAME_SIZE];
double balance;
};
/* Makes file if files does not exist.
* Returns true if file already exists
*/
bool make_file(char filename[], int number_of_records)
{
// Check if file exists
fstream file;
file.open(filename, ios_base::out | ios_base::in); // will not create file
if (file.is_open())
{
file.close();
return true;
}
else
{
file.clear();
file.open(filename, ios_base::out);
if(!file) {cerr << "File open error." << endl; exit(1);}
cout << "File created. \n";
file.close();
return false;
}
}
/* Create an application that reads x number of accounts from a text file
* into an array of client data structures.
*/
int _tmain(int argc, _TCHAR* argv[])
{
client clientArray[SIZE];
char cleanName[NAME_SIZE];
for(int i = 0; i < NAME_SIZE; i++)
cleanName[i] = NULL;
// Make file if doesn't not exist.
char *fname = "credit.txt";
bool fileExisted = false;
fileExisted = make_file(fname, SIZE);
// initialize client array
for(int j = 0; j < SIZE; j++)
{
clientArray[j].account = -1;
strcpy_s(clientArray[j].name, cleanName);
clientArray[j].balance = 0.0;
}
// Open file and populate the client array
fstream readFile("credit.txt", ios::in | ios::binary);
if(fileExisted)
{
if(!readFile)
{
cerr<<"File open error! "<<endl;
exit(1);
}
int index = 0;
bool firstRun = true;
client temp;
while(index < SIZE)
{
readFile >> temp.account;
readFile >> temp.name;
readFile >> temp.balance;
if(readFile.eof())
break;
if(firstRun)
{
cout << "Data read \n";
cout << "----------\n";
firstRun = false;
}
clientArray[index].account = temp.account;
strcpy_s(clientArray[index].name, temp.name);
clientArray[index].balance = temp.balance;
cout << setw(3) << index+1;
cout << setw(6) << clientArray[index].account;
cout << setw(20) << clientArray[index].name;
cout << setw(10) << clientArray[index].balance << "\n";
index++;
}
readFile.close();
readFile.clear();
}
// Get user input
{
client temp; // Create and initialize temp client
temp.account = 0;
temp.balance = 0;
strcpy_s(temp.name, cleanName);
int index = 0;
bool keepLooping = true;
while(keepLooping)
{
cout << "Account[1.."<< SIZE << "], Name, Balance (-1 to exit)= ";
cin >> temp.account;
// If user exited
if(temp.account == -1)
keepLooping = false;
else
{
cin >> temp.name; // If not keep reading data
cin >> temp.balance;
// Find either unused account or same account
bool found = false;
int firstEmpty = -1;
for(int i = 0; i<SIZE; i++)
{
if(temp.account == clientArray[i].account) // Same account found
{
strcpy_s(clientArray[i].name, temp.name);
clientArray[i].balance = temp.balance;
found = true;
break;
}
else if((clientArray[i].account == -1)&&(firstEmpty == -1)) // Empty account found
{
firstEmpty = i;
}
}
if((firstEmpty != -1)&&(!found)) // Copy input to empty account
{
clientArray[firstEmpty].account = temp.account;
strcpy_s(clientArray[firstEmpty].name, temp.name);
clientArray[firstEmpty].balance = temp.balance;
}
else if(found) //
{
cout << "Updating Client Data. \n";
}
else // No empty accounts break loop
{
cout << "Client array is full!\n";
keepLooping = false;
}
}
}
} // end of user input scope
// Clear file and write only valid data to new file
{
ofstream out;
out.open("credit.txt");
for(int i=0 ; i<SIZE ; i++)
{
if(clientArray[i].account != -1)
{
out << clientArray[i].account << "\t";
out << clientArray[i].name << "\t";
out << clientArray[i].balance << "\n";
}
}
out.close();
out.clear();
}
// Open file and read the data
{
ifstream readFile("credit.txt", ios::in | ios::binary);
// readFile("credit.txt", ios::in | ios::binary);
if(!readFile)
{
cerr<<"File open error! "<<endl;
exit(1);
}
if(!readFile.good())
{
cerr<<"File open error!2"<<endl;
exit(1);
}
int index = 0; // scope variables
client temp;
temp.account = 0;
temp.balance = 0;
strcpy_s(temp.name, cleanName);
cout << "\nAccounts" << "\n";
cout << "----------" << "\n";
bool readFileb = readFile.good();
while(index < SIZE)
{
readFile >> temp.account;
readFile >> temp.name;
readFile >> temp.balance;
if(readFile.eof())
break;
cout << setw(3) << index+1;
cout << setw(6) << temp.account;
cout << setw(20) << temp.name;
cout << setw(10) << temp.balance << "\n";
index++;
}
readFile.close();
readFile.clear();
}
system("pause");
}