cin error in C++ - c++

I am writing a program that will calculate password strength according to two formulas. It requires the user to enter 2 passwords, one being eight characters or less and the other being 20 characters or more. The first parts executes with out problem. But, when I go to execute the second part, the prompt to enter the password and character set both show up at the same time and when I enter anything, whether it be numbers or characters, it aborts. I have checked over my code several times and don't understand why this is happening. Any help would be greatly appreciated!
int main()
{
//All variables and constants are declared
string eight_password, first_char, next_seven, twenty_password, first_char_twenty, next_seven_twenty, next_twelve, remaining;
int ep_length, character_set, first_char_length, next_seven_length, character_set_20, twenty_length;
double eight_ent_strength, eight_nist_strength, twenty_ent_strength;
const int NIST_FIRST = 4, NIST_SEVEN = 2, NIST_REM = 1, NIST_CHARACTER=94, NIST_BONUS=6;
const double NIST_TWELVE = 1.5;
//Console prompts for user to input password and character set
cout << "Hello! Please enter a password of 8 characters or less (including spaces!):" << endl;
getline(cin, eight_password);
cout << "What character set is being used?";
cin >> character_set>>ws;
//Password length and information entropy strength are calculated and saved to the appropriate variables
ep_length = eight_password.length();
eight_ent_strength = (ep_length*((log(character_set))/(log(2))));
//First character and next seven characters are extracted and saved to the appropriate variables
first_char = eight_password.substr(0, 1);
next_seven = eight_password.substr(1, 7);
//First character and next seven characters lengths are calculated and saved to the appropriate variables
first_char_length = first_char.length();
next_seven_length = next_seven.length();
//NIST strength is calculated and saved to the appropriate variable
eight_nist_strength = (first_char_length*NIST_FIRST) + (next_seven_length*NIST_SEVEN)+((character_set/NIST_CHARACTER)*NIST_BONUS);
//The information that was calculated is now printed back out on the console to be viewed by the user
cout << "Your password " << eight_password << " is " << ep_length << " characters long. According to the information " << endl;
cout<<"entropy formula, it has a strength of " << eight_ent_strength << "." << endl;
cout << "The first character is \"" << first_char << "\" and the next seven characters are \"" << next_seven << "\". " << endl;
cout << "According to the NIST formula, it has a strength of " << eight_nist_strength << "." << endl << endl;
cout << "Now, please enter a password of 8 characters or less (including spaces!):" << endl;
getline(cin, twenty_password);
cout << "What character set is being used?";
cin >> character_set_20;
twenty_length = twenty_password.length();
twenty_ent_strength = (twenty_length*((log(character_set_20)) / (log(2))));
first_char_twenty = twenty_password.substr(0, 1);
next_seven_twenty = twenty_password.substr(1, 7);
next_twelve = twenty_password.substr(7, 19);
remaining = twenty_password.substr(19);
cout << remaining;
return 0;
}

Change
cin >> character_set;
to
cin >> character_set;
cin.ignore( 1<<14, '\n' );
The call to getline(cin, twenty_password) consumes the previous newline leftover from cin >> character_set; which is why it doesn't wait. This same problem and solution is here: getline(cin, aString) receiving input without another enter

try this ignore function in between the 2 getline() functions to get-rid of the newline in the buffer
cin.ignore (std::numeric_limits<std::streamsize>::max(), '\n');
It works after this inclusion

Related

char + int to change the char value

