Reading and writing from a file - c++

I need to make card catalog entries for a library system and will need a menu and save the card and read the card from a file. I'm just looking for help and not saving for anyone to do it just tips if you have any because I want ro learn and not just copy and paste.
I already finished the information they need to add but having a problem making them save and read from a file and choosing from the menu to add new entry, review entry.
#include <iostream>
#include <fstream>
#include <cstdlib>
using namespace std;
struct libary
{
string title;
string author;
string ISBN_code;
int page_count;
int publish_year;
} s[10];
bool processMenu()
{
int choice, spot;
cout << "Main Menu" << endl;
cout << "Select your options" << endl;
cout << "1. Add a new entry to the system" << endl;
cout << "2. Review an entry" << endl;
cout << "3. Save entries to a file" << endl;
cout << "4. Read entries from a file" << endl;
cin >> choice;
switch (choice)
{
case 1:
cout << "which spot do you want to add a entry to the system " << endl;
cin >> spot;
break;
case 2:
cout << "which spot do you want to review to a file " << endl;
cin >> spot;
break;
case 3:
cout << "Save entries to a file" << endl;
ofstream myfile;
myfile.open("file.txt");
myfile << "this will show in the file";
break;
case 4:
cout << "read entries from a file :" << endl;
break;
case 7:
return 0;
}
}
int main()
{
while (!processMenu())
{
cout << "Sorry, that is not a valid choice." << endl;
cout << "Please try again." << endl << endl << endl;
}
cout << " Enter information of each card catalog" << endl;
for (int i = 0; i < 10; i++)
{
cout << endl;
cout << " Enter title " << endl;
cin >> s[i].title;
cout << endl;
cout << " Enter author " << endl;
cin >> s[i].author;
cout << endl;
cout << " Enter Page count " << endl;
cin >> s[i].page_count;
cout << endl;
cout << " Enter publish year " << endl;
cin >> s[i].publish_year;
cout << endl;
cout << " Enter ISBN code, it should be 13 digits" << endl;
cin >> s[i].ISBN_code;
while (s[i].ISBN_code.length() != 13)
{
cout << " Please enter a ISBN code thats 13 digits" << endl;
cin >> s[i].ISBN_code;
cout << endl;
cout << endl;
}
}
cout << " Displaying Information" << endl;
for (int i = 0; i < 10; i++)
{
cout << " title: " << s[i].title << endl;
cout << " author: " << s[i].author << endl;
cout << " page count: " << s[i].page_count << endl;
cout << " publish year: " << s[i].publish_year << endl;
cout << " ISBN code: " << s[i].ISBN_code << endl;
}
return 0;
}
It lets me pick a spot but won't add new entry nor review or save/read.

You can make your own type writable to a stream (cout or ofstream) and/or readable from a stream (cin or ifstream) just by overriding its output (operator<<) and/or input operator (operator>>).
#include <fstream> // ifstream, ofstream
#include <iostream> // cin, cout
#include <string> // getline, string
using namespace std;
struct Card
{
// Writing to the standard output ('cout').
friend ostream& operator<<(ostream& os, const Card& card);
// Reading from the standard input ('cin').
friend istream& operator>>(istream& is, Card& card);
// Writing to a file ('ofstream').
friend ofstream& operator<<(ofstream& os, const Card& card);
// Reading from a file ('ifstream).
friend ifstream& operator>>(ifstream& is, Card& card);
string title = "";
string author = "";
string isbn = "";
int page_count = -1;
int publish_year = -1;
};
ostream& operator<<(ostream& os, const Card& card)
{
os << "Title: " << card.title << '\n'
<< "Author: " << card.author << '\n'
<< "ISBN: " << card.isbn << '\n'
<< "Page count: " << card.page_count << '\n'
<< "Publish year: " << card.publish_year << '\n';
return os;
}
istream& operator>>(istream& is, Card& card)
{
// 'getline' needs for the reading of strings because the title of a book or
// its author's name may contain Space (' ') characters. 'cin' and
// 'ifstream' separate input by every whitespace. So, if we want to allow
// spaces in our fields we have to separate them by a special delimiter
// character. We use the Newline ('\n') character here to separate fields.
// `page_count` and `publish_year` are numbers, they don't contain
// whitespaces, so they simply can be read with 'operator>>'.
cout << "Title: ";
std::getline(is, card.title);
cout << "Author: ";
std::getline(is, card.author);
cout << "ISBN code: ";
std::getline(is, card.isbn);
cout << "Page count: ";
is >> card.page_count;
cout << "Publish year: ";
is >> card.publish_year;
return is;
}
// The next two functions is for files.
ofstream& operator<<(ofstream& os, const Card& card)
{
os << card.title << '\n'
<< card.author << '\n'
<< card.isbn << '\n'
<< card.page_count << '\n'
<< card.publish_year << '\n';
return os;
}
ifstream& operator>>(ifstream& is, Card& card)
{
std::getline(is, card.title);
std::getline(is, card.author);
std::getline(is, card.isbn);
is >> card.page_count;
is >> card.publish_year;
return is;
}
int main()
{
Card card;
// Read the informations of a card from the standard input.
cin >> card;
// Write the informations of a card to the standard output.
cout << card;
// Write the informations of a card to "file.txt".
ofstream ofs("file.txt");
ofs << card;
ofs.close();
// Read the informations of a card from "file.txt".
ifstream ifs("file.txt");
ifs >> card;
ifs.close();
return 0;
}
Important: For the sake of simplicity, I omitted error checking at the opening of a file and at the writing/reading of a stream. In your code you should do these.

Related

Reading Input file and writing to output file one section at a time, skipping lines in getline()

