Not looping Correctly - c++

The purpose of this code it to be a basic Library check-in check-out system, I use a scanner to input a barcode which is the ISBN number then the program looks at my .txt database and searches for the book name. Then it asks you if you would like to check out the book and asks for student ID number and then outputs ISBN, out/in, id number and current time to a FILE. The program works great the first time but then if you try to check out another book after inputting the barcode it will stop working. It wont take input cant move on just stops.
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <iomanip>
#include <fstream>
#include <string>
#include <ctime>
using namespace std;
int main()
{
char variable = 1;
ifstream infile;
ofstream outfile;
infile.open("Library_Database.txt");
outfile.open("Library_Checkout.txt", ios::app);
do {
char variable;
cout << "SETSUCON MANGA LIBRARY DATABASE\n\n" << setw(45) << "For Check-Out please enter: O or o\n" << setw(45) << "For Check-In please enter: I or i\n" << setw(45) << "For Assistance please enter: H or h\n" << setw(45) << "To close this program please enter: Q or q\n" << setw(50) << "Enter an option: ";
cin >> variable;
cout << "\n";
if (variable == 'O' || variable == 'o'){
double search;
double ISBN = 0;
string bookName;
cout << "Please Scan Barcode: ";
cin >> search; //runs fine one time then gets stuck here after I input the ISBN number the second time
while (ISBN != search){
infile >> ISBN >> bookName;
}
cout << "You would like to check out: " << bookName << "?" << endl;
string idNumber;
char yesOrNo;
cout << "Yes or No (Y or N): ";
cin >> yesOrNo;
if (yesOrNo == 'Y' || yesOrNo == 'y'){
cout << "Please input Student ID number or Badge ID Number: ";
cin >> idNumber;
cout << endl;
time_t now = time(0);
char* dt = ctime(&now);
outfile.setf(ios::fixed);
outfile.precision(0);
outfile << search << std::resetiosflags(std::ios::showbase) << setw(12) << idNumber << setw(4) << "out" << setw(30) << dt << endl;
}
else{
cout << endl << "\n";
continue;
}
}
else if (variable == 'I' || variable == 'i'){
double search;
double ISBN = 0;
string bookName;
cout << "Please Scan Barcode: ";
cin >> search; //runs fine one time then gets stuck here after I input the ISBN number the second time
while (ISBN != search){
infile >> ISBN >> bookName;
}
cout << "You would like to check in: " << bookName << "?" << endl;
string idNumber;
char yesOrNo;
cout << "Yes or No (Y or N): ";
cin >> yesOrNo;
if (yesOrNo == 'Y' || yesOrNo == 'y'){
cout << "Please input Student ID number or Badge ID Number: ";
cin >> idNumber;
cout << endl;
time_t now = time(0);
char* dt = ctime(&now);
outfile.setf(ios::fixed);
outfile.precision(0);
outfile << search << std::resetiosflags(std::ios::showbase) << setw(12) << idNumber << setw(4) << "in" << setw(30) << dt << endl;
}
else{
cout << endl << "\n";
continue;
}
}
else if (variable == 'H' || variable == 'h'){
cout << "This program was written Shea Transue.\n" << "For Assistance Please Contact Shea Transue at 484-264-5863\n\n";
}
else if (variable == 'Q' || variable == 'q') {
cout << "Thank you for using the SETSUCON LIBRARY DATABASE.\n" << "For assistance please Call or Text Shea Transue at 484-264-5864\n\n";
break;
}
else {
cout << variable << " is not a valid option. Try again\n\n";
}
} while (variable != 'Q' || variable != 'q');
infile.close();
outfile.close();
return 0;
}