I am new to C++, learned it for more than a month. I have a beginner-level knowledge of Python, like creating a list, modifying it, loops, etc. I don't know some codes for C++ that I know in python.
I am making a program for a school class (creative program). This is a part of my code (description at the bottom):
int number, new_one, num_letter;
char one;
cout << "You chose to encypher a message\nPlease choose an integer between 1-25:";
cin >> number;
cout << "How many letters are in your word?";
cin >> num_letter;
if (num_letter == 1)
{
cout << "Enter the first letter";
cin >> one;
new_one = one + number;
cout << "Your encrypted message is '"
<< static_cast<char>(new_one)
<< "' with the code number of "
<< number;
I am making a program where it enciphers and deciphers a message. The user chooses the number of letters of their message (maximum of 10 because I don't know how to use a for-loop in C++ yet). Then, they choose an integer. Then, they enter the letter, hit Enter, enter the letter, and hit Enter for the number of letters in their message (I don't know how to separate strings to chars in C++ yet).
When the user enters their letter and hits Enter, I cin >> that letter into the variable one, which is a char. Then, I add that one to the number the user chose, so the ASCII code of the one increases by the value of the number.
For example, when I enter 3 for number and h for the value of one, 104 (the ASCII code of h) should add up with 3, resulting in 107, which I then would static_cast to a char value.
But, when I add h and 3, instead of creating 107, it creates 155. Same for other variables. I tried cout'ing static_cast<int>(one) (in this case, the letter h) and number (which is 3). They printed 104 and 3.
But, when I add those two values, it prints 155. Why is this happening?
This is my solution. Hope it helps!
#include <iostream>
using namespace std;
int main()
{
int offset = 0;
int num_with_offset;
int size;
// Gets offset from user
do{
cout << "You chose to encypher a message\nPlease choose an integer between 1-25: ";
cin >> offset;
} while (offset < 1 || offset > 25);
// Gets letters in word
do{
cout << "Letters in word: ";
cin >> size;
} while(size < 0);
// Given size, init arrays
int number[size];
char one[size];
// Conversion from char to int
for(int i = 0; i < (sizeof(one)/sizeof(one[0])); i++)
{
cout << "Enter character " << (i + 1) << ": ";
cin >> one[i];
num_with_offset = one[i] + offset;
// Converts ASCII to integer and stores it into array
number[i] = static_cast<int>(num_with_offset);
}
// Prints out the new encrypted message
for(int j = 0; j < (sizeof(number)/sizeof(number[0])); j++)
{
cout << "Your encrypted message is: "
<< number[j] << " , with the code number: "
<< offset << "." << endl;
}
cout << endl << endl;
return 0;
}

Trying to validate input in C++

The idea behind this code in c++ is to calculate the sum of all the entered numbers. When the user enters 0, the program should stop. This part of the code is working as I intended, but I'd like to include a variant which recognizes that a character different than a float number has been entered, ignore it in the calculation and allow the user to continue entering float numbers. At the moment, entering anything else but a float number stops the program.
I know there's a "if (!(cin >> numb))" condition, I've tried parsing it in different places in the code, but I can't figure out how to force the program to ignore these invalid inputs. I would be very grateful for any help.
#include <iostream>
#include <stdlib.h>
using namespace std;
float numb; float sum=0;
int main()
{
cout << "This app calculates the sum of all entered numbers." << endl;
cout << "To stop the program, enter 0." << endl << endl;
cout << "Enter the first number: ";
cin >> numb;
while(true)
{
sum += numb;
if (numb!=0)
{
cout << "Sum equals: " << sum << endl << endl;
cout << "Enter another number: ";
cin >> numb;
}
else
{
cout << "Sum equals: " << sum << endl << endl;
cout << "Entered 0." << endl;
cout << "Press Enter to terminate the app." << endl;
exit(0);
}
}
return 0;
}
You have three options:
trial and error: try to read a float, and in case of error clear the error flag, ignore the bad input and read again. The problem is that you don't know really how many of the input is to be ignored.
read strings: read space delimited strings, try to convert the string using stringstream, and just ignore the full string in case of error. The problem is that if the input starts with a valid float but then contains invalid characters (e.g. 12X4), the invalid part will be ignored (e.g. X4)
control parsing: read space delimited strings, try to convert the string using std::stof(), and check that all characters of the string where successfully read
Here the second approach, with a slightly restructured loop, so that a 0 entry will lead to exiting the loop and not the full program:
string input;
while(cin >> input)
{
stringstream sst(input);
if (sst>>numb) {
sum += numb;
cout << "Sum equals: " << sum << endl << endl;
if (numb==0)
{
cout << "Entered 0." << endl;
break; // exits the while loop
}
cout << "Enter another number: ";
}
else
{
cout << "Ignored entry "<<input<<endl;
}
}
cout << "Press Enter to terminate the app." << endl;
Online demo
If you prefer a more accurate parsing, consider something like:
size_t pos=0;
float xx = stof(input, &pos );
if (pos!=input.size()) {
cout << "error: invalid trailing characters" <<endl;
}
You have to clear the failbit after a failed read. After that, you can read in the invalid stuff into a string (that you just ignore). This function will read in values and add them up until it encounters a 0 or the end of the input stream.
int calc_sum_from_input(std::istream& stream) {
int sum = 0;
// If it couldn't read a value, we just read the thing into here
std::string _ignored;
while(stream) // Checks if the stream has more stuff to read
{
int value;
if(stream >> value)
{
if(value == 0) // Exit if it read the value 0
break;
else
sum += value; // Otherwise update the sum
}
else {
// Clear the failbit
stream.clear();
// Read ignored thing
stream >> _ignored;
}
}
return sum;
}
The logic is basically:
set the initial sum to 0
check if there's stuff to read
if there is, try reading in a value
if successful, check if the value is 0
if it's 0, exit and return the sum
otherwise, add the value to the sum
otherwise, clear the failbit (so that you can read stuff in again) and read the bad value into a string (which gets ignored)
otherwise, return the value

Why isn't this while loop exiting?

I wrote a console program to help me test a function library I coded. Part of it is this piece of code:
char insertChoice[2] = {'9'};
while (insertChoice[0] != '0')
{
cout << "\nEnter a string:\n";
char insertStringInput[256];
cin.getline(insertStringInput, 255);
char insertChoice[2];
insertChoice[0] = '9';
cout << "\nWhere would you like to insert the substring?\n\n
1) At the beginning of the string\n
2) At the end of the string\n\nInput: ";
cin >> insertChoice;
cin.ignore();
while (insertChoice[0] != '1' && insertChoice[0] != '2')
{
cout << "\nInvalid input.\nWhere would you like to insert the substring?\n\n
1) At the beginning of the string\n
2) At the end of the string\n\nInput: ";
cin >> insertChoice;
cin.ignore();
}
cout << "\nEnter the substring you would like to insert: ";
char insertSubstring[256];
cin.getline(insertSubstring, 255);
std::string used = "", substr = "";
used += insertStringInput;
substr += insertSubstring;
char insertOutputChoice[2];
insertOutputChoice[0] = '1';
if (insertChoice[0] == '1')
insertOutput(insertInBeginning(used, substr));
else
insertOutput(insertInEnd(used, substr));
cin >> insertOutputChoice;
cin.ignore();
if (insertOutputChoice[0] == '1')
{
ofstream outfile("logfile.txt", ios::app);
outfile << "Test type: Insert Substring\n";
outfile << "Test carried out on: " << __DATE__ << "; " << __TIME__ <<"\n";
outfile << "PARAMETERS:\n";
outfile << "usedString: \"" << insertStringInput << "\"\n";
outfile << "insertString: \"" << insertSubstring << "\"\n";
outfile << "function used: "
<< (insertChoice[0]=='1'?"insertInBeginning":"insertInEnd")
<< "\nOUTPUT:\n";
outfile << "\""
<< (insertChoice[0]=='1'?insertInBeginning(used, substr):insertInEnd(used, substr))
<< "\"\n\n";
outfile.close();
cout << "\nWould you like to do another string insertion test? [y/n]: ";
char insertConfirm[2];
insertConfirm[0] = ' ';
while (tolower(insertConfirm[0]) != 'y'
&& tolower(insertConfirm[0] != 'n'))
{
cin >> insertConfirm;
cin.ignore();
if (tolower(insertConfirm[0]) != 'y'
&& tolower(insertConfirm[0] != 'n'))
cout << "\nInvalid input.
Would you like to do another string insertion test? [y/n]: ";
}
if (insertConfirm[0] == 'n')
insertChoice[0] = '0';
}
}
However, the while (insertChoice[0] != '0') loop does not exit when the user types in insertOutputChoice as 1, regardless of whether the user types in insertConfirm as y or n even though it is supposed to exit when insertConfirm is typed in as n.
insertOutput looks as looks as follows:
void insertOutput(std::string substrOut)
{
cout << "\nThe new string generated is:\n";
cout << substrOut;
cout << "\n\n1) Generate a log file of this test\n";
cout << "2) Insert another substring into a string\n\n";
cout << "0) Finish testing string insertion\n\n\n";
cout << "Input: ";
}
Please excuse the messy, unoptimized code. My first priority is to get this done, and I usually leave optimization until last.
Inside the while loop you create a new insertChoice array. And it hides external one. So when you modify values in this array, external one remains unmodified.
I think there may also be an issue with the if statement at the end of the code. Have you tried this while inputting in both upper and lower case? When checking for a valid input you are converting to lowercase to check but not when checking if the response is 'n'.
Remove line 9:
char insertChoice[2];
There are a lot of errors in your code, are you sure it's compiling correctly?
First, there are 2 insertChoice declarations
char insertChoice[2] = {'9'}; // <------- 1ˢᵗ
and in the while loop:
char insertChoice[2]; // <------- 2ⁿᵈ
insertChoice[0] = '9';
The compiler should warn you about that. If not you must enable warnings with the appropriate options of your compiler (/W3 for cl, -Wall -Wpedantic for gcc...). Never compile without warnings
Second, the following string has syntax error
cout << "\nWhere would you like to insert the substring?\n\n
1) At the beginning of the string\n
2) At the end of the string\n\nInput: ";
If you want a line break in the string you must use an escape right before the new line character
cout << "\nWhere would you like to insert the substring?\n\n\
1) At the beginning of the string\n\
2) At the end of the string\n\nInput: ";
or use multiple string literals like this
cout << "\nWhere would you like to insert the substring?\n\n"
"1) At the beginning of the string\n"
"2) At the end of the string\n\nInput: ";
Consecutive literals will be automatically combined into one by the compiler
In C++-0x life is a lot easier with raw string literals where embedded quotes or newlines are possible
cout << R"(
Where would you like to insert the substring?
1) At the beginning of the string
2) At the end of the string
Input: )";