I'm very new to C++ and am having difficulty with the getline() command skipping the lines from the input file and am unsure what my issue is.
The goal of the program is to read in an input file one "section" at a time, put it into a structure, and then output that line to the file, and continue until there aren't any more lines in the file.
The input files look like this:
000.000.0000
lastname
street
city
state
zipcode
firstname
000.000.0000
lastname
street
....
etc...
when I run the program, it outputs to the out file, but it skips and lines and continues to repeat those same lines until I forcibly stop the program.
#include <iostream>
#include <fstream>
#include <iomanip>
#include <string>
#include <climits>
using namespace std;
struct Person
{
string firstName;
string lastName;
string phoneNumber;
};
struct Address
{
string streetNum_Name;
string city;
string state;
int zip_code;
};
struct Info
{
Person person;
Address address;
};
void printFileHeader(ofstream& outFile);
bool openInputFile(ifstream& inFile);
void openOutputFile(ofstream& outFile);
struct Info readInfo(ifstream& inFile, Info&);
void printInfo(ofstream& outFile, Info&);
int main()
{
ifstream inFile;
ofstream outFile;
bool fileStreamState;
Info person;
printFileHeader(outFile);
fileStreamState = openInputFile(inFile);
openOutputFile(outFile);
cout << "Processing information. Please Wait...." << endl << endl;
while (fileStreamState) {
readInfo(inFile, person);
printInfo(outFile, person);
}
outFile << setw(7) << "-----" << setw(20) << "---------" << setw(15) << "----------" << setw(20) << "----"
<< setw(12) << "------------" << endl;
cout << "Program has finished execution." << endl;
inFile.close();
outFile.close();
}
void printFileHeader(ofstream& outFile) {
outFile << left << setw(7) << "Entry" << setw(20) << "Last Name" << setw(15) << "First Name" << setw(20) << "City"
<< setw(12) << "Phone Number" << endl;
outFile << setw(7) << "-----" << setw(20) << "---------" << setw(15) << "----------" << setw(20) << "----"
<< setw(12) << "------------" << endl;
}
bool openInputFile(ifstream& inFile) {
string filename;
cout << "Enter the name of the input file: ";
cin >> filename;
cout << filename << endl << endl;
inFile.open(filename.c_str());
while(inFile.fail()) {
cout << string(15,'*') << " File Open Error " << string(15,'*') << endl;
cout << "==> Input file failed to open properly!!\n";
cout << "==> Attempted to open file: " << filename << endl;
cout << "==> Try Again\n";
cout << string(47,'*') << endl<< endl;
inFile.clear();
cout << "Enter in the name of the input file: ";
cin >> filename;
cout << filename << endl << endl;
inFile.open(filename.c_str());
}
return 1;
}
void openOutputFile(ofstream& outFile) {
string filename;
cout << "Enter the name of the output file: ";
cin >> filename;
cout << filename << endl << endl;
outFile.open(filename.c_str());
while(outFile.fail()) {
cout << string(15,'*') << " File Open Error " << string(15,'*') << endl;
cout << "==> Output file failed to open properly!!\n";
cout << "==> Attempted to open file: " << filename << endl;
cout << "==> Try Again\n";
cout << string(47,'*') << endl<< endl;
outFile.clear();
cout << "Enter in the name of the input file: ";
cin >> filename;
cout << filename << endl << endl;
outFile.open(filename.c_str());
}
}
struct Info readInfo(ifstream& inFile, Info& record) {
getline(inFile, record.person.phoneNumber);
cout << record.person.phoneNumber << endl;
inFile.ignore(INT_MAX, '\n');
getline(inFile, record.person.lastName);
cout << record.person.lastName << endl;
inFile.ignore(INT_MAX, '\n');
getline(inFile, record.address.streetNum_Name);
cout << record.address.streetNum_Name << endl;
inFile.ignore(INT_MAX, '\n');
getline(inFile, record.address.city);
cout << record.address.city << endl;
inFile.ignore(INT_MAX, '\n');
getline(inFile, record.address.state);
cout << record.address.state << endl;
inFile.ignore(INT_MAX, '\n');
inFile >> record.address.zip_code;
cout << record.address.zip_code << endl;
inFile.ignore(INT_MAX, '\n');
getline(inFile, record.person.firstName);
cout << record.person.firstName << endl;
return record;
}
void printInfo(ofstream& outFile, Info& record) {
static int entry = 0;
entry++;
outFile << left << setw(7) << entry << setw(20) << record.person.lastName << setw(15) << record.person.firstName
<< setw(20) << record.address.city << setw(12) << record.person.phoneNumber << endl;
}
Any help would be much appreciated, thanks!
You are ignore()'ing data in readInfo() that you should not be ignoring. getline() reads everything up to and including a line break, and then discards the line break. So you are reading the phoneNum data, then ignore()'ing the lastName data, then reading the streetNum data, then ignore()'ing the city data, etc. You need to remove all of the ignore()'s after getline()'s, the only ignore() you need is the one after reading the zip_code with operator>>:
struct Info readInfo(ifstream& inFile, Info& record) {
getline(inFile, record.person.phoneNumber);
cout << record.person.phoneNumber << endl;
getline(inFile, record.person.lastName);
cout << record.person.lastName << endl;
getline(inFile, record.address.streetNum_Name);
cout << record.address.streetNum_Name << endl;
getline(inFile, record.address.city);
cout << record.address.city << endl;
getline(inFile, record.address.state);
cout << record.address.state << endl;
inFile >> record.address.zip_code;
inFile.ignore(INT_MAX, '\n');
cout << record.address.zip_code << endl;
getline(inFile, record.person.firstName);
cout << record.person.firstName << endl;
return record;
}
That being said, your while loop in main() is broken. Once readInfo() reads the last record in the file, if the last firstName ends with a line break then EOF hasn't been reached yet, so while (fileStreamState) will still evaluate as true and the loop will call readInfo() and printInfo() again, even though there is no more record data left to read/print.
There is no good reason to have readInfo() take the struct as a reference and also return it. So you should return a bool instead indicating success/fail:
bool readInfo(ifstream& inFile, Info&);
...
while (readInfo(inFile, person)) {
printInfo(outFile, person);
}
...
bool readInfo(ifstream& inFile, Info& record) {
getline(inFile, record.person.phoneNumber);
cout << record.person.phoneNumber << endl;
getline(inFile, record.person.lastName);
cout << record.person.lastName << endl;
getline(inFile, record.address.streetNum_Name);
cout << record.address.streetNum_Name << endl;
getline(inFile, record.address.city);
cout << record.address.city << endl;
getline(inFile, record.address.state);
cout << record.address.state << endl;
inFile >> record.address.zip_code;
inFile.ignore(INT_MAX, '\n');
cout << record.address.zip_code << endl;
getline(inFile, record.person.firstName);
cout << record.person.firstName << endl;
return !inFile.fail();
}
Online Demo
The complete working program given below shows how you can achieve what you want. I have done some corrections to your given code snippet. Major changes include using a std::vector for storing information and also calling readInfo() and printInfo() only once instead of calling them again and again in a while loop. Using a vector has the advantage that you can use that vector for later purposes(if any).
#include <iostream>
#include <fstream>
#include <iomanip>
#include <sstream>
#include <string>
#include <climits>
#include <vector>
using namespace std;
struct Person
{
string firstName ;
string lastName;
string phoneNumber;
};
struct Address
{
string streetNum_Name;
string city;
string state;
int zip_code = 70; //always initialize built in type in block/local scope
};
struct Info
{
Person person;
Address address;
};
void printFileHeader(ofstream& outFile);
bool openInputFile(ifstream& inFile);
void openOutputFile(ofstream& outFile);
void readInfo(ifstream& inFile, std::vector<Info>&);
void printInfo(ofstream& outFile, std::vector<Info>&);
int main()
{
ifstream inFile;
ofstream outFile;
bool fileStreamState;
std::vector<Info> infoVec; //this vector will contain all the information
//Info person; //no need for this anymore since we have the vector
//printFileHeader(outFile);//call this after openOutputFile()
fileStreamState = openInputFile(inFile);
openOutputFile(outFile);
printFileHeader(outFile);
cout << "Processing information. Please Wait...." << endl << endl;
readInfo(inFile, infoVec) ; //call readInfo once instead of calling again and again
printInfo(outFile, infoVec);//call printInfo once instead of calling again and again
outFile << setw(7) << "-----" << setw(20) << "---------" << setw(15) << "----------" << setw(20) << "----"
<< setw(12) << "------------" << endl;
cout << "Program has finished execution." << endl;
inFile.close();
outFile.close();
}
void printFileHeader(ofstream& outFile) {
outFile << left << setw(7) << "Entry" << setw(20) << "Last Name" << setw(15) << "First Name" << setw(20) << "City"
<< setw(12) << "Phone Number" << endl;
outFile << setw(7) << "-----" << setw(20) << "---------" << setw(15) << "----------" << setw(20) << "----"
<< setw(12) << "------------" << endl;
}
bool openInputFile(ifstream& inFile) {
string filename;
cout << "Enter the name of the input file: ";
cin >> filename;
cout << filename << endl << endl;
inFile.open(filename.c_str());
while(inFile.fail()) {
cout << string(15,'*') << " File Open Error " << string(15,'*') << endl;
cout << "==> Input file failed to open properly!!\n";
cout << "==> Attempted to open file: " << filename << endl;
cout << "==> Try Again\n";
cout << string(47,'*') << endl<< endl;
inFile.clear();
cout << "Enter in the name of the input file: ";
cin >> filename;
cout << filename << endl << endl;
inFile.open(filename.c_str());
}
return 1;
}
void openOutputFile(ofstream& outFile) {
string filename;
cout << "Enter the name of the output file: ";
cin >> filename;
cout << filename << endl << endl;
outFile.open(filename.c_str());
while(outFile.fail()) {
cout << string(15,'*') << " File Open Error " << string(15,'*') << endl;
cout << "==> Output file failed to open properly!!\n";
cout << "==> Attempted to open file: " << filename << endl;
cout << "==> Try Again\n";
cout << string(47,'*') << endl<< endl;
outFile.clear();
cout << "Enter in the name of the input file: ";
cin >> filename;
cout << filename << endl << endl;
outFile.open(filename.c_str());
}
}
void readInfo(ifstream& inFile, std::vector<Info> &infoVec) {
std::string temporaryZipCode;
Info info;
while(getline(inFile, info.person.phoneNumber,'\n'),
getline(inFile, info.person.lastName,'\n'),
getline(inFile, info.address.streetNum_Name,'\n'),
getline(inFile, info.address.city,'\n'),
getline(inFile, info.address.state,'\n'),
getline(inFile, temporaryZipCode, '\n'),
getline(inFile, info.person.firstName,'\n')
)
{
std::istringstream ss(temporaryZipCode);
ss >> info.address.zip_code;
infoVec.emplace_back(info);
}
}
void printInfo(ofstream& outFile, std::vector<Info> &infoVec) {
int entry = 0; //no need for making it static
for(const Info& record: infoVec )
{
outFile << left << setw(7) << entry << setw(20) << record.person.lastName << setw(15) << record.person.firstName
<< setw(20) << record.address.city << setw(12) << record.person.phoneNumber << endl;
entry++;
}
}
The output of the above program can be seen here. I have added comments wherever i have made changes to your program.

