C++ Cash Register Program Not using <string> - c++

I have to write a program without using strings . Here is my code :
#include <iostream>
#include <iomanip>
using namespace std;
struct product
{
char productName[100];
double productPrice = 0;
};
const int MAX_CHAR = 101;
const int MAX_ITEM = 100;
int main()
{
product item[MAX_ITEM];
double total = 0;
int count = 0;
for (int i = 0; i < MAX_ITEM; i++)
{
cout << "Please , enter the product name(for checkout type -1) : ";
cin.get(item[i].productName, MAX_CHAR, '\n');
cin.ignore(100, '\n');
if (strcmp(item[i].productName, "-1") == 0 ) {
break;
}
else {
count++;
cout << "Please , enter the price for " << item[i].productName << " : $";
cin >> item[i].productPrice;
cin.ignore(100, '\n');
total += item[i].productPrice;
cout << endl << "Product entered : " << item[i].productName << " " << "$"
<< fixed << setprecision(2) <<item[i].productPrice << endl;
cout << "Total : $" << total << endl << endl;
}
}
cout << endl << "###############";
cout << endl << "Your Receipt : " << endl << endl;
for (int i = 0; i < count; i++) {
cout << item[i].productName << " $" << fixed << setprecision(2) << item[i].productPrice << endl;
}
cout << endl << "Total : $" << total;
cout << endl << "###############";
getchar();
getchar();
return 0;
}
I have a couple questions :
Why does the program crash if I don't use cin.ignore(100, '\n'); after cin >> item[i].productPrice; ? It's just cin without any condition, so it should not leave a new line char in input stream?
How can I check if the price doesn't contain incorrect input (so it has only decimal or floating point numbers) ?
How can I check if the name contains chars and numbers which are >0 (except -1) ?
Is it better to use cin.getline in this case ?

cin is an istream, so it should leave the newline char in the stream if you use cin.get(). I haven't tested if this is the cause of your crash but it sounds like this could give you problems.
chars are just numbers. A . is 46, the digit characters are from 48 through 57. You could read your price input into a buffer and check if you read any char that does not have one of your desired values. If you find an unwanted char, you can decide if you want to repeat the input, ignore this item or exit the program.
In your else branch, check if the first character of productName is a '-'. That way, you already ensured that productName is not -1.
cin.getline() discards the newline character, so you could avoid the use of cin.ignore().

Related

c++ why is there still input buffer left?

After my first entry, my second entery name field fills up with the input buffer from the previous entry. Why? I am even using the getline but the problem still persists. Please help me with the problem. This is question from Jumping Into C++ book .
#include <iostream>
#include <string>
using namespace std;
struct Person
{
string name;
string address;
long long int PhoneNumber;
};
void displayEntries(Person p[])
{
int enteryNumber;
cout << "Enter the entry number of the person for details(enter 0 to display all entries): ";
cin >> enteryNumber;
if(enteryNumber == 0)
{
for(int i = 0; i < 10; i++)
{
cout << "Entery Number: " << i + 1;
cout << "Name: " << p[i].name << endl;
cout << "Address: " << p[i].address << endl;
cout << "Phone Number: " << p[i].PhoneNumber << endl;
}
}
do
{
cout << "Entery Number: " << enteryNumber;
cout << "Name: " << p[enteryNumber].name << endl;
cout << "Address: " << p[enteryNumber].address << endl;
cout << "Phone Number: " << p[enteryNumber].PhoneNumber << endl;
} while (enteryNumber != 0);
}
int main()
{
Person p[10];
for(int i = 0; i < 10; i++)
{
cout << "Enter the details of the person\n\n";
cout << "Name: ";
getline(cin, p[i].name);
cout << "Address: ";
getline(cin, p[i].address);
cout << "Phone Number: ";
cin >> p[i].PhoneNumber;
cout << endl;
}
displayEntries(p);
return 0;
}
You can see what is happening when you read the reference for getline:
When used immediately after whitespace-delimited input, e.g. after
int n;
std::cin >> n;
getline(cin, n); //if used here
getline consumes the endline character left on the input stream by operator>>, and returns immediately. A common solution is to ignore all leftover characters on the line of input with
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
before switching to line-oriented input.
cin >> p[i].PhoneNumber; only gets the number. That leaves the line ending still in the input buffer to be read the next time you try to read a line.

I am trying to use a do while loop to repeat a certain portion of my program and it refuses to execute properly