I'm having trouble writing a console application to create a simple program to solve a math equation for superannuation

Could some one help me with this?
I've racked my head over an hour and I can't get it to work.
This is in C++ and I've been learning for a little bit but I'm still new...
int main()
{
double rate, amount,time, S;
cout << "Insert the time of the super: ";
cin >> time;
cout << "Insert the rate (as a decimal, eg 1% AKA 101% = 1.01): ";
cin >> rate;
cout << "Insert the amount $: ";
cin >> amount;
S =("amount * (rate ^ time - 1)", pow(rate,time));
cin >> S;
cout << "The total amount is: " << "S /(rate - 1)" << endl;
system("PAUSE");
return 0;
}
i dont get a compile error but i can never get an answer from it
You "never get a result" because you're setting S to the result of pow with comma operator weirdness then assigning to it again with the line
cin >> S;
which is waiting for you to input another number.
You have two main problems. Here is the updated code with comments on the altered parts:
int main()
{
double rate, amount,time, S;
cout << "Insert the time of the super: ";
cin >> time;
cout << "Insert the rate (as a decimal, eg 1% AKA 101% = 1.01): ";
cin >> rate;
cout << "Insert the amount $: ";
cin >> amount;
S = amount * pow(rate, time - 1); // take away the quotes and don't make pow seperate
cout << "The total amount is: " << (S /(rate - 1)) << endl; // do the calculation and output it
system("PAUSE");
return 0;
}
Remember that things inside quotes "like this" are string literals, so "4 * 4" is a string but 4 * 4 (see the absence of quotes) does multiplication which yields the number 16.
I don't think you should assign values to S the way you are doing it. S is declared as double and you are assinging a string to it initially. And when you output the result you are also enclosing the calculation in quotes. You should simply cout << S / (rate-1); // without quotes or cout will simply output the string