Searching for artist name and song from a file in C++

I have written some code for the search function in C++ to find artist name and song. My code doesn't seem to work. A message displays that the artist and song is found and then the menu repeats itself infinite times.
My full program code is as below.
#include "Music.h"
#include<iostream>
#include<fstream>
#include<string>
using namespace std;
void Music::menu()
{
int input;
do {
cout << "Select an option from the menu" << endl;
cout << "1. Display records" << endl;
cout << "2. Search for records" << endl;
cout << "3. Writing records to a file" << endl;
cin >> input;
switch (input) {
case 1:
displayfile();
break;
case 2:
searchrecords();
break;
case 3:
writefile();
break;
default:
cout << "Invalid option entered. Try again" << endl;
menu();
}
} while (input != 4);
}
void Music::displayfile()
{
string line;
ifstream myfile;
myfile.open("Music.txt");
if (myfile.is_open()) {
while (getline(myfile, line)) {
cout << line << endl;
}
myfile.close();
}
else {
cout << "Unable to open file" << endl;
}
}
void Music::writefile()
{
ofstream write;
write.open("Music.txt", ofstream::app);
if (write.is_open()) {
cin.ignore();
cout << "Enter a title of song to the playlist" << endl;
cin.getline(title, 255).get();
write << " " << title;
cout << "Enter the artist of the song to playlist" << endl;
cin.getline(artist, 255).get();
write << " " << artist;
cout << "Enter the year of the song" << endl;
cin >> year;
write << "" << year;
cout << "Enter the duration of the song" << endl;
cin >> duration;
write << " " << duration;
cout << "Writing to a file is successful" << endl;
}
else {
cout << "File couldn't be open" << endl;
}
write.close();
displayfile();
}
bool Music::searchrecords()
{
bool found = true;
string search;
string line;
ifstream myfile;
myfile.open("Music.txt");
cout << "Enter the artist you want to search for: " << endl;
getline(cin, search).get();
cout << "Enter for the song you want to search for: " << endl;
getline(cin, search).get();
if (myfile.is_open()) {
while (!myfile.eof()) {
if (found) {
cout << "The artist is found" << search << endl;
cout << "The song is found" << search << endl;
return found;
}
else {
cout << "The artist is not found" << endl;
return false;
}
getline(myfile, line);
myfile.close();
displayfile();
}
}
}
Appreciate it if you could help me as I am stuck on what to do.
You have bool found = true; right in the beginning of Music::searchrecords function, so the first iteration of looking through file immediately returns.
You do getline(cin, search).get(); twice in a row, while apparently you want to read in two different string variables, one for artist, one for song
You do a loop with this if on each iteration
if (found) {
cout << "The artist is found" << search << endl;
cout << "The song is found" << search << endl;
return found;
}
else {
cout << "The artist is not found" << endl;
return false;
}
In both cases you terminate your function by calling return, so the very first iteration of looking through file returns from function (you don't read the file completely)
You call
myfile.close();
displayfile();
on each iteration, so even if you hadn't had your if right above, then your program would crash anyway, because you close file inside the loop that's iterating over it.
You don't compare line to check if you indeed found your song
In total, your program doesn't work at all, and StackOverflow isn't a forum to completely write the entire program instead of you. So you better use a debugger in your IDE to see what your program does step by step, or take a piece of paper and a pen to write down how you would accomplish your task

Program reading from variables stored in itself and not from binary file

I'm working on a program very important to my programming class, and there's something I can't quite figure out; When I try to read from a binary file I've created after opening the program, it fails even if the file's in the directory, and after I try to wipe the contents of the file, I can still 'read' them from the file even though said file is empty when I examine it in explorer. I've determined from this that even though I'm using BinaryFile.read, it's not truly reading from the file, and instead reading from variables stored in the program itself. How can I get my program to read from the actual file?
(please note that this is not yet a complete program, hence the commented sections and empty functions.)
(Also please note that, due to the nature of my class, I am only allowed to use what has been taught already (namely, anything in the fstream header and most things before which are necessary to make a basic program - he's letting me use things in stdio.h, as well.)
//
// main.cpp
// Binary Program
//
// Created by Henry Fowler on 11/19/14.
// Copyright (c) 2014 Bergen Community College. All rights reserved.
#include <iostream>
#include <iomanip>
#include <fstream>
#include <string>
#include <cstdlib>
#include <math.h>
#include <stdio.h>
using namespace std;
struct Record
{
char Name[20];
char LastName[20];
double Pay;
int Clearance;
int ID;
};
void CreateFile(fstream&); //Working
void CheckExist(fstream&); //Working
void Populate(fstream&,Record[],int&,int&); //Working
void Display(fstream&,Record[],int&,int&); //Working
void Append(fstream&,Record[],int&,int&); //Working
void DeleteFromFile(fstream&,fstream&,Record[],int&,int&);
// void SearchInFile(fstream&,Record[],int&,int&);
// void ModifyRecord(fstream&,Record[],int&,int&);
//void SortFile();
void WipeFile(fstream&);
void DelFile(fstream&);
int main(int argc, const char * argv[])
{
Record EmpRecords[20];
char Binary[] = "BinaryFile.dat";
char Binary2[] = "BinaryFileTemp.dat";
int maxsize; //make sure to set i to max size so you can use it later for things like wiping the file or deleting specific records
fstream BinaryFile;
fstream BinaryFile2;
string InputStr;
// char Read;
//int Choice = 0;
int i = 0;
int choice = 0;
int switchchoice;
CreateFile(BinaryFile); //working
CheckExist(BinaryFile); //working
BinaryFile.close();
while(choice==0)
{
cout << "Options: " << endl;
cout << "End Program (0)" << endl;
cout << "Input new records to file (1)" << endl;
cout << "Display current contents of file (2)" << endl;
cout << "Append a record at the end of the file (3)" << endl;
cout << "Delete a record from the file (4)" << endl;
cout << "Search for a record in the file (5)" << endl;
cout << "Modify a certain record (6)" << endl;
cout << "Sort file (unimplemented)" << endl;
cout << "Wipe contents of file (8)" << endl;
cout << "Please choose an option: ";
cin >> switchchoice;
switch(switchchoice)
{
case 0:
{
cout << "Exiting.";
BinaryFile.close();
system("PAUSE");
return 0;
break;
}
case 1:
{
Populate(BinaryFile, EmpRecords,i,maxsize); //working
break;
}
case 2:
{
Display(BinaryFile, EmpRecords,i,maxsize); //working i think
break;
}
case 3:
{
Append(BinaryFile, EmpRecords,i,maxsize); //working
break;
}
case 4:
{
DeleteFromFile(BinaryFile,BinaryFile2,EmpRecords,i,maxsize); //!
break;
}
case 5:
{
// SearchInFile(BinaryFile, EmpRecords,i,maxsize); //!
break;
}
case 6:
{
// ModifyRecord(BinaryFile, EmpRecords,i,maxsize); //!
break;
}
case 7:
{
cout << "Error, file sorting is currently unimplemented. Please try again.";
break;
}
case 8:
{
WipeFile(BinaryFile);
break;
}
}
}
system("PAUSE");
return 0;
}
void CreateFile(fstream& BinaryFile)
{
BinaryFile.open("BinaryFile.dat", ios::out | ios::binary);
}
void CheckExist(fstream &BinaryFile)
{
if(BinaryFile.good())
{
cout << endl << "File does exist" << endl;
}
else
{
cout << "file named can not be found \n";
system("PAUSE");
}
}
void Populate(fstream &BinaryFile,Record EmpRecords[],int &i, int &maxsize)
{
BinaryFile.open("BinaryFile.dat", ios::out | ios::binary);
int choice = 0;
while(choice==0)
{
cout << "Please input employee first name: ";
cin >> EmpRecords[i].Name;
cout << "Please input employee last name: ";
cin >> EmpRecords[i].LastName;
cout << "Please input Employee Pay: ";
cin >> EmpRecords[i].Pay;
cout << "Please input Employee Clearance (1-10): ";
cin >> EmpRecords[i].Clearance;
cout << "Please input Employee ID (6 numbers, i.e. 122934): ";
cin >> EmpRecords[i].ID;
cout << "Input another employee's information? (0) = yes, (1) = no: ";
cin >> choice;
BinaryFile.write((char *) (&EmpRecords[i]),sizeof(EmpRecords[i]));
i = i+1;
}
maxsize = i;
cout << "i is " << i << endl;
cout << "maxsize is " << maxsize << endl;
BinaryFile.close();
}
void Display(fstream &BinaryFile,Record EmpRecords[],int &i,int &maxsize)
{
BinaryFile.open("BinaryFile.dat", ios::in | ios::binary | ios::app);
int i2 = maxsize;
i = 0;
while(i2>0)
{
BinaryFile.read((char *) (&EmpRecords[i]),sizeof(EmpRecords[i]));
cout << i << endl;
cout << EmpRecords[i].Name << " " << EmpRecords[i].LastName << endl;
cout << "Pay: $" << EmpRecords[i].Pay << endl;
cout << "Clearance: " << EmpRecords[i].Clearance << endl;
cout << "Employee ID: " << EmpRecords[i].ID << endl;
BinaryFile.read((char *) (&EmpRecords[i]),sizeof(EmpRecords[i]));
cout << endl;
i2 = i2-1;
i = i+1;
}
BinaryFile.close();
}
void Append(fstream &BinaryFile,Record EmpRecords[],int &i,int &maxsize)
{
BinaryFile.open("BinaryFile.dat", ios::out|ios::binary|ios::ate|ios::app);
cout << "Please input employee first name: ";
cin >> EmpRecords[maxsize].Name;
cout << "Please input employee last name: ";
cin >> EmpRecords[maxsize].LastName;
cout << "Please input Employee Pay: ";
cin >> EmpRecords[maxsize].Pay;
cout << "Please input Employee Clearance (1-10): ";
cin >> EmpRecords[maxsize].Clearance;
cout << "Please input Employee ID (6 numbers, i.e. 122934): ";
cin >> EmpRecords[maxsize].ID;
cout << "Input another employee's information? (0) = yes, (1) = no: ";
BinaryFile.write((char *) (&EmpRecords[i]),sizeof(EmpRecords[i]));
maxsize = maxsize+1;
cout << "maxsize is " << maxsize << endl;
BinaryFile.close();
}
void DeleteFromFile(fstream &BinaryFile,fstream &BinaryFile2, Record EmpRecords[],int &i,int &maxsize)
{
BinaryFile.open("BinaryFile.dat", ios::out|ios::binary|ios::app);
BinaryFile2.open("BinaryFileTemp.dat", ios::out|ios::binary|ios::app);
int Choice;
cout << "Would you like to delete a file by name or by employee number?" << endl;
cout << "Name (1)" << endl;
cout << "Number (2)" << endl;
cout << "Choice: ";
cin >> Choice;
int i2 = maxsize;
if(Choice==1)
{
cout << "Please input employee first name: ";
// cin >> firstname;
cout << "Please input employee last name: ";
// cin >> lastname;
cout << "Searching...";
int i2 = maxsize;
i = 0;
while(i2>0)
{
BinaryFile.read((char *) (&EmpRecords[i]),sizeof(EmpRecords[i]));
cout << i << endl;
BinaryFile.read((char *) (&EmpRecords[i]),sizeof(EmpRecords[i]));
// if(EmpRecords[i].Name == firstname)
// {
// cout << "Found first name." << endl;
// if (EmpRecords[i].LastName == lastname)
// {
// cout << "Found last name." << endl;
/// }
// }
// else
// {
// cout << "Could not find name.";
// // BinaryFile2.write((char *) (&EmpRecords[i]),sizeof(EmpRecords[i]));
// }
cout << endl;
i2 = i2-1;
i = i+1;
}
}
BinaryFile.close();
if( remove( "BinaryFile.dat" ) != 0 )
cout << endl << "Error deleting file" << endl;
else
{
cout << "File successfully deleted" << endl << endl;
}
int result;
char oldname[]="BinaryFileTemp.dat";
char newname[]="BinaryFile.dat";
result = rename(oldname,newname);
if(result == 0)
cout << "DEBUG: Success" << endl;
else
cout << "DEBUG: Failure" << endl;
}
void WipeFile(fstream &BinaryFile)
{
int sure;
cout << "There is no undoing this action." << endl;
cout << "Continue (1)" << endl;
cout << "Cancel (2)" << endl;
cout << "Wipe file? ";
cin >> sure;
if(sure == 1)
{
cout << "Wiping file.";
BinaryFile.open("BinaryFile.dat", ios::out | ios::binary | ios::trunc);
BinaryFile.close();
}
else
{
cout << "Canceling.";
}
}
void DelFile(fstream &BinaryFile)
{
BinaryFile.close();
if( remove( "BinaryFile.dat" ) != 0 )
cout << endl << "Error deleting file" << endl;
else
{
cout << "File successfully deleted" << endl << endl;
}
}
Here the problem seems to be, even though you are wiping the file contents, you are not clearing the data you had stored in Record EmpRecords[20]; or the int maxsize value.
Few things you can do inside void WipeFile(fstream &BinaryFile) function: To keep it simple, we'll just reset maxsize to 0:
Pass the maxsize variable as reference to WipeFile(), the same way you are passing for Populate()
Update maxsize = 0, to indicate all the records are removed, when you delete the file contents.
It is better to memset the contents of EmpRecords as well similarly.
For now, I just modified your code to reset maxsize to 0 in WipeFile() and it worked.
void WipeFile(fstream &BinaryFile, int &maxsize)
{
int sure;
cout << "There is no undoing this action." << endl;
cout << "Continue (1)" << endl;
cout << "Cancel (2)" << endl;
cout << "Wipe file? ";
cin >> sure;
if(sure == 1)
{
cout << "Wiping file.";
BinaryFile.open("BinaryFile.dat", ios::out | ios::binary | ios::trunc);
BinaryFile.close();
maxsize = 0;
}
else
{
cout << "Cancelling.";
}
}

Database problems in C++

I have been messing with this program for past 8 hours and I do not know where to go further. I am very sorry that my code is in a foreign language, I tried to comment it in English to my best efforts.
I managed to debug it at last.but I have few problems.
1)How to print the first 5 lines(the first 5 lines from the txt fail) and then the previous 5 again?My rather pathetic try is listed below.Example:
At first you have Memento , Godfather. You print the next five
Godfather II , Shawshank Redemption, Leon, A Bittersweet Life,Se7en.Now previous 5:Memento, Godfather,Godfather II, Shawshank Redemption, Leon
2) How to use characters rather than numbers to make a menu in the program?
3)Am I really stupid? Answer honestly, please.
I will take a break now and get some sleep, will go through the replies in the morning, I hope it isnt aganist the rules.
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
void sisend(); /*input*/
string valik(); /*choice*/
void kogukuvand(); /* the whole display of the database */
void valjumine(); /* program quit*/
void sisendvoivaljumine(); /*quiting with output to file or not*/
void viisjuurde(); /* input further 5 lines from the file */
void viismaha(); /* input previous 5 lines from the file*/
int main()
{
system ("title Filmide andmebaas"); /*Movie database*/
system ("cls");
int valik;
cout << "Vajuta klahv 'j',kui tahad naha jargmist 5 kirjet."<< endl; /* j to get extra 5*/
cout << "Vajuta klahv 'e',kui tahad naha eelmist 5 kirjet."<< endl; /* e for previous 5 lines */
cout << "Vajuta klahv 'v',kui tahad lopetada programmi taitumist."<< endl; /* v for the output */
cin >> valik;
switch (valik) { /*choice*/
case 1:
viisjuurde();
break;
case 2:
viismaha();
break;
case 3:
sisendvoivaljumine();
break;
}
}
void viisjuurde()
{
ifstream filmike("andmebaas.txt");
int n, sum = 5;
while (filmike >> n) {
sum += n;
string film;
string vaadatud;
int aasta;
long int hinne;
system ("CLS");
cout << "Kogu filmide andmebaas"<<endl;
cout << "Film" << " " << "Aasta" << " " <<"Hinne"<< " " << "Vaadatud" << endl;
cout << "------------------------------" << endl;
while (filmike>> film >> aasta >> hinne >> vaadatud)
{
cout << film << " " << aasta << " " << hinne << " " << vaadatud << endl;
}
system ("pause");
cin.get();
main();
}
}
void viismaha()
{
ifstream filmike("andmebaas.txt");
int n, sum = -5;
while (filmike >> n) {
sum += n;
}
string film;
string vaadatud;
int aasta;
long int hinne;
system ("CLS");
cout << "Kogu filmide andmebaas"<<endl;
cout << "Film" << " " << "Aasta" << " " <<"Hinne"<< " " << "Vaadatud" << endl;
cout << "------------------------------" << endl;
while (filmike>> film >> aasta >> hinne >> vaadatud)
{
cout << film << " " << aasta << " " << hinne << " " << vaadatud << endl;
}
system ("pause");
cin.get();
main();
}
void sisend() /* user input */
{
string nimi;
int aasta;
long int hinne;
string vaadatud;
ofstream lisafilm("andmebaas.txt", ios::app);
cout <<"Sisestage filmi nimi." << endl; /*Enter film's name */
cin >> nimi;
string film;
cout << "Sisestage filmi ilmumisaasta." << endl; /* Enter film's year */
cin >> aasta;
cout << "Sisestage filmi hinne." << endl; /* Enter film's rating */
cin >> hinne;
cout << "Kas olete filmi juba vaadanud?" << endl; /* Has the user seen the movie already*/
cout << "Vastake 'Jah' voi 'Ei'" << endl;
cin >> vaadatud;
cout << film << " " << aasta << " " << hinne << " " << vaadatud << endl;
lisafilm<< nimi << " " << aasta << " " << hinne<< " " << vaadatud << endl;
lisafilm.close();
main();
cout << "Aitah kasutamast andmebaasi." << endl;
system("pause");
cin.get ();
}
void valjumine() /*quiting without output */
{
system("CLS");
cout << "Aitah kasutamast andmebaasi." << endl;
system("pause");
cin.get ();
}
void kogukuvand() /* the whole movie database*/
{
ifstream filmike("andmebaas.txt");
string film;
string vaadatud;
int aasta;
long int hinne;
system ("CLS");
cout << "Kogu filmide andmebaas"<<endl;
cout << "Film" << " " << "Aasta" << " " <<"Hinne"<< " " << "Vaadatud" << endl;
cout << "------------------------------" << endl;
while (filmike>> film >> aasta >> hinne >> vaadatud)
{
cout << film << " " << aasta << " " << hinne << " " << vaadatud << endl;
}
system ("pause");
cin.get();
main();
}
void sisendvoivaljumine()
{
int valik2;
system ("CLS");
cout << "Vajuta klahv 'j',kui tahad salvestada kirje ja v2ljuda programmist." << endl; /* output new movie to file and quit*/
cout << "Vajuta klahv 'e',kui ei taha salvestada kirje ja v2ljuda programmist." << endl; /*just quit, without any output to file*/
cout << "Vajuta klahv 'k',kui tahad naha kogu filmide andmebaasi." << endl; /* display the whole movie database*/
cin >> valik2;
switch (valik2)
{
case 1:
sisendvoivaljumine();
break;
sisend();
break;
case 2:
valjumine();
break;
case 3:
kogukuvand();
break;
}
}
Some hints:
Indent and format your code according to common convention. It makes it easer for you to read and debug (and everyone else too).
You are calling main() recursively. Do not do that. Use a loop around you menu switch instead.
A good failsafe way of reading lines from files is by using getline(). Combine with an istringstream to read individual values from the line:
ifstream infile("somefile.txt");
string line;
while ( getline(infile, line) ) // read infile until eof
{
istringstream iss(line); // create stream from line data
string a, b, c, d;
iss >> a >> b >> c >> d; // read just as from cin
cout << a << "," << b << "," << c << "," << d << endl;
}
If you read to integers you need to verify that the read succeeded (unless you are sure the file contained digits at the point you where reading):
int n;
if (iss >> n)
{
// read OK
}
else
{
// read failed
infile.clear();
string junk;
infile >> junk;
cout << "ERROR: bad data was:" << junk << endl;
}
To use characters in menu you can use char datatype. It's a good idea, since char input won't fail:
char choice;
cin >> choice;
switch (choice)
{
case '1':
{
// do something
break;
}
case 'A':
{
// do something
break;
}
}
Beware that sisendvoivaljumine calls itself recursively when you select that option. As menus can be selected over and over again, infinitely, you are better off by using a loop to repeat the menu.
You want to read up on the above topics. Check http://www.cplusplus.com.
When you debug, make sure you know exactly which lines the program is executing at each point. Add clear debug output to help you.