You open the library database infile and scan through it with the >> operator, but you never seek back to the beginning with infile.seekg( 0, std::ios::beg ).
When any book isn't found, the while loop never terminates. Since you only start scanning the database from somewhere in the middle, any book after the first may not be found.
Try this:
do {
cout << "Please Scan Barcode: ";
cin >> search; //runs fine one time then gets stuck here after I input the ISBN number the second time
infile.clear();
infile.seekg( 0, std::ios::beg );
while ( infile && ISBN != search){
infile >> ISBN >> bookName;
}
if ( ! infile ) {
std::cout << "The book was not found in the database.\n";
}
} while ( ! infile );
Also, try dividing ("factoring") the program into separate functions, and test each function separately.

Related

How to ignore .txt for cin for output file in C++?

This is my C++ code and I wish to create an output file. In order to create the output file, I request the user to include .txt at this input, cin >> accnum ; , hence, when output file is produced, it will show accnum.txt as plain text. My question is, what should I do in order to ignore .txt to be appeared in the text file, provided that I must input .txt(this is to produce txt file, without .txt at the input, no output file will be produced). I have put a comment line, kindly refer to that line. Thanks for your help!
#include <iostream>
#include <fstream>
#include <string>
#include <iomanip>
using namespace std;
int main ()
{
double withdraw,deposit,number,transfer,num,amt;
string name,first_name,middle_name,last_name;
int x=0;
int option;
int A = 300;
int B = 500;
int C,W,y;
string accnum;
ifstream infile;
ofstream outfile;
do {
cout <<" Welcome to ATM Machine "<<endl;
cout <<"\n\t****Menu****";
cout <<"\n\t* 1.Creating a new account *";
cout <<"\n\t* 2.Cash Deposit *";
cout <<"\n\t* 3.Cash withdrawal *";
cout <<"\n\t* 4.Fund transfer between two account *";
cout <<"\n\t* 5.Exit *";
cout <<"\n\t* *";
cout <<"\n\t********";
cout <<"\n\t Please choose an option: ";
cin>>option;
switch(option){
case 1:
cout <<"Press 1 to Confirm" << endl << "Press 0 to exit " << endl ;
cin >> C ;
{
if( C == 1 )
{
cout << "Enter first name: " << endl;
cin >> first_name;
cout << "Enter middle name: " << endl;
cin >> middle_name;
cout << "Enter last name: " << endl;
cin >> last_name;
name = first_name + " " + middle_name + " " + last_name;
cout << "enter a 4 digit number : " << endl << "gentle reminder : please add .txt at the end of your number" << endl << "e.g 1234.txt" << endl;
cin >> accnum ; //how to ignore .txt
cout << "What is your primary balance: " << endl;
cin >> amt;
infile.open(name);
outfile.open(name);
cout << "your account has been created " << endl ;
outfile << "name" << name << endl;
outfile << "account no. : " << accnum << endl ;
outfile << "current balance : RM" << amt << endl ;
}else {
cout << "Bye, have a nice day";
}
infile.close();
outfile.close();
}
break;
case 2:
cout<<"Deposit amount: "<<endl;
cin>>deposit;
if(deposit<10) {
cout<<"The smallest note acceptable is RM10."<<endl;
}else {
x=static_cast<int>(deposit)%10;
if(x!=0)
{
cout<<"Invalid deposit amount"<<endl;
cout<<"Example of deposit amount: RM10, RM20, RM50, RM320..."<<endl;
}else {
A+=deposit;
cout<<"current balance: RM"<< A <<endl;
}
}
break;
case 3:
cout<<"Amount you want to withdraw"<<endl;
cin>>withdraw;
if(A < withdraw || withdraw < 10) { // A is balance
cout <<"Failed to withdraw money! Please try again."<<endl;
}else {
A-=withdraw;
cout <<"current balance: "<< A <<endl;
}
break;
case 4:
infile.open("1212.txt");
infile >> x;
cout<<"Enter Details of transfering Account(Account A)"<<endl;
cout<< "Your account number is:"<<endl;
cin>>W;
cout<< "What is your name:"<<endl;
cin.ignore();
getline(cin,name);
cout<<"Enter Details of receiving Account(Account B)"<<endl;
cout<<"Enter account number:"<<endl;
cin>>W;
cout<<"Enter name:"<<endl;
cin.ignore();
getline(cin, name);
cout <<"your account balance is : " << x << endl << "how much do you want to transfer ? ";
cin >> num ;
outfile.open("1212.txt");
outfile << x - num ;
cout << "your account balance is : " << x - num ;
infile.close();
outfile.close();
infile.open("2121.txt");
infile >> y ;
outfile.open("2121.txt") ;
outfile << y + num ;
infile.close();
outfile.close();
break;
case 5:
cout<<"Thank you for using ATM machine. Bye, have a nice day !"<<endl;
return 0;
default:
if(option != 5) cout<<"Invalid option.Please try again!"<<endl;
break;
}
}while(option != 5);
system("pause");
return 0;
}
Just create the file without a format, the name will be the file_name content exactly, be aware that in windows has reserved names such as CON.
#include <iostream>
#include <fstream>
#include <string>
int main (void) {
std::string file_name = "1234";
std::fstream f_handle;
f_handle.open(file_name, std::fstream::out);
if (f_handle.is_open()){
f_handle << "Some text" << std::endl;
f_handle.close();
}
f_handle.open(file_name, std::fstream::in);
if (f_handle.is_open()){
std::cout << f_handle.rdbuf() << std::endl;
f_handle.close();
}
return 0;
}
You asked about how to remove the .txt part from accnum and here's one way to do that:
cin >> accnum ; //how to ignore .txt
// check that the length/size of the entered accnum is at least 4 characters
// and
// that the last 4 characters is ".txt"
if(accnum.size() >= 4 && accnum.substr(accnum.size() - 4) == ".txt") {
// extract a substring from accnum without the last 4 characters
accnum = accnum.substr(0, accnum.size() - 4);
}
However, I have my doubts about the requirement that the user should actually add .txt to the account number, because seeing this at an ATM would be really confusing:
enter a 4 digit number :
gentle reminder : please add .txt at the end of your number"
e.g 1234.txt
It's especially confusing since the only thing you want to do with .txt is to remove it. I would consider changing this user interface.
Suggestions:
Let the user add the account number without .txt
Instead of saving the account information in a file with the account holders name as the filename, save it in a file named accnum + ".txt". This makes it possible for a person to have more than one account - just as in real life.

