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");
}
Related
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();
}
}
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 want to take data from file and store it in string array and and perform a search function with only few information like type"j" and the program able to look for data name which contain "j".
but my program cannot work.....
i am wondering am i using the strstr() correctly or not?
my text file :
Jason Derulo
5000
Martin Delux
8752
Justin Haber
51855
Alex Zander
52163
and
coding:
#include <iostream>
#include <fstream>
#include <cstring>
using namespace std;
//---------------------------------------------------------------------------------------------------------
typedef struct
{
char name[30],adv_srh_name[30];
double balance;
}ACCOUNT;
int main()
{
ACCOUNT record[31];
int choice,acc_amount=0;
ifstream openfile("list.txt"); //open text file
if (!openfile)
{
cout << "Error opening input file\n";
return 0;
}
else
{
ACCOUNT temp;
int i = 0;
double d = 0;
while (openfile)
{
openfile.getline(temp.name, 30, '\n');
//consume the newline still in the stream:
if ((openfile >> d).get()) { temp.balance = d; }
record[i] = temp;
i++;
}
openfile.close(); //close text file
acc_amount = i;
}
cout << "Please enter a client name:";
fflush(stdin);
cin.getline(adv_srh_name, 30);
for (int j = 0; adv_srh_name[j] != NULL; j++)
adv_srh_name[j] = toupper(adv_srh_name[j]);
cout << adv_srh_name;
for (int a = 0; a < acc_amount; a++)
{
if ((strstr(record[a].name, adv_srh_name)) != NULL)
{
cout << "Name :" << record[a].name << "\n";
cout << "Balance :" << record[a].balance << "\n\n";
}
}
return 0;
}
my text file was like
123456123456
Jason
uk
012456788
1000
456789456789
david
uk
012456788
1000
i'm trying to get the data from a text file and save it into arrays
however when i want to store the data from the text file into array it loop non-stop.
what should i do ?
the problem exiting in looping or the method i get the data from text file ?
code:
#include <iostream>
#include <fstream>
using namespace std;
typedef struct {
char acc_no[12];
char name[30];
char address[50];
char phone_no[12];
double balance;
} ACCOUNT;
//function prototype
void menu();
void read_data(ACCOUNT record[]);
int main() {
ACCOUNT record[31]; //Define array 'record' which have maximum size of 30
read_data(record);
}
//--------------------------------------------------------------------
void read_data(ACCOUNT record[]) {
ifstream openfile("list.txt"); //open text file
if (!openfile) {
cout << "Error opening input file\n";
return 0;
} else {
int loop = -1; //size of array
cout << "--------------Data From File--------------"<<endl;
while (!openfile.eof()) {
if (openfile.peek() == '\n')
openfile.ignore(256, '\n');
openfile.getline(record[++loop].acc_no, 12);
openfile.getline(record[loop].name, 30);
openfile.getline(record[loop].address, 50);
openfile.getline(record[loop].phone_no, 12);
openfile >> record[loop].balance;
}
openfile.close(); //close text file
for (int i = 0; i <= loop + 1; i++) {
cout << "Account " << endl;
cout << "Account No. : " << record[i].acc_no << endl;
cout << "Name : " << record[i].name << endl;
cout << "Address : " << record[i].address << endl;
cout << "Phone Number : " << record[i].phone_no << endl;
cout << "Balance : " << record[i].balance << endl;
}
}
}
UPDATE:
The OP didn't properly cite the correct format in his data file. This answer is only valid up until the last iteration.
Don't use .eof() - that's more applicable to when you want to open the file and read it by characters.
A better way would be to use the insertion operator >> as follows:
#define ARR_SIZE 31
ACCOUNT temp;
ACCOUNT record[ARR_SIZE];
int i=0;
while(i < ARR_SIZE) {
openfile >> temp.acc_no >> temp.name >> temp.address >> temp.phone_no >> temp.balance;
record[i] = temp;
i++;
}
Of course, even better is to use std::string to hold the values from the input file, in addition to using std::vectors instead of arrays.
Why does this file always contain an extra Fraction structure? If a user enters option 3 to view all fractions when the program just starts (the file should be empty), 0/0 is printed out. If a user selects option one and enters a fraction 1/1, and then selects option 3, two fractions are printed out 1/1 1/1.
Note: to run this you will need to create an empty .dat file called "fractions.dat"
I really appreciate your help!
#include <iostream>
#include <fstream>
using namespace std;
struct Fraction
{
int num, den;
};
int search(fstream& file, Fraction* f);
int menu();
void proccessChoice(int i);
Fraction* readFrac();
Fraction* fracs[100];
int index;
string fileName = "fractions.dat";
fstream file(fileName, ios::in | ios::out | ios::binary | ios::trunc);
//structure called Fraction with num and den as its only integer members
int main()
{
if (!file)
{
cout << "Error opening file. Program aborting.\n";
system("pause");
exit(1);
}
int choice;
do
{
choice = menu();
proccessChoice(choice);
} while(choice != 4);
system("pause");
return 0;
}
int menu()
{
int c;
cout << "1.Enter new fraction" << endl;
cout << "2.Display/update a fraction" << endl;
cout << "3.Display all fractions" << endl;
cout << "4.Quit" << endl;
cin >> c;
return c;
}
void proccessChoice(int i)
{
switch(i)
{
case 1:
{
cout << "Enter a fraction to add: ";
fracs[index] = readFrac();
file.seekp(0, ios::end);
file.write(reinterpret_cast<char*>(fracs[index]), sizeof(Fraction));
/*cout << fracs[index]->num << "/" << fracs[index]->den ;*/
index++;
}
break;
case 2:
{
cout << "Enter fraction to view/update: ";
Fraction* fToFind = readFrac();
int i = search(file, fToFind);
if (i == -1)
{
cout << "Fraction not found." << endl;
}
else
{
char r;
cout << fToFind->num << "/" << fToFind->den << " found at index " << i << ". Update? [y/n]";
cin >> r;
if(r == 'y' || r == 'Y')
{
cout << "Enter a new fraction: ";
Fraction* fToWrite = readFrac();
file.seekp(sizeof(Fraction) * (i));
file.write(reinterpret_cast<char*>(fToWrite), sizeof(Fraction));
}
}
cout << i << endl;
cout << "Case 2" << endl;
}
break;
case 3:
{
Fraction* cur = new Fraction();
//int pos = -1;
if (!file)
{
cout << "Error opening file. Program aborting.\n";
system("pause");
exit(1);
}
file.seekg(0, ios::beg);
while(!file.eof())
{
file.read(reinterpret_cast<char *>(cur), sizeof(Fraction));
cout << cur->num << "/" << cur->den << endl;
}
cout << "Case 3" << endl;
}
break;
}
}
int search(fstream& file, Fraction* f)
{
Fraction* cur = new Fraction();
int pos = -1;
if (!file)
{
cout << "Error opening file. Program aborting.\n";
system("pause");
exit(1);
}
file.seekg(0, ios::beg);
while(!file.eof())
{
file.read(reinterpret_cast<char *>(cur), sizeof(Fraction));
if((cur->num == f->num) && (cur->den == f->den))
{
cout << "\nFrac found!" << cur->num << "/" << cur->den<<endl;
pos = file.tellg()/sizeof(Fraction) - 1;
return pos;
}
}
return pos;
}
Fraction* readFrac()
{
Fraction* f = new Fraction();
char slash;
cin >> f->num >> slash >> f->den;
return f;
}
Attempted solution 1: works for the first attempt of the user to view all fractions but on the second attempt the file is not found.
case 3:
{
Fraction* cur = new Fraction();
//int pos = -1;
if (!file)
{
cout << "Error opening file. Program aborting.\n";
system("pause");
exit(1);
}
file.seekg(0, ios::beg);
while(!file.eof())
{
if(file.read(reinterpret_cast<char *>(cur), sizeof(Fraction)).gcount()== sizeof(Fraction))
{
cout << cur->num << "/" << cur->den << endl;
}
}
cout << "Case 3" << endl;
}
break;
}
Because you didn't yet reach the end of the file!
while(!file.eof())
You opened the empty file, however, note that the read cursor is currently at position 0. As long as you didn't attempt to read data file.eof() will be false, as the end of file hasn't been reached yet by the cursor.
You'll need to check whether you were actually able to extract the Fraction:
if(
file.read(reinterpret_cast<char *>(cur), sizeof(Fraction)).gcount()
== sizeof(Fraction)
){
// Fraction has been extracted
}
else
// either eof() or some other error.
Note that this gets much simpler if you provide a custom operator for this:
std::istream& operator>>(std:istream& in, Fraction& f){
return in.read(reinterpret_cast<char *>(&f), sizeof(Fraction));
}
// ....
while(file >> *cur){
// ... your code.
}