Okay so as the title said its refusing to execute the stuff right under the "do" function even though as far as i can tell all the parameters for a repeat have been fulfilled. So far what i get when i run the program is something along the lines of...
"Would you like to search another name?
Please enter Y for yes and n for no:"
looping over and over when i press y
#include <iostream>
#include <string>
#include <iomanip>
#include <vector>
#include <algorithm>
#include <cstdlib>
using namespace std;
int main()
{
vector <string> vName, vID, vClass;
string sName, sID, sClass, sSearch, cQuestion;
int iSize, iStudent;
// Display initial vector size
iSize = vName.size();
cout << "Student list starts with the size:" << iSize << endl;
// Get size of list from user
cout << "How many students would you like to add?" << endl;
cin >> iStudent;
cin.ignore();
// Get names, ids, and classes
for (int i = 0; i < iStudent; i++)
{
cout << "Student" << i + 1 << ":\n";
cout << "Please enter the student name: ";
getline(cin, sName);
vName.push_back(sName);
cout << "Enter ID number ";
getline(cin, sID);
vID.push_back(sID);
cout << "Enter class name ";
getline(cin, sClass);
vClass.push_back(sClass);
}
// Display header
cout << "The list of students has the size of: " << iStudent << endl;
cout << "The Student List" << endl;
cout << "\n";
cout << "Name:" << setw(30) << "ID:" << setw(38) << "Enrolled Class : " << endl;
cout << "--------------------------------------------------------------------------";
cout << "\n";
// for loop for displying list
for (int x = 0; x < vName.size() && vID.size() && vClass.size(); x++)
{
cout << vName[x] << "\t \t \t" << vID[x] << "\t \t \t" << vClass[x] << endl;
}
// Sorting function
cout << "\n";
cout << "The Student List after Sorting:" << endl;
cout << "\n";
sort(vName.begin(), vName.end());
for (int y = 0; y < vName.size(); y++)
{
cout << vName[y] << endl;
}
cout << "\n";
// Search function
do
{
cout << "Please Enter a name to be searched:" << endl;
getline(cin, sSearch);
if (binary_search(vName.begin(), vName.end(), sSearch))
{
cout << sSearch << " was found." << endl << endl;
}
else
{
cout << sSearch << " was not found." << endl << endl;
}
cout << "Would you like to search another name?" << endl << endl;
cout << "Please enter Y for Yes and N for No:" << endl << endl;
cin >> cQuestion;
} while (cQuestion == "Y" || cQuestion == "y");
cout << "Thank you for using this program!" << endl;
return 0;
}
Edit:
Posted whole program, please excuse any grammatical mistakes, I'm just trying to get the program down before i go in there and make it pretty.
The tail of your loop does this:
cout << "Please enter Y for Yes and N for No:" << endl << endl;
cin >> cQuestion;
which will consume your string if you entered one, but leave the trailing newline in the input stream. Thus when you return to the top of the loop after entering Y or y, and do this:
cout << "Please Enter a name to be searched:" << endl;
getline(cin, sSearch);
the getline will extract an empty line.
How to consume the unread newline from the input stream is up to you. You will likely just end up using .ignore() as you did prior in your program. Or use getline to consume cQuestion. You have options. Pick one that works.
And as a side note, I would strongly advise you check your stream operations for success before assuming they "just worked". That is a hard, but necessary, habit to break. Something like this:
do
{
cout << "Please Enter a name to be searched:" << endl;
if (!getline(cin, sSearch))
break;
if (binary_search(vName.begin(), vName.end(), sSearch))
{
cout << sSearch << " was found." << endl << endl;
}
else
{
cout << sSearch << " was not found." << endl << endl;
}
cout << "Would you like to search another name?" << endl << endl;
cout << "Please enter Y for Yes and N for No:" << endl << endl;
} while (getline(cin,cQuestion) && (cQuestion == "Y" || cQuestion == "y"));
If cQuestion is a char array then you need to use strcmp or stricmp to compare it with another string i.e. "Y" and "y" in this case. If cQuestion is a single char then you need to compare with 'Y' and 'y' (i.e. with a single quote)
Strings in C++ are not first class types therefore they do not have some of the string operation that exist for other basic types like ints and floats. You do have std::string as part of the standard C++ library which almost fulfills the void.
If you just change the type of cQuestion to std::string your code should work but if you want to stick with chars then you will need to change the quote style.

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;
}

Check for non-numeric inputs in a C++ program