C++ loop error that my professor can't figure out

I am currently taking a C++ programming class and am working on a project in which I have to create a fairly simple movie database. My code essentially works as intended yet in certain cases it causes the main menu to loop infinitely and I cannot figure out why. I brought this to my teacher and he cannot explain it either. He gave me a workaround but I would like to know if anyone can see the cause of the problem. Full code is as follows:
#include <cstdlib>
#include <iostream>
#include <vector>
#include <string>
using namespace std;
struct MovieType
{
string title;
string director;
int year;
int length;
string rating;
};
MovieType addMovie() {
MovieType newMovie;
cout << "Movie title :";
getline(cin, newMovie.title);
cout << "Director :";
getline(cin, newMovie.director);
cout << "Year :";
cin >> newMovie.year;
cout << "Length(in minutes) :";
cin >> newMovie.length;
cout << "Rating :";
cin >> newMovie.rating;
cout << endl;
return newMovie;
}
void listMovie(MovieType movie) {
cout << "______________________________________" << endl;
cout << "Title : " << movie.title << endl;
cout << "Director : " << movie.director << endl;
cout << "Released : " << movie.year << endl;
cout << "MPAA Rating : " << movie.rating << endl;
cout << "Running time : " << movie.length << " minutes" << endl;
cout << "______________________________________" << endl;
}
void search(vector<MovieType> movieVector) {
string strSearch;
cout << endl << "Search title: ";
getline(cin, strSearch);
for (int c = 0; c < movieVector.size(); c++) {
if (movieVector.at(c).title == strSearch)
listMovie(movieVector.at(c));
}
}
int main() {
bool quit = 0;
vector<MovieType> movieVector;
while (quit == 0) {
char selection = 'f';
cout << "Main Menu:" << endl;
cout << "'a' - Add movie" << endl;
cout << "'l' - List movies" << endl;
cout << "'s' - Search by movie title" << endl;
cout << "'q' - Quit" << endl;
cout << "Please enter one of the listed commands:";
cin >> selection;
cin.ignore();
cout << endl;
if (selection == 'a')
movieVector.push_back(addMovie());
else if (selection == 'l') {
for (int c = 0; c < movieVector.size(); c++) {
listMovie(movieVector.at(c));
}
}
else if (selection == 's') {
search(movieVector);
}
else if (selection == 'q')
quit = 1;
}
return 0;
}
When an unexpected input type is entered during the addMovie function(like entering text for the int type year), it just runs through the function then loops through the menu infinitely. It appears to me that the code just stops even looking at the input stream. I have tried using cin.ignore() in many different places but it doesn't matter if there is nothing left in the stream it just keeps going.
I am using NetBeans to compile my code.
I really have no idea why it behaves like this otherwise I would offer more information but I am just curious as to why this happens, because as I said before, my professor doesn't even know why this is happening.
Any help or insight is greatly appreciated.
cin enters an error state where cin.fail() is true. In this state it just ignores all input operations. One fix is to clear the error state, but better, only use getline operations on cin, not formatted input.
E.g., instead of
cin >> newMovie.year;
… do
newMovie.year = stoi( line_from( cin ) );
… where line_from can be defined as
auto line_from( std::istream& stream )
-> std::string
{
std::string result;
if( not getline( stream, result ) )
{
// Throw an exception or call exit(EXIT_FAILURE).0
}
return result;
}
Disclaimer: code untouched by compiler.