Why won't my ofstream work when I put it outside my while statement?

Every time I do anything, and my while(1) gets called in my main function, my file gets cleared. It's driving me crazy. I've tried EVERYTHING. I try to put my ofstream out("data.dat"); outside the while(1) statement so it isn't called everytime but then nothing is written to the file like the ofstream isn't even working!
I've tried to make the ofstream static, so it isn't called over and over again like:
static ofstream open("data.dat");
That doesn't work.
And like I said, when I put the ofstream OUTSIDE the while statement, nothing is written to the file. Like:
ofstream out("data.dat");
while (1)
{
string line = "";
cout << "There are currently " << structList.size() << " items in memory.";
cout << endl << endl;
cout << "Commands: " << endl;
cout << "1: Add a new record " << endl;
cout << "2: Display a record " << endl;
cout << "3: Edit a current record " << endl;
cout << "4: Delete a record " << endl;
cout << "5: Save current information " << endl;
cout << "6: Exit the program " << endl;
cout << endl;
cout << "Enter a command 1-6: ";
getline(cin , line);
int rValue = atoi(line.c_str());
system("cls");
switch (rValue)
{
case 1:
structList = addItem(structList);
break;
case 2:
displayRecord(structList);
break;
case 3:
structList = editRecord(structList);
break;
case 4:
deleteRecord(structList);
break;
case 5:
if (!structList.size()) { cout << "There are no items to save! Enter one first!" << endl << endl; system("pause"); system("cls"); break; }
writeVector(out , structList);
break;
case 6:
return 0;
default:
cout << "Command invalid. You can only enter a command number 1 - 6. Try again. " << endl;
}
out.close();
}
And can someone tell me why my check to prevent reading of a empty file won't work?
My Check:
bool checkFileEmpty()
{
ifstream in("data.dat");
if (in.peek() == in.eofbit)
{
return true;
}
return false;
}
I am so sick and tired of my program crashing on startup over and over again because my vector is getting set to a size of 200 million. I've tried a BUNCH of stuff for this... none of it works... Please GOD someone help me with both of these! I've been up for 18 hours working on this ( all night yes ) and i'm ALMOST done. I'm begging you....
My Code:
#include "stdafx.h"
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
using namespace System;
using namespace std;
#pragma hdrstop
bool isValidChoice(int size, int choice);
bool checkFileEmpty();
template<typename T>
void writeVector(ofstream &out, const vector<T> &vec);
template<typename T>
vector<T> readVector(ifstream &in);
template<typename T>
vector<T> addItem(vector<T> &vec);
template<typename T>
void printItemDescriptions(vector<T> &vec);
template<typename T>
int displayRecord(vector<T> &vec);
template<typename T>
vector<T> editRecord(vector<T> &vec);
template<typename T>
vector<T> deleteRecord(vector<T> &vec);
struct InventoryItem {
string Description;
int Quantity;
int wholesaleCost;
int retailCost;
string dateAdded;
} ;
int main(void)
{
cout << "Welcome to the Inventory Manager extreme! [Version 1.0]" << endl;
ifstream in("data.dat");
if (in.is_open()) { cout << "File \'data.dat\' has been opened successfully." << endl; } else { cout << "Error opening data.dat" << endl;}
cout << "Loading data..." << endl;
vector<InventoryItem> structList = readVector<InventoryItem>( in );
cout <<"Load complete." << endl << endl;
in.close();
while (1)
{
string line = "";
cout << "There are currently " << structList.size() << " items in memory.";
cout << endl << endl;
cout << "Commands: " << endl;
cout << "1: Add a new record " << endl;
cout << "2: Display a record " << endl;
cout << "3: Edit a current record " << endl;
cout << "4: Delete a record " << endl;
cout << "5: Save current information " << endl;
cout << "6: Exit the program " << endl;
cout << endl;
cout << "Enter a command 1-6: ";
getline(cin , line);
int rValue = atoi(line.c_str());
system("cls");
ofstream out("data.dat");
switch (rValue)
{
case 1:
structList = addItem(structList);
break;
case 2:
displayRecord(structList);
break;
case 3:
structList = editRecord(structList);
break;
case 4:
deleteRecord(structList);
break;
case 5:
if (!structList.size()) { cout << "There are no items to save! Enter one first!" << endl << endl; system("pause"); system("cls"); break; }
writeVector(out , structList);
break;
case 6:
return 0;
default:
cout << "Command invalid. You can only enter a command number 1 - 6. Try again. " << endl;
}
out.close();
}
system("pause");
return 0;
}
template<typename T>
void writeVector(ofstream &out, const vector<T> &vec)
{
out << vec.size();
for(vector<T>::const_iterator i = vec.begin(); i != vec.end(); i++)
{
out << *i;
}
cout << "Save completed!" << endl << endl;
}
ostream &operator<<(ostream &out, const InventoryItem &i)
{
out << i.Description << ' ';
out << i.Quantity << ' ';
out << i.wholesaleCost << ' ' << i.retailCost << ' ';
out << i.dateAdded << ' ';
return out;
}
istream &operator>>(istream &in, InventoryItem &i)
{
in >> i.Description;
in >> i.Quantity;
in >> i.wholesaleCost >> i.retailCost;
in >> i.dateAdded;
return in;
}
template<typename T>
vector<T> readVector(ifstream &in)
{
size_t size;
if (checkFileEmpty())
{
size = 0;
} else {
in >> size;
}
vector<T> vec;
vec.reserve(size);
for(unsigned int i = 0; i < size; i++)
{
T tmp;
in >> tmp;
vec.push_back(tmp);
}
return vec;
}
template<typename T>
vector<T> addItem(vector<T> &vec)
{
system("cls");
string word;
unsigned int number;
InventoryItem newItem;
cout << "-Add a new item-" << endl << endl;
cout << "Enter the description for the item: ";
getline (cin , word);
newItem.Description = word;
cout << endl;
cout << "Enter the quantity on hand for the item: ";
getline (cin , word);
number = atoi(word.c_str());
newItem.Quantity = number;
cout << endl;
cout << "Enter the Retail Cost for the item: ";
getline (cin , word);
number = atoi(word.c_str());
newItem.retailCost = number;
cout << endl;
cout << "Enter the Wholesale Cost for the item: ";
getline (cin , word);
number = atoi(word.c_str());
newItem.wholesaleCost = number;
cout << endl;
cout << "Enter current date: ";
getline (cin , word);
newItem.dateAdded = word;
vec.push_back(newItem);
return vec;
}
template<typename T>
void printItemDescriptions(vector<T> &vec)
{
int size = vec.size();
if (size)
{
cout << "---------------------------------" << endl;
cout << "| ~ Item Descriptions ~ |" << endl;
cout << "---------------------------------" << endl;
cout << "*********************************" << endl;
for (int i = 0 ; i < size ; i++)
{
cout << "(" << i+1 << ")" << ": " << vec[i].Description << endl;
}
cout << "*********************************" << endl << endl;
}
}
template<typename T>
int displayRecord(vector<T> &vec)
{
string word = "";
string quit = "quit";
int choice = 1;
int size = vec.size();
if (size)
{
printItemDescriptions(vec);
cout << endl;
while (1)
{
cout << "Type \"exit\" to return to the Main Menu." << endl << endl;
cout << "Enter \"list\" to re-display the items." << endl << endl;
cout << endl;
cout << "Pick the number of the item you would like to display: ";
getline (cin , word);
if (convertToLower(word) == "exit") { system("cls"); return 0; }
if (convertToLower(word) == "list") { system("cls"); displayRecord(vec); }
choice = atoi(word.c_str());
choice -= 1;
if (isValidChoice(size, choice))
{
system("cls");
cout << endl << "[Item (" << choice << ") details] " << endl << endl;
cout << "******************" << endl;
cout << "* Description * " << vec[choice].Description << endl;
cout << "******************" << endl << endl;
cout << "******************" << endl;
cout << "*Quantity On Hand* " << vec[choice].Quantity << endl;
cout << "******************" << endl << endl;
cout << "******************" << endl;
cout << "* Wholesale Cost * " << vec[choice].wholesaleCost << endl;
cout << "****************** " << endl << endl;
cout << "******************" << endl;
cout << "* Retail Cost * " << vec[choice].retailCost << endl;
cout << "****************** " << endl << endl;
cout << "******************" << endl;
cout << "* Data Added * " << vec[choice].dateAdded << endl;
cout << "****************** " << endl << endl;
} else { system("cls"); cout << "That item doesn't exist!" << endl; cout << "Pick another item or enter \"list\" to see available items." << endl << endl; }
}
} else { cout << "There are currently no items to display." << endl << endl; system("pause"); system("cls"); return 0; }
return 1;
}
bool isValidChoice(int size, int choice)
{
for (int i = 0 ; i <= size ; i++)
{
if (choice == i) { return true; }
}
return false;
}
string convertToLower(string word)
{
for (unsigned int i = 0 ; i < word.size() ; i++)
{
word[i] = tolower(word[i]);
}
return word;
}
bool checkFileEmpty()
{
ifstream in("data.dat");
if (in.peek() == in.eofbit)
{
return true;
}
return false;
}
template<typename T>
vector<T> editRecord(vector<T> &vec)
{
string word;
int choice;
printItemDescriptions(vec);
cout << "Choose item to edit: ";
getline ( cin, word );
choice = atoi(word.c_str());
system("cls");
unsigned int number;
InventoryItem newItem;
cout << "-Edit an item-" << endl << endl;
cout << "Enter the description for the item: ";
getline (cin , word);
vec[choice-1].Description = word;
cout << endl;
cout << "Enter the quantity on hand for the item: ";
getline (cin , word);
number = atoi(word.c_str());
vec[choice-1].Quantity = number;
cout << endl;
cout << "Enter the Retail Cost for the item: ";
getline (cin , word);
number = atoi(word.c_str());
vec[choice-1].retailCost = number;
cout << endl;
cout << "Enter the Wholesale Cost for the item: ";
getline (cin , word);
number = atoi(word.c_str());
vec[choice-1].wholesaleCost = number;
cout << endl;
cout << "Enter current date: ";
getline (cin , word);
vec[choice-1].dateAdded = word;
system("cls");
cout << "Item edited successfully! " << endl;
return vec;
}
template<typename T>
vector<T> deleteRecord(vector<T> &vec)
{
if (!vec.size()) { cout << "There are no items to delete!" << endl << endl; return vec; }
printItemDescriptions(vec);
string word;
int choice;
cout << "Choose item to delete: ";
getline( cin, word);
choice = atoi(word.c_str());
vec.erase (vec.begin()+choice-1);
return vec;
}
You'd better move the ofstream openning and closing inside case 5.
Here you create a new file at each while iteration.
case 5:
{
ofstream out("data.dat");
writeVector(out , structList);
out.close();
}
break;
ofstream out("data.dat");
Opens the file for writing. By default, it will start at the very beginning wiping out anything that was there previously. First, use a different output file than the file you are reading from.
Try adding the close to the case 6 statements:
case 6:
out.close();
return 0;
I'm pretty sure the close isn't getting called as the return will exit main before getting to that statement. With the file unclosed you are left with a buffer unflushed and I suspect that will leave the data unwritten.
You should move the open to before the while loop and also remove the out.close() from the while loop as it's going to close the file after the first menu selection.
To check if a file is empty or cannot be opened
bool IsEmpty( const std::string & filename ) {
std::ifstream ifs( filename.c_str() );
if ( ifs.is_open() ) {
std::string line;
return ! std::getline( ifs, line );
}
else {
return true;
}
}