How do you check for non-numeric input using C++? I am using cin to read in a float value, and I want to check if non-numerical input is entered via stdin. I have tried to use scanf using the %d designator, but my output was corrupted. When using cin, I get the correct format, but when I enter, a string such as "dsffsw", I get an infinite loop.
The commented code was my attempt to capture the float, and type cast it as string, and check if it is a valid float, but the check always comes up false.
I have tried using other methods I have found on the message boards, but they want to use scanf in C and not cin in C++. How do you do this in C++? Or in C if it is not feasible.
while (!flag) {
cout << "Enter amount:" << endl;
cin >> amount;
cout << "BEGIN The amount you entered is: " << strtod(&end,&pend) << endl;
//if (!strtod(((const char *)&amount), NULL)) {
// cout << "This is not a float!" << endl;
// cout << "i = " << strtod(((const char *)&amount), NULL) << endl;
// //amount = 0.0;
//}
change = (int) ceil(amount * 100);
cout << "change = " << change << endl;
cout << "100s= " << change/100 << endl;
change %= 100;
cout << "25s= " << change/25 << endl;
change %= 25;
cout << "10s= " << change/10 << endl;
change %= 10;
cout << "5s= " << change/5 << endl;
change %= 5;
cout << "1s= " << change << endl;
cout << "END The amount you entered is: " << amount << endl;
}
return 0;
}
int amount;
cout << "Enter amount:" << endl;
while(!(cin >> amount)) {
string garbage;
cin.clear();
getline(cin,garbage);
cout << "Invalid amount. "
<< "Enter Numeric value for amount:" << endl;
}
I think you task relates to the so called defensive programming, one of it`s ideas is to prevent situations like one you described (function expects one type and user enters another).
I offer you to judge whether input is correct using method that returns stream state , which is good(),
so I think it will look something like this:
int amount = 0;
while (cin.good()) {
cout << "Enter amount:" << endl;
cin >> amount;

It skips the second getline() function?

I have been trying to figure out why it doesn't read my second getline() function. The first getline(cin, input) works fine for getting the input data for partition. I did the same for getting the job datas, and it doesn't work. No errors or anything. it just skips that line. Any help will be greatly appreciated. Thank you.
#include <iostream>
#include <string>
#include "memory.h"
#define show(a) std::cout << #a << ": " << (a) << std::endl
using std::cin;
using std::cout;
using std::endl;
int main(void)
{
//Variables
int MEM_SIZE = 0;
vector<int> partition_input;
vector<int> job_input;
while(true)
{
//INPUT PARTITION DATA
while(true)
{
char confirm;
string input;
int temp; //Temporary variable to store extracted data
int num_part = 0; //Iterator to check partition size and memory, and partition limits
int check_size = 0;
cout << "Please enter the memory size and partitions in the following format: \n";
cout << "1000 250 250 250 250 \n";
cout << "> ";
getline(cin, input); //The whole of user input is stored in variable "line"
istringstream os(input); //"line" is passed to stringstream to be ready to be distributed
while(os >> temp)
{
partition_input.push_back(temp);
check_size += partition_input[num_part];
num_part++;
}
//sets the first input to MEM_SIZE
//AND deletes it from the partition vector
MEM_SIZE = partition_input[0];
partition_input.erase(partition_input.begin(), partition_input.begin()+1);
check_size -= MEM_SIZE;
cout << "Memory size: " << MEM_SIZE << endl;
cout << "# of Partitions: " << partition_input.size() << endl;
cout << "Partition Sizes: ";
for(int i = 0; i < partition_input.size(); i++)
cout << partition_input[i] << ' ';
cout << endl;
cout << "Correct? (y/n) ";
cin >> confirm;
cout << endl << endl;
if(confirm == 'n')
continue;
//Checks the total partition size and the total memory size
if(!(MEM_SIZE >= check_size))
{
cout << "ERROR: Total partition size is less than total memory size." << endl;
system("pause");
continue;
}
//Check if it exceeded the max number of partition limit
if((num_part-1) >=5)
{
cout << "ERROR: You have entered more than the allowed partition(5). Please try again. \n";
system("pause");
continue;
}
break;
}
//START INPUT JOB DATA
do
{
string input2;
cout << "Please enter the size of each job in the following format." << endl;
cout << "300 100 200 400" << endl;
cout << "> ";
//*******************
//IT SKIPS THESE TWO LINES
getline(cin, input2);
istringstream oss(input2);
//*******************
int j;
while(oss >> j)
job_input.push_back(j);
for(int i = 0; i < job_input.size(); i++)
cout << job_input[i] << ' ';
break;
}while(false);
//END OF INPUT JOB DATA
break;
}
Memory A1(MEM_SIZE, partition_input.size(), partition_input, job_input.size(), job_input);
//A1.FirstFit();
// A1.BestFit();
// A1.NextFit();
// A1.WorstFit();
//system("pause");
return 1;
}
The problem is here:
cout << "Correct? (y/n) ";
cin >> confirm;
This reads the confirm character from the input. But not the '\n' character. Thus the next readline will read just that newline character.
It is best not to mix std::getline() and operator>> when reading from the input.
I would change the code to this:
cout << "Correct? (y/n) ";
std::string confirmLine;
std::getline(cin, confirmLine);
cout << endl << endl;
if(confirmLine == "n")
continue;