Fahrenheit to Celsius converter. Verify int not char

Created a program to convert Fahrenheit to Celsius. Having trouble verifying if what the user input is an int. The problem I believe is the "if (!cin)" line.
#include <iomanip>
#include <iostream>
using namespace std;
int main()
{
float f, c;
string choice;
do{
cout << "Enter a Fahrenheit temperature to convert to Celsius:" << endl;
cin >> f ;
if ( !cin ) {
cout << "That is not a number..." << endl;
}
else if (f < -459.67) {
cout << "That is not a Fahrenheit temperature..." << endl;
}
if ( f >= -459.67) {
c = (( f - 32) * 5.0)/9.0 ;
cout << fixed ;
cout << setprecision(2) << "Celsius temperature is: " << showpos << c << endl;
}
cout << "Would you like to convert another? If so, enter Yes" << endl;
cin >> choice ;
}while ( choice == "Yes" || choice == "yes" );
return 0;
}
I'm not sure of what you mean about your "Continue yes or no statement", So I've written a code that asks the user to type yes to confirm the conversion, otherwise no to enter a new Fahrenheit value. After the conversion, The program also asks the user to type yes if he/she wants another conversion, If the user types anything except "yes", The program will close.
#include <iostream>
#include <iomanip>
#include <string>
using namespace std;
int main()
{
bool Continue = true;
while (Continue == true)
{
double f, c;
cout << endl << "Enter a Fahrenheit temperature to convert to Celsius:" << endl << endl;
while (!(cin >> f))
{
cout << endl << "Invalid Input. " << endl << endl;
cin.clear();
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
while (f <= -459.67)
{
cout << "Invalid Input. " << endl;
cin.clear();
cin.ignore();
cin >> f;
}
cout << endl << "Continue? Type yes to proceed conversion, Otherwise type no." << endl << endl;
string confirmation;
cin >> confirmation;
while (confirmation != "yes" && confirmation != "no")
{
cout << endl << "Input not recognized. try again." << endl << endl;
cin >> confirmation;
}
if (confirmation == "yes")
{
c = ((f - 32) * 5.0) / 9.0;
cout << fixed;
cout << endl << setprecision(2) << "Celsius temperature is: " << showpos << c << endl;
cout << endl << "Another convertion? type yes to confirm. " << endl << endl;
string cont;
cin >> cont;
if (cont != "yes")
{
Continue = false;
}
}
}
return 0;
}
You should use while loop, So the program won't stop asking until the user enters the correct data. Use cin.clear(); to clear invalid data that the user inputted. And cin.ignore(); to ignore any succeeding erroneous data. For example, '25tg', 'tg' character is ignored since it's not valid. '25' will be accepted.
Edits in my answer and code provided are very welcome.
you can use a function to check if the input is numeric or not....
should be something like this:
bool isFloat( string myString ) {
std::istringstream iss(myString);
float f;
iss >> noskipws >> f; // noskipws considers leading whitespace invalid
// Check the entire string was consumed and if either failbit or badbit is set
return iss.eof() && !iss.fail();
}

Won't let me read in user input in after IF statement (homework)

I am having some issues with my simple code of creating a dvd & software list to import into a csv file.
I have the output working fine but for some reason my program is skipping my first part of the code. If I take out the IF statement, that bit of code works so I am not understanding why.
my output looks like this:
Would you like to add new media? Enter M for Movie or S for software: m
Enter the name of the Movie (20 Chararters or less)Name: Enter a rating for
your movie 1-5:
I am not getting any errors in my compiler (Visual Studio 2013) and it does not allow me to input a name and skips right to rating.
Any explanations or suggestions would be appreciated as I want to fix this before I move on to adding more.
here is my code:
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main(){
string typeM = "movie";
string typeS = "software";
char answer, mediainput;
int rating = 0;
string dir, type;
string moviename,softname;
do
{
cout << "Would you like to add new media? Enter M for Movie or S for software: ";
cin >> mediainput;
cout << endl;
if (mediainput == 'm' || mediainput == 'M')
{
cout << "Enter the name of the Movie (20 Chararters or less) \n Name: ";
getline(cin, moviename);
cout << endl;
cout << "Enter a rating for your movie " << moviename << " 1-5 ";
cin >> rating;
if (rating < 1 || rating > 5)
{
cout << "You must enter a number from 1 to 5. Enter a number rating: ";
cin >> rating;
cout << endl;
}
ofstream outdata("DVD_Software_inventory.csv", ios_base::app);
outdata << moviename << "," << typeM << "," << rating << "," << endl;
outdata.close();
}
if (mediainput == 's' || mediainput == 'S')
{
cout << "Enter the name of the software (20 Chararters or less) \n Software name: " << endl;
getline(cin, softname);
cout << "Enter the directory it is in \n Directory: ";
cin >> dir;
ofstream outdata("DVD_Software_inventory.csv", ios_base::app);
outdata << softname << "," << typeS << ",," << dir << "," << endl;
outdata.close();
}
cout << "\n\nWould you like to add more? Y/N ";
cin >> answer;
cout << endl;
if (answer == 'N' || answer == 'n')
{
cout << "** End of Program **" << endl;
break;
}
} while (answer == 'Y' || answer == 'y');
system("pause");
return(0);
}
The problem is that while your cin >> statement ignores "\n" (the newline character), the character is still in cin's buffer. getline(), however,
does not ignore the "\n" character.
The solution, therefore, is to explicitly tell cin to ignore the "\n" character:
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
getline(cin, moviename);
(credit to http://www.cplusplus.com/forum/beginner/24470/)

C++ Address Book Array and Textfile

Sorry for the lack of previous explanation to my school's assignment. Here's what I'm working with and what I have / think I have to do.
I have the basic structure for populating the address book inside an array, however, the logic behind populating a text file is a bit beyond my knowledge. I've researched a few examples, however, the implementation is a bit tricky due to my novice programming ability.
I've gone through some code that looks relevant in regard to my requirements:
ifstream input("addressbook.txt");
ofstream out("addressbook.txt");
For ifstream, I believe implementing this into the voidAddBook::AddEntry() would work, though I've tried it and the code failed to compile, for multiple reasons.
For ostream, I'm lost and unsure as to how I can implement this correctly. I understand basic file input and output into a text file, however, this method is a bit more advanced and hence why I'm resorting to stackoverflow's guidance.
#include <iostream>
#include <string.h> //Required to use string compare
using namespace std;
class AddBook{
public:
AddBook()
{
count=0;
}
void AddEntry();
void DispAll();
void DispEntry(int i); // Displays one entry
void SearchLast();
int Menu();
struct EntryStruct
{
char FirstName[15];
char LastName[15];
char Birthday[15];
char PhoneNum[15];
char Email[15];
};
EntryStruct entries[100];
int count;
};
void AddBook::AddEntry()
{
cout << "Enter First Name: ";
cin >> entries[count].FirstName;
cout << "Enter Last Name: ";
cin >> entries[count].LastName;
cout << "Enter Date of Birth: ";
cin >> entries[count].Birthday;
cout << "Enter Phone Number: ";
cin >> entries[count].PhoneNum;
cout << "Enter Email: ";
cin >> entries[count].Email;
++count;
}
void AddBook::DispEntry(int i)
{
cout << "First name : " << entries[i].FirstName << endl;
cout << "Last name : " << entries[i].LastName << endl;
cout << "Date of birth : " << entries[i].Birthday << endl;
cout << "Phone number : " << entries[i].PhoneNum << endl;
cout << "Email: " << entries[i].Email << endl;
}
void AddBook::DispAll()
{
cout << "Number of entries : " << count << endl;
for(int i = 0;i < count;++i)
DispEntry(i);
}
void AddBook::SearchLast()
{
char lastname[32];
cout << "Enter last name : ";
cin >> lastname;
for(int i = 0;i < count;++i)
{
if(strcmp(lastname, entries[i].LastName) == 0)
{
cout << "Found ";
DispEntry(i);
cout << endl;
}
}
}
AddBook AddressBook;
int Menu()
{
int num;
bool BoolQuit = false;
while(BoolQuit == false)
{
cout << "Address Book Menu" << endl;
cout << "(1) Add A New Contact" << endl;
cout << "(2) Search By Last Name" << endl;
cout << "(3) Show Complete List" << endl;
cout << "(4) Exit And Save" << endl;
cout << endl;
cout << "Please enter your selection (1-4) and press enter: ";
cin >> num;
cout << endl;
if (num == 1)
AddressBook.AddEntry();
else if (num == 2)
AddressBook.SearchLast();
else if (num == 3)
AddressBook.DispAll();
else if (num == 4)
BoolQuit = true;
else
cout << "Please enter a number (1-4) and press enter: " << endl;
cout << endl;
}
return 0;
}
int main (){
Menu();
return 0;
}
As it currently stands, I'm still stuck. Here's where I believe I should start:
cout << "Please enter your selection (1-4) and press enter: ";
cin >> num;
cout << endl;
if (num == 1)
AddressBook.AddEntry();
else if (num == 2)
AddressBook.SearchLast();
else if (num == 3)
AddressBook.DispAll();
else if (num == 4)
BoolQuit = true;
//save first name
//save last name
//save dob
//save phone number
//save email
//exit
else
cout << "Please enter a number (1-4) and press enter: " << endl;
cout << endl;
}
Somehow, during menu option 4 the array should dump the data into a .txt file and arrange it in a way that it can be easily imported upon reloading the program. I'm a little confused as to how I can store the array data from each character array into a .txt file.
Well first, if the input is coming from the file input, then instead of doing cin >> x you would have to do input >> x. If it's coming from standard input (the keyboard), then you can use cin.
Also, your else if statement should be something like this:
while (true)
{
// ...
else if (num == 4)
{
for (int i = 0; i < AddressBook.count; ++i)
{
AddBook::EntryStruct data = AddressBook.entries[i];
out << data.FirstName << " " << data.LastName
<< std::endl
<< data.Birthday << std::endl
<< data.PhoneNum << std::endl
<< data.Email;
}
}
break;
}