First while loop's first iteration always fails to take input. 2+ loops work fine

The bug starts at cin.getline ( string, 25, '\n' ); or the line below it (strtod). If I use cin, it works, except I cannot quit out. If I type anything that's not a double, an infinite loop runs. Need help. Basically, the first iteration runs, does not ask for input, so the user gets the math questions wrong. The second iteration works fine. And the next is fine, too. If I back out, using q, I get dumped back to the mode-chooser. After choosing a mode, the bug reappears for the first iteration. Next iterations it's gone.
int main()
{
char choice, name[25], string[25], op;
int operator_number, average, difference, first_operand, second_operand, input, answer, total_questions = 0, total_correct = 0;
double dfirst_operand, dsecond_operand, dinput, danswer, percentage;
bool rounding = false;
srand ( time(NULL) );
cout << "What's your name?\n";
cin.getline ( name, 25, '\n' );
cout << '\n' << "Hi, " << name << ".";
do {
do {
cout << "\nWhich math operations do you want to practice?\n 1. Addition\n 2. Subtraction\n 3. Multiplication\n 4. Division\n 5. Mixed\n 6. Difference of squares multiplication.\nChoose a number (q to quit).\n";
cin >> choice;
} while( choice < '1' || choice > '6' && choice!= 'q');
cout << "\n";
switch(choice) {
case '1':
while( string[0]!= 'q') {
dfirst_operand = rand() % 15 + 1;
dsecond_operand = rand() % 15 + 1;
danswer = dfirst_operand + dsecond_operand;
cout << dfirst_operand << " + " << dsecond_operand << " equals?\nEnter q to quit.\n";
cin.getline ( string, 25, '\n' );
dinput = strtod( string,NULL);
//cin >> dinput;
if(string[0]!='q') {
++total_questions;
if(dinput==danswer) {
++total_correct;
cout << "Correct. " << total_correct << " correct out of " << total_questions << ".";
} else {
cout << "Wrong. " << dfirst_operand << " + " << dsecond_operand << " equals " << danswer << ".\n" << total_correct << " correct out of " << total_questions << ".";
};
percentage = floor(10000 * (float) total_correct / total_questions)/100;
cout << ' ' << percentage << "%.\n\n";
}
}
break;
}
} while(choice!='q');
return 0;
}
The problem is this line:
cin >> choice;
This line parses the input buffer for character input that can be converted to an integer. So if you enter:
2<newline>
The string "2" is converted, and <newline> remains in the input buffer; so the subsequent cin.getline() is satisfied immediately.
This is also why JonH's suggestion does not work, you need to purge the input buffer after the cin << choice input. An alternative is to use cin.getline() for all input (or better; use ::getline() which operates on std::string rather than C-strings), and then parse that input using a std::istringstream object when you need formatted input scanning.
However if you must use cin.ignore() to solve this problem, you should do it thus:
cin.ignore( std::numeric_limits<std::streamsize>::max(), '\n' ) ;
where std::numeric_limits is defined in the header. Your solution trusts the user not to enter more than 25 characters. That is not a very safe assumption.
Try to throw a cin.ignore() right after or before the cin.getline().