Stopping If statement from running entire code at once - c++

I'm creating a password system for an encryption program.
For this i moved my main chunk of code inside an if statement, however now, instead of reading the code line by line, it simply prints it all at once. (e.g. when it comes to std::cout << "Enter here: "; std::getline(std::cin, userin); the user cant input anything, it just prints the next line and keeps going.
int main(){
std::string userin;
std::string pass;
int attempts = 3;
std::cout << " ENCRYPTER" << std::endl;
std::cout << " " << std::endl;
while (attempts > 0){
std::cout << "Please Enter the Password" << std::endl;
if(attempts > 1){
std::cout << "You have " << attempts << " attempts remaining." << std::endl;
}
else {
std::cout << "You have " << attempts << " attempt remaining." << std::endl;
}
std::cin >> pass;
std::cout << " " << std::endl;
if(pass == "12345"){
std::cout << greetingFunc() << std::endl;
std::cout << " " << std::endl;
std::cout << "NOTE: Use only LETTERS. No numbers or grammar." << std::endl;
std::cout << " " << std::endl;
std::cout << "Please enter the message you wish to encrypt." << std::endl;
std::cout << "Enter here: "; std::getline(std::cin, userin);
std::cout << " " << std::endl;
std::cout << "Encrypted Message: " << encryptFunc(userin) << std::endl;
std::cout << " " << std::endl;
std::cout << "Highlight it and right click to copy." << std::endl;
system("pause");
} else {
std::cout << "Incorrect password. Please try again." << std::endl;
attempts--;
}
}
return 0;
}
Here is what is received in the console after the password is correctly entered.
Welcome to the Code Encrypter
NOTE: Use only LETTERS. No numbers or grammar.
Please enter the message you wish to encrypt.
Enter here:
Encrypted Message:
Highlight it and right click to copy.
Press any key to continue . . .
See how it just prints everything without running the functions or allowing the user to input their data.
How can i get it to read each line and stop to let the user input the info, and then proceed to call the encryption function? Thanks.

Just add std::getchar(); after std::cin >> pass
The problem is that when you enter pass and click enter, this enter keyboard will be considered as your next input. std::getchar(); receives the effect of enter keyboard. Now you can enter userin.
Note: Use std::getchar() only after you get a string by std::cin.
If you use std::getline(std::cin, pass); instead of std::cin >> pass;, you don't have to worry about the final '\n' because getline() doesn't let this character interrupt the next input.

Using stream operators with getline(cin, variable) is always a problem because some data remains in the input buffer. So you should remove everything still in there then read your input.
I.e.
while(getline(cin, userin))
if (userin != "")
break;
so this should works:
int main(){
std::string userin;
std::string pass;
int attempts = 3;
std::cout << " ENCRYPTER" << std::endl;
std::cout << " " << std::endl;
while (attempts > 0){
std::cout << "Please Enter the Password" << std::endl;
if(attempts > 1){
std::cout << "You have " << attempts << " attempts remaining." << std::endl;
}
else {
std::cout << "You have " << attempts << " attempt remaining." << std::endl;
}
std::cin >> pass;
std::cout << " " << std::endl;
if(pass == "12345"){
std::cout << greetingFunc() << std::endl;
std::cout << " " << std::endl;
std::cout << "NOTE: Use only LETTERS. No numbers or grammar." << std::endl;
std::cout << " " << std::endl;
std::cout << "Please enter the message you wish to encrypt." << std::endl;
std::cout << "Enter here: ";
while (std::getline(std::cin, userin))
if (userin != "")
break;
std::cout << " " << std::endl;
std::cout << "Encrypted Message: " << encryptFunc(userin) << std::endl;
std::cout << " " << std::endl;
std::cout << "Highlight it and right click to copy." << std::endl;
system("pause");
} else {
std::cout << "Incorrect password. Please try again." << std::endl;
attempts--;
}
}
return 0;
}

It looks like you're having issues with the input buffer. This is a very common issue when running command line/terminal programs.
When the cin >> pass is called, the stream buffer may have inputs remaining (namely the '\n' from pressing enter). You can do a few things, but the easiest thing is to call cin.get() after the cin >> pass.
You could also try creating a helper function or parsing the input using a while loop.

Related

How to exit from a stream reading loop, avoiding an additional empty loop?

When the program enters in the if and then break, empty cout-s are printed again.
void Person::ShowRecords()
{
std::ifstream data("Input.txt");
while (true)
{
if (!data.good())
{
break;
}
Person person;
data >> person;
std::cout << "First Name: " << person.getFirstName() << "\n";
std::cout << "Last Name: " << person.getLastName() << "\n";
std::cout << "Phone number: " << person.getNumber() << "\n";
std::cout << "EGN: " << person.getEGN() << "\n\n";
}
}
I really think that the most didactic way of tackling stream input is:
while (true) {
// Read
// Check (if fail then break)
// Use
}
Notice the pattern: infinite loop with Read/Check/Use. Check is where we can exit the loop. First you read, than you check if the reading operation was successful or failed, than you can use the data or exit based on that.
Adapting this to your case:
void Person::ShowRecords()
{
std::ifstream data("Input.txt");
while (true) {
// Read
Person person;
data >> person;
// Check
if (!data) {
break;
}
// Use
std::cout << "First Name: " << person.getFirstName() << "\n";
std::cout << "Last Name: " << person.getLastName() << "\n";
std::cout << "Phone number: " << person.getNumber() << "\n";
std::cout << "EGN: " << person.getEGN() << "\n\n";
}
}
The non didactic and probably more idiomatic way is:
void Person::ShowRecords()
{
std::ifstream data("Input.txt");
Person person;
while (data >> person) { // Read and, immediately after, Check
std::cout << "First Name: " << person.getFirstName() << "\n"; // Use
std::cout << "Last Name: " << person.getLastName() << "\n";
std::cout << "Phone number: " << person.getNumber() << "\n";
std::cout << "EGN: " << person.getEGN() << "\n\n";
}
}

Stringstream is not feeding into a string that has a endline character added to it

I'm basically trying to add integers to a string, and then add endline chars to the string at specific times, and then continue adding integers. I want it all added to just one string object.
So I added an int to stringstream, fed stringstream to a string. Then added '\n' to the string.
Then I added another int to stringstream, and fed it to the string again.
Unfortunately, the second object from the stringstream object is not being added to the string, and I'm not sure why it cannot.
I tried adding two objects to my string stream object, and then feeding those to the string one at a time (with the endline character in between), but stringstream adds everything in the string to the string at once, so that doesn't work.
int main(){
string h;
stringstream ss;
ss << 1;
ss >> h;
h += '\n';
ss << 2;
ss >> h;
h += '\n';
cout << h << "endline";
cout << endl;
return 0;
}
There are no error messages of course. I expect it to output:
1
2
endline
Instead I get
1
endline
So obviously the string is adding both of my endline characters, but not the 2 that I added to the stringstream.
To demonstrate what happened we need to inspect the various stream status bits.
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
int main()
{
string h;
stringstream ss;
if (ss << 1)
{
cout << "1 success. Fail " << ss.fail()
<< " eof " << ss.eof() << " bad " << ss.bad() << endl;
if (ss >> h)
{
cout << "2 success. Fail " << ss.fail()
<< " eof " << ss.eof() << " bad " << ss.bad() << endl;
h += '\n';
if (ss << 2)
{
cout << "3 success. Fail " << ss.fail()
<< " eof " << ss.eof() << " bad " << ss.bad() << endl;
if (ss >> h)
{
cout << "4 success. Fail " << ss.fail()
<< " eof " << ss.eof() << " bad " << ss.bad() << endl;
h += '\n';
cout << h << "endline";
cout << endl;
}
else
{
cout << "4 Fail " << ss.fail() << " eof " << ss.eof()
<< " bad " << ss.bad() << endl;
}
}
else
{
cout << "3 Fail " << ss.fail() << " eof " << ss.eof()
<< " bad " << ss.bad() << endl;
}
}
else
{
cout << "2 Fail " << ss.fail() << " eof " << ss.eof()
<< " bad " << ss.bad() << endl;
}
}
else
{
cout << "1 Fail " << ss.fail() << " eof " << ss.eof()
<< " bad " << ss.bad() << endl;
}
return 0;
}
Output
1 success. Fail 0 eof 0 bad 0
2 success. Fail 0 eof 1 bad 0
3 Fail 1 eof 1 bad 0
So the first write succeeded. Flawless victory. But the first read read everything in the stream and hit the end of file (not that the stream is a file, but the name stuck), setting the EOF bit. Once the EOF bit is set, there isn't much you can do with a stream other than clear the bit and pray someone adds more data to be read.
More data was added to the stream, but the file could not accept it because of the EOF bit.
If we clear the EOF
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
int main()
{
string h;
stringstream ss;
if (ss << 1)
{
cout << "1 success. Fail " << ss.fail() << " eof " << ss.eof()
<< " bad " << ss.bad() << endl;
if (ss >> h)
{
cout << "2 success. Fail " << ss.fail() << " eof " << ss.eof()
<< " bad " << ss.bad() << endl;
h += '\n';
ss.clear(); // added this
if (ss << 2)
{
cout << "3 success. Fail " << ss.fail() << " eof " << ss.eof()
<< " bad " << ss.bad() << endl;
if (ss >> h)
{
cout << "4 success. Fail " << ss.fail() << " eof " << ss.eof()
<< " bad " << ss.bad() << endl;
h += '\n';
cout << h << "endline";
cout << endl;
}
else
{
cout << "4 Fail " << ss.fail() << " eof " << ss.eof()
<< " bad " << ss.bad() << endl;
}
}
else
{
cout << "3 Fail " << ss.fail() << " eof " << ss.eof()
<< " bad " << ss.bad() << endl;
}
}
else
{
cout << "2 Fail " << ss.fail() << " eof " << ss.eof()
<< " bad " << ss.bad() << endl;
}
}
else
{
cout << "1 Fail " << ss.fail() << " eof " << ss.eof()
<< " bad " << ss.bad() << endl;
}
return 0;
}
the output is now
1 success. Fail 0 eof 0 bad 0
2 success. Fail 0 eof 1 bad 0
3 success. Fail 0 eof 0 bad 0
4 success. Fail 0 eof 1 bad 0
2
endline
If we ignore all the status information I added we really got
2
endline
not the desired
1
2
endline
because ss >> h will overwrite everything already in h. The "1\n" is wiped out by the "2"
The easiest way to get what you want is to write everything in and then get the contents as a string.
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
int main()
{
string h;
stringstream ss;
if (ss << 1 << '\n' << 2 << '\n')
{
cout << ss.str() << "endline";
cout << endl;
}
else
{
cout << "Fail " << ss.fail() << " eof " << ss.eof()
<< " bad " << ss.bad() << endl;
}
return 0;
}
This time the output is
1
2
endline
Use the stringstream to buildup the output you want, and then extract the string.
ss << 1 << '\n';
ss << 2 << '\n';
h = ss.str();

Program closes after user input, no reason it should

sorry, I'm very new and have to hurry, so I just wanted to put this up. The code randomly ends after trying the first input (choosing what topic, algebra, basic mathematics, etc.) I've tried other sources, tried reformatting and still don't know what it is. I'm fairly new, so I assume it's just a stupid issue that I overlooked.
#include <iostream>
#include <fstream>
#include <string>
#include <stdlib.h>
using namespace std;
int main() {
int calculatorChoice, choiceMath1;
int addition1, addition2, additionSum;
int subtraction1, subtraction2, subtractionDifference;
int multiplication1, multiplication2, multiplicationProduct;
int division1, division2, divisionQuotient;
cout << "What would you like to figure out?" << endl;
cout << "" << endl;
cout << "[1]: Basic Mathematic Equations" << endl;
cout << "[2]: Figuring out a Grade" << endl;
cout << "[3]: Algebra" << endl;
cout << "[4]: Inquiry Sciences" << endl;
cout << "[5]: Unit Conversion" << endl;
cin >> calculatorChoice;
if (calculatorChoice == 1) {
cout << "What would you like to do?" << endl;
cout << "" << endl;
cout << "[1]: Addition" << endl;
cout << "[2]: Subtraction" << endl;
cout << "[3]: Multiplication" << endl;
cout << "[4]: Division" << endl;
cin >> choiceMath1;
if (choiceMath1 == 1) {
cout << "Choose your first number." << endl;
cin >> addition1;
cout << "Choose your second number." << endl;
cin >> addition2;
additionSum = addition1 + addition2;
cout << "The sum of " << addition1 << " and " << addition2 << " is " << additionSum << "." << endl;
}
else if (choiceMath1 == 2) {
cout << "Choose the first number." << endl;
cin >> subtraction1;
cout << "Choose the second number." << endl;
cin >> subtraction2;
subtractionDifference = subtraction1 - subtraction2;
cout << "The difference of " << subtraction1 << " and " << subtraction2 << " is " << subtractionDifference << "." << endl;
}
else if(choiceMath1 == 3) {
cout << "Choose the first number." << endl;
cin >> multiplication1;
cout << "Choose the second number." << endl;
cin >> multiplication2;
multiplicationProduct = multiplication1 * multiplication2;
cout << "The product of " << multiplication1 << " and " << multiplication2 << " is " << multiplicationProduct << "." << endl;
}
else if(choiceMath1 == 4) {
cout << "Choose the first number." << endl;
cin >> division1;
cout << "Choose the second number." << endl;
cin >> division2;
divisionQuotient = division1 / division2;
cout << "The quotient of " << division1 << " by " << division2 << " is " << divisionQuotient << "." << endl;
}
else {
cout << "That is not a choice." << endl;
}
}
else {
}
}
void calculator() {
}
Your code doesnt have any loop, what means, after enter the input , it shows the result and program finishes. If you want to stop your code somewhere (depends on the IDE, this solution is for VS) just type system("pause")and you will see what your program shows on console. In case you are not on VS, add #include <cstdlib>
If you explain a bit more hat you expect your code to do we can help you easier.

C++ Dynamic array of structs segmentation fault

I am working on a program that reads data from a text file called "phonebook.txt" and displays it in terminal. It ask how many contacts the user wants to add. The user will input the number of contacts he/she wants and the program will output this along with the old contacts from "phonebook.txt" to "updated-phonebook.txt." Now I chose to use a dynamic array over a vector simply because I wanted to get a feel for how to handle memory allocation.
#include <iostream>
#include <string>
#include <fstream>
#define nullptr 0;
struct Person
{
std::string lName, fName, streetAddr, city, state, zip, phoneNum;
};
int main ()
{
std::ofstream outFile;
std::string dummy;
int amount, total, count = 0;
Person *contact;
//set the pointer to 0 so its not pointing
//to anything else in memory
contact = nullptr;
std::ifstream inFile("/home/isemanthaj/My_Programs/Class_Programs/Assignment_3/phonebook/phonebook.txt",std::ios::in);
if (!inFile)
{
std::cout << "File failed to open" << std::endl;
}
else
outFile.open("updated_phonebook.txt", std::ios::out);
std::cout << "How many contacts do you want to add?" << std::endl;
std::cin >> amount;
contact = new Person[amount];
std::cout << "Contacts in the previous book \n" << std::endl;
std::cin.ignore();
while (inFile)
{
//dummy stores the contact number which is the first line
// in the read file. I don't want to carry the number over
// to the other updated_phonebook.txt file
std::getline(inFile, dummy);
std::getline(inFile, contact[count].lName);
std::getline(inFile, contact[count].fName);
std::getline(inFile, contact[count].streetAddr);
std::getline(inFile, contact[count].city);
std::getline(inFile, contact[count].state);
std::getline(inFile, contact[count].zip);
std::getline(inFile, contact[count].phoneNum);
std::cout << contact[count].lName << std::endl;
std::cout << contact[count].fName << std::endl;
std::cout << contact[count].streetAddr << std::endl;
std::cout << contact[count].city << std::endl;
std::cout << contact[count].state << std::endl;
std::cout << contact[count].zip << std::endl;
std::cout << contact[count].phoneNum << std::endl;
outFile << contact[count].lName << std::endl;
outFile << contact[count].fName << std::endl;
outFile << contact[count].streetAddr << std::endl;
outFile << contact[count].city << std::endl;
outFile << contact[count].state << std::endl;
outFile << contact[count].zip << std::endl;
outFile << contact[count].phoneNum << std::endl;
count++;
}
// I know this is a little wacky here.
// I want the program to display the total amount of contacts
// to the screen
total = amount + count;
for (int index = 0; index < total; index++)
{
std::cout << "Last name: ";
std::getline(std::cin, contact[index].lName);
std::cout << "First name: ";
std::getline(std::cin, contact[index].fName);
std::cout << "Street address: ";
std::getline(std::cin, contact[index].streetAddr);
std::cout << "City: ";
std::getline(std::cin, contact[index].city);
std::cout << "State: ";
std::getline(std::cin, contact[index].state);
std::cout << "Zip code: ";
std::getline(std::cin, contact[index].zip);
std::cout << "Phone number: ";
std::getline(std::cin, contact[index].phoneNum);
std::cout << std::endl;
std::cout << "Contact: " << index + 1 << std::endl;
std::cout << "Last name: " << contact[index].lName << std::endl;
std::cout << "First name: " << contact[index].fName << std::endl;
std::cout << "Street address: " << contact[index].streetAddr << std::endl;
std::cout << "City: " << contact[index].city << std::endl;
std::cout << "State: " << contact[index].state << std::endl;
std::cout << "Zip code: " << contact[index].zip << std::endl;
std::cout << "Phone number: " << contact[index].phoneNum << std::endl;
std::cout << std::endl;
outFile << "Last name: " << contact[index].lName << std::endl;
outFile << "First name: " << contact[index].fName << std::endl;
outFile << "Street address: " << contact[index].streetAddr << std::endl;
outFile << "City: " << contact[index].city << std::endl;
outFile << "State: " << contact[index].state << std::endl;
outFile << "Zip code: " << contact[index].zip << std::endl;
outFile << "Phone number: " << contact[index].phoneNum << std::endl;
}
inFile.close();
outFile.close();
delete [] contact;
return 0;
}
I am trying to store the new contacts the user created and the old contacts from the read file in one dynamic array of structures. Am I getting this segmentation fault because I am using two different indexes "count" and "index" to store the contacts in the same dynamic array?
Your segfault is happening because you are trying to access an out-of-bounds element of contact array. The size of contact is amount, and you are iterating it from 0 to amount + count. Obviously, amount + count >= amount, so sooner or later you will run out of bounds.
I would suggest you to use std::vector instead of a plain array. You will always be aware of it's size and will be able to iterate it safely.
If you want to keep the arrays, you will have to either reallocate contact after copying the contacts from the old file, to make it size equal to total, or make two separate arrays: one to hold the records from the old file with the size of amount elements, and another one for the newly-added contacts with the size of count elements.
As it is mentioned in the comments, your end-of-file check is wrong, this and this questions are relevant.

How can I delete a element from a vector?

I'm developing a simple console based email application.
In my app, messages are stored in std::vector, and I want to add possibility to delete messages.
How can I delete a element from a vector?
Here's my code:
//MAIN MENU OPTION 1 SELECTED:
// print list of all messages to the console
void viewInbox() {
vector<Message> inbox{
Message("jayleno#hotmail.com", "Knife you tonight", "Hey Sam, what kind of suit do you wanna be buried in?!"),
Message("paypalservices#hotmail.com", "Urgent from paypal.com", "Dear paypal user, someone has hacked your account. Give us your password now so we change it!"),
};
cout << "You have " << inbox.size() << " new messages.\n";
cout << "Index Subject" << '\n';
for (int i = 0; i < inbox.size(); ++i)
std::cout << "Message " << i << ": " << inbox[i].getSubject() << '\n';
cout << "Please enter number of message you would like to view\n";
int read;
cin >> read;
cout << "From: " << inbox[read].getAddress() << '\n';
cout << "Subject: " << inbox[read].getSubject() << '\n';
cout << inbox[read].getMessageText() << '\n';
cout << "To erase this message press 1\n";
//Code here for deleting a message...
}//end of viewInbox()
To erase a message from the vector use vector::erase which takes an iterator.
The easiest way to get an iterator to a particular message is to use inbox.begin() + message_number.
I have refactored your code into smaller functions to make the code easier to work with:
void viewMessage(vector<Message>& messages, size_t message_number) {
vector<Message>::iterator message = messages.begin() + message_number;
cout << "From: " << message->getAddress() << endl;
cout << "Subject: " << message->getSubject() << endl;
cout << message->getMessageText() << endl;
cout << "To erase this message press 1\n";
int erase;
cin >> erase;
// Maybe do some error checking on cin...
if (erase == 1) {
messages.erase(message);
}
}
void viewMessages(vector<Message>& messages){
auto inbox_size = messages.size();
cout << "You have " << inbox_size << " new messages.\n";
cout << "Index Subject" << '\n';
for (size_t i = 0u; i != inbox_size; ++i) {
std::cout << "Message " << i << ": " << messages[i].getSubject() << '\n';
}
cout << "Please enter number of message you would like to view\n";
size_t message_number;
cin >> message_number;
// Maybe do some error checking on cin...
// And some bounds checking of message_number...
viewMessage(messages, message_number);
}
void viewInbox() {
vector<Message> inbox{
Message{ "jayleno#hotmail.com", "Knife you tonight", "Hey Sam, what kind of suit do you wanna be buried in?!" },
Message{"paypalservices#hotmail.com", "Urgent from paypal.com", "Dear paypal user, someone has hacked your account. Give us your password now so we change it!"},
};
viewMessages(inbox);
// Maybe call viewMessages again to see results of erase...
}
As I have commented, watch out for error checking on your input.