Stack around the variable 'equation' was corrupted - c++

I'm trying to make a calculator in VC++ and even though it runs, it keeps reading memory that I haven't told it to, and I don't know how to make it stop.
#include <iostream>
#include <ctype.h>
int main(){
char equation[4];
equation[3] = '\0'; //string terminator
int result;
bool wantsToContinue = true;
char yesOrNo;
equationPrompt:
std::cout << "Enter Equation: ";
std::cin >> equation;
while(wantsToContinue){
switch(equation[1]){
case '+':
result = int(equation[0]) + int(equation[2]);
break;
case '-':
result = int(equation[0]) - int(equation[2]);
break;
case '*':
result = int(equation[0]) * int(equation[2]);
break;
case '/':
result = int(equation[0]) / int(equation[2]);
break;
}
std::cout << std::endl << "Your answer is " << result << std::endl;
exitPrompt:
std::cout << "Exit? Y/N: ";
std::cin >> yesOrNo;
if(tolower(yesOrNo) == 'n'){
wantsToContinue = true;
goto equationPrompt;
}
else if (tolower(yesOrNo) == 'y')
wantsToContinue = false;
else{
std::cout << std::endl << "Unknown response." << std::endl;
goto exitPrompt;
}
}
return 0;
}

You make it stop by not writing an arcane Frankenstein language mix of C and C++, but instead using real C++ string types:
#include <string>
#include <istream>
#include <iostream>
int main()
{
std::string equation;
std::cin >> equation;
// now equation[0] is the first character
}
Note that int(equation[0]) is almost guaranteed not to be what you think. What you want is something like int x = std::atoi(equation[0]); or std::strtol(), but that only works for single digits. Probably much simpler to just stream into an integer, which performs an actual text-to-integer conversion:
int x, y;
std::string operand;
std::cin >> x >> operand >> y;

equation is an array of 4 chars.
std::cin >> equation;
reads an arbitrarily long string into that array. Type too much, and it will overflow, stepping on adjacent memory.
As #Kerrek SB says, you're better off using std::string, which doesn't have that problem.

Related

How can I throw a error if the user enters more than one integer

So this is my code:
#include <iostream>
#include <vector>
#include <string>
using namespace std;
long int iterFunc(int);
long int recurFunc(int);
int main() {
int n;
while(true){
try{
cout << "Enter: ";
if (!(cin >> n))
throw("Type Error");
if (n < 0)
throw n;
else
if (n == 0)
break;
cout << "Iterative: " << iterFunc(n) << endl;
cout << "Recursive: " << recurFunc(n) << endl;
}
catch(int n){
cout << "Error. Enter positive number." << endl;
}
catch(...){
cin.clear();
cin.ignore(100, '\n');
cout << "Error. Please enter a number" << endl;
}
}
cout << "Goodbye!";
return 0;
}
long int iterFunc(int n){
vector<long int> yVec = {1, 1, 1, 3, 5};
if (n <= 5)
return yVec[n - 1];
else
for(int i = 5;i < n; i++){
long int result = yVec[i - 1] + 3 * yVec[i- 5];
yVec.push_back(result);
}
return yVec.back();
}
long int recurFunc(int n){
switch (n) {
case 1:
case 2:
case 3:
return 1;
break;
case 4:
return 3;
break;
case 5:
return 5;
break;
default:
return recurFunc(n - 1) + 3 * recurFunc(n - 5);
break;
}
}`
The program shoud accept only one integer and return the y of the function using both iterative and recursive implemetations. Ex.: 30, 59, 433. How can I throw an error message if the user enters more then one integer, separated by space? Ex.: '3 45 32'.
I tried using if (cin.getline == ' ') throw("Error name") but the program still executes and return the y of the function for number in the input
Something like this works:
int main()
{
std::string str;
std::cout << "? : ";
std::getline(std::cin, str);
std::string::size_type pos(0);
int i = std::stoi(str, &pos);
if (pos != str.length())
return 1;
}
I found a part of my old code that might come in handy.
int val;
do
{
cin>>val;
if(!cin){ //you can add more conditions here
cin.clear();
cin.sync();
/* additional error handling */
}
else{
break; //input is correct - leaving loop
}
}while(true); //or here
Basically what !cin does is - it checks what type of value you actually want to write to, because it's needed anyway to figure out if data type is written to the correct type of our val. This means, that "30" or "433" etc. are integers (correct), "s" or "string" etc. are strings (or char*, correct me if I am wrong) (incorrect).
This also means, that "3 45 32" should be interpreted as string, which should result in another loop run.
Note: I didn't really test this code, so it might be completely wrong.
Edit: Okay now after some tests I realised this code needs some retweaking.
Firstly, "3 45 32" is not interpreted as string (now understandable). Instead, first number (before whitespace) is saved as an integer and all other numbers are stored in the buffer (next cin will be filled with it), which we can avoid using cin.clear() and cin.sync() once again.
The question is - is it okay for you to accept the first integer and ignore everything after the first whitespace? If not, you will have to save the input as string and extract whatever data you want from it.
I am leaving the original answer as is for simplicity of finding references in this edit.

When I input a number in char type, why i can't get a whole number?

I input a number in char type variable. like 12 or 22. but, console show me a 1 or 2.
How i get a whole number 12 ,22 in console?
#include <iostream>
int main()
{
using namespace std;
char a = 0;
cin >> a;
cout << a << endl;
return 0;
}
Here is console result.
12
1
C:\Users\kdwyh\source\repos\MyFirstProject\Debug\MyFirstProject.exe(프로세스 18464개)이(가) 종료되었습니다(코드: 0개).
이 창을 닫으려면 아무 키나 누르세요...
The reason I don't use int, string and something is because I want to get both number and Character in one variable.
So I want to see the results of combined numbers and character at the same time.
in that process i can't get a whole number.
#include <iostream>
using namespace std;
int index = 0;
constexpr int pagenum = 10;
void chapterlist(void);
void nextlist(void);
void beforelist(void);
void movechapter(char a);
int main(void)
{
char userin = 0;
bool toggle = 0;
cout << "결과를 볼 챕터를 고르시오." << endl;
chapterlist();
cout << "다음 페이지로 이동: n" << endl;
cin >> userin;
if (userin == 'n')
{
backflash:
while(toggle == 0)
{
nextlist();
cin >> userin;
if (userin == 'b')
{
toggle = 1;
goto backflash;
}
else if (userin == 'n')
continue;
else
{
system("cls");
movechapter(userin);
break;
}
}
while(toggle == 1)
{
beforelist();
cin >> userin;
if (userin == 'n')
{
toggle = 0;
goto backflash;
}
else if (userin == 'b')
continue;
else
{
system("cls");
movechapter(userin);
break;
}
}
}
else
{
system("cls");
movechapter(userin);
}
return 0;
}
void chapterlist(void)
{
int x = 0;
for (x = index + 1; x <= index + 10; x++)
cout << "Chapter." << x << endl;
}
void nextlist(void)
{
system("cls");
cout << "결과를 볼 챕터를 고르시오." << endl;
index = index + pagenum;
chapterlist();
cout << "다음 페이지로 이동: n" << endl;
cout << "이전 페이지로 이동: b" << endl;
}
void beforelist(void)
{
system("cls");
cout << "결과를 볼 챕터를 고르시오." << endl;
index = index - pagenum;
chapterlist();
cout << "다음 페이지로 이동: n" << endl;
cout << "이전 페이지로 이동: b" << endl;
}
void movechapter(char a)
{
cout << "선택한 Chapter." << a << "의 결과입니다." << endl;
}
In movechapter(), console show me a is 1 or 2, not 12, 22.
First, you have to understand what achar type is.
Character types: They can represent a single character, such as 'A' or '$'. The most basic type is char, which is a one-byte character. Other types are also provided for wider characters.
To simplify that, char can only hold one character.
Where as with your code, "12" is actually 2 separate characters, '1' and '2', and that's the reason it would not work.
Instead of declaring a as a char type, you could declare it as an int type, which is a type designed to hold numbers. So you would have:
int a = 0;
However, do note that int often has a maximum value of 2^31.
Or you could use std::string to store character strings. However, do note that if you wish to do any calculations to your string type, you would need to convert them to a number type first:
int myInt = std::stoi(myString);
Edit:
So I have re-checked your code after your update, there is nothing wrong with using std::string in your case. You can still check if user have input n or b by:
if (userin == "n")
Note that you would use double quotation mark, or "letter", around the content that you want to check.
On the other hand, you could use:
if(std::all_of(userin .begin(), userin.end(), ::isdigit))
To check if user have input a number.
Although char is just a number, it's presumed to mean "single character" here for input. Fix this by asking for something else:
int a = 0;
You can always cast that to char as necessary, testing, of course, for overflow.
You should be reading characters into a string, and then converting that string into an int. It would also probably make more sense to use something like getline() to read input, rather than cin >> a.
#include <string>
#include <iostream>
#include <stdexcept>
#include <stdio.h>
int main() {
std::string input_string;
/* note that there is no function that will convert an int string
to a char, only to an int. You can cast this to a char if needed,
or bounds check like I do */
int value;
while(1) {
getline(std::cin, input_string);
/* std::stoi throws std::invalid_argument when given a string
that doesn't start with a number */
try {
value = std::stoi(input_string);
} catch (std::invalid_argument) {
printf("Invalid number!\n");
continue;
}
/* You wanted a char, the max value of a `char` is 255. If
you are happy for any value, this check can be removed */
if (value > 255) {
printf("Too big, input a number between 0-255\n");
continue;
}
break;
}
printf("Number is %hhu\n", value);
}

Validating user input. Is The input an integer? C++ [duplicate]

I was typing this and it asks the user to input two integers which will then become variables. From there it will carry out simple operations.
How do I get the computer to check if what is entered is an integer or not? And if not, ask the user to type an integer in. For example: if someone inputs "a" instead of 2, then it will tell them to reenter a number.
Thanks
#include <iostream>
using namespace std;
int main ()
{
int firstvariable;
int secondvariable;
float float1;
float float2;
cout << "Please enter two integers and then press Enter:" << endl;
cin >> firstvariable;
cin >> secondvariable;
cout << "Time for some simple mathematical operations:\n" << endl;
cout << "The sum:\n " << firstvariable << "+" << secondvariable
<<"="<< firstvariable + secondvariable << "\n " << endl;
}
You can check like this:
int x;
cin >> x;
if (cin.fail()) {
//Not an int.
}
Furthermore, you can continue to get input until you get an int via:
#include <iostream>
int main() {
int x;
std::cin >> x;
while(std::cin.fail()) {
std::cout << "Error" << std::endl;
std::cin.clear();
std::cin.ignore(256,'\n');
std::cin >> x;
}
std::cout << x << std::endl;
return 0;
}
EDIT: To address the comment below regarding input like 10abc, one could modify the loop to accept a string as an input. Then check the string for any character not a number and handle that situation accordingly. One needs not clear/ignore the input stream in that situation. Verifying the string is just numbers, convert the string back to an integer. I mean, this was just off the cuff. There might be a better way. This won't work if you're accepting floats/doubles (would have to add '.' in the search string).
#include <iostream>
#include <string>
int main() {
std::string theInput;
int inputAsInt;
std::getline(std::cin, theInput);
while(std::cin.fail() || std::cin.eof() || theInput.find_first_not_of("0123456789") != std::string::npos) {
std::cout << "Error" << std::endl;
if( theInput.find_first_not_of("0123456789") == std::string::npos) {
std::cin.clear();
std::cin.ignore(256,'\n');
}
std::getline(std::cin, theInput);
}
std::string::size_type st;
inputAsInt = std::stoi(theInput,&st);
std::cout << inputAsInt << std::endl;
return 0;
}
Heh, this is an old question that could use a better answer.
User input should be obtained as a string and then attempt-converted to the data type you desire. Conveniently, this also allows you to answer questions like “what type of data is my input?”
Here is a function I use a lot. Other options exist, such as in Boost, but the basic premise is the same: attempt to perform the string→type conversion and observe the success or failure:
template <typename T>
auto string_to( const std::string & s )
{
T value;
std::istringstream ss( s );
return ((ss >> value) and (ss >> std::ws).eof()) // attempt the conversion
? value // success
: std::optional<T> { }; // failure
}
Using the optional type is just one way. You could also throw an exception or return a default value on failure. Whatever works for your situation.
Here is an example of using it:
int n;
std::cout << "n? ";
{
std::string s;
getline( std::cin, s );
auto x = string_to <int> ( s );
if (!x) return complain();
n = *x;
}
std::cout << "Multiply that by seven to get " << (7 * n) << ".\n";
limitations and type identification
In order for this to work, of course, there must exist a method to unambiguously extract your data type from a stream. This is the natural order of things in C++ — that is, business as usual. So no surprises here.
The next caveat is that some types subsume others. For example, if you are trying to distinguish between int and double, check for int first, since anything that converts to an int is also a double.
There is a function in c called isdigit(). That will suit you just fine. Example:
int var1 = 'h';
int var2 = '2';
if( isdigit(var1) )
{
printf("var1 = |%c| is a digit\n", var1 );
}
else
{
printf("var1 = |%c| is not a digit\n", var1 );
}
if( isdigit(var2) )
{
printf("var2 = |%c| is a digit\n", var2 );
}
else
{
printf("var2 = |%c| is not a digit\n", var2 );
}
From here
If istream fails to insert, it will set the fail bit.
int i = 0;
std::cin >> i; // type a and press enter
if (std::cin.fail())
{
std::cout << "I failed, try again ..." << std::endl
std::cin.clear(); // reset the failed state
}
You can set this up in a do-while loop to get the correct type (int in this case) propertly inserted.
For more information: http://augustcouncil.com/~tgibson/tutorial/iotips.html#directly
You can use the variables name itself to check if a value is an integer.
for example:
#include <iostream>
using namespace std;
int main (){
int firstvariable;
int secondvariable;
float float1;
float float2;
cout << "Please enter two integers and then press Enter:" << endl;
cin >> firstvariable;
cin >> secondvariable;
if(firstvariable && secondvariable){
cout << "Time for some simple mathematical operations:\n" << endl;
cout << "The sum:\n " << firstvariable << "+" << secondvariable
<<"="<< firstvariable + secondvariable << "\n " << endl;
}else{
cout << "\n[ERROR\tINVALID INPUT]\n";
return 1;
}
return 0;
}
I prefer to use <limits> to check for an int until it is passed.
#include <iostream>
#include <limits> //std::numeric_limits
using std::cout, std::endl, std::cin;
int main() {
int num;
while(!(cin >> num)){ //check the Input format for integer the right way
cin.clear();
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
cout << "Invalid input. Reenter the number: ";
};
cout << "output= " << num << endl;
return 0;
}
Under C++11 and later, I have the found the std::stoi function very useful for this task. stoi throws an invalid_argument exception if conversion cannot be performed. This can be caught and handled as shown in the demo function 'getIntegerValue' below.
The stoi function has a second parameter 'idx' that indicates the position of the first character in the string after the number. We can use the value in idx to check against the string length and ascertain if there are any characters in the input other than the number. This helps eliminate input like 10abc or a decimal value.
The only case where this approach fails is when there is trailing white space after the number in the input, that is, the user enters a lot of spaces after inputting the number. To handle such a case, you could rtrim the input string as described in this post.
#include <iostream>
#include <string>
bool getIntegerValue(int &value);
int main(){
int value{};
bool valid{};
while(!valid){
std::cout << "Enter integer value: ";
valid = getIntegerValue(value);
if (!valid)
std::cout << "Invalid integer value! Please try again.\n" << std::endl;
}
std::cout << "You entered: " << value << std::endl;
return 0;
}
// Returns true if integer is read from standard input
bool getIntegerValue(int &value){
bool isInputValid{};
int valueFromString{};
size_t index{};
std::string userInput;
std::getline(std::cin, userInput);
try {
//stoi throws an invalid_argument exception if userInput cannot be
//converted to an integer.
valueFromString = std::stoi(userInput, &index);
//index being different than length of string implies additional
//characters in input that could not be converted to an integer.
//This is to handle inputs like 10str or decimal values like 10.12
if(index == userInput.length()) isInputValid = true;
}
catch (const std::invalid_argument &arg) {
; //you could show an invalid argument message here.
}
if (isInputValid) value = valueFromString;
return isInputValid;
}
You could use :
int a = 12;
if (a>0 || a<0){
cout << "Your text"<<endl;
}
I'm pretty sure it works.

C++ How to protect against invalid input?

In my program, I want users to choose between two choices. Simply, 1 or 2. I have written the program to where it will protect against an invalid numeric value such as 3 or 28, but I cannot protect against alphabetical input.
Code is as follows:
int whileInt = 0;
int choiceOne_One = 0;
while(whileInt == 0)
{
cin >> choiceOne_One;
if(choiceOne_One != 1 && choiceOne_One != 2)
{
cout << "Woah! That wasn't an option! Try Again.\n";
}
else if(choiceOne_One == 1)
{
whileInt++;
cout << "\nYou have died. Be more careful.\n";
}
else if(choiceOne_One == 2)
{
whileInt++;
cout << "\nYou have survived the alien invasion due to your cunning sense of "
"safety.\nCongratulations.\n";
}
}
My brain still works in Java, please help me figure this out. It will definitely be appreciated.
Try this :
#include <iostream>
using namespace std;
int main()
{
char input;
cin>>input;
switch(input)
{
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
cout<<"valid input"<<endl;
break;
default :
cout<<"Invalid input"<<endl;
}
return 0;
}
You can define a case for all your valid inputs, leave the rest to default.
Integers from 0-9 have their ASCII values from 48-57 respectively.
This solution wont be helpful if you have
. input>9 or input<0
. input such as 1abc
Might be a bit late but my favorite way to do and this is what i use :
#include <iostream>
#include <string>
#include <limits>
//T is for our variable and lambdaFunc will be our lambda function or
//function pointer
template<typename T, typename lambdaFunc>
auto secureEntry(T& variable, LambdaFunc lFunc, std::string errorMessage) //can ommit error message
{
while(!(std::cin(variable)) && !lFunc(variable)){
std::cout << errorMessage << std::endl;
std::cin.clear();
std::ignore((std::numeric_limits<std::streamsize>::max)(), '\n');
}
}
int main(int argc, char* argv[]){
int mynumber = {0};
std::string errorMessage = "Please use a number bigger than 0 and lower than 5"
secureEntry(myNumber, [](int& mynumber) -> bool{
return mynumber > 0 && mynumber < 5;
}, errorMessage)
}
you can do this also
int whileInt=0;
int choiceOne_One = 0;
while(whileInt == 0)
{
cin >> choiceOne_One;
if (choiceOne_One == 1 || choiceOne_One == 2){
if (choiceOne_One == 1){
whileInt++;
cout << "\nYou have died. Be more careful.\n";
}
else {
whileInt++;
cout << "\nYou have survived the alien invasion due to your cunning sense of "
"safety.\nCongratulations.\n";
}
}
else {
cout << "Woah! That wasn't an option! Try Again.\n";
}
}
Try reading a std::string with std::getline, then simply compare the string with "1" or "2". Otherwise, you can just read the whole line with std::getline, then use std::stoi (C++11) to transform the read string into an integer. The result of std::stoi tells you whether the transformation was successful or not (i.e., whether the string represented an integer). If successful, then you can simply compare the integer with 1 or 2. If not successful, then an std::invalid_argument or std::out_of_range exception is thrown.
First case (with std::string comparison):
#include <iostream>
int main()
{
std::string input;
std::getline(std::cin, input);
if (input != "1" && input != "2")
std::cout << "Invalid input!";
}
Second case (using std::stoi):
#include <iostream>
int main()
{
std::string input;
std::getline(std::cin, input);
int n = std::stoi(input); // throws exception if cannot convert to int
if (n != 1 && n != 2)
std::cout << "Invalid input!";
}
If you change the program so that cin puts a User's answer to a std::string, then you could do tests on the string value.
If the string's length() was more than 1, it cannot be '1' or '2'
There are additional tests you can do, like std::isalpha(int ch)
#include <stdio.h>
#include <string>
#include <iostream>
int main(int argc, char * argv[]) {
std::string value;
std::cin >> value;
std::cout << "Value is " << value << "\n";
std::cout << "length of value is " << value.length() << "\n";
char ch;
ch = value.at(0);
if(std::isalpha(ch)) std::cout << "You did not enter a number" << "\n";
return 0;
}
robert#debian:/tmp$ g++ -Wall test.cpp
robert#debian:/tmp$ ./a.out
123
Value is 123
length of value is 3
robert#debian:/tmp$ ./a.out
abc
Value is abc
length of value is 3
You did not enter a number

Switch-statement inside a while-loop which loop infinitely

Here is my code:
int main()
{
int nothing;
string name;
int classnum;
bool classchosen;
string classname;
cout << "Welcome adventurer, your journey is about to begin.\n\n";
cout << "Firstly, what's your name? ";
cin >> name;
classchosen = false;
while (classchosen == false)
{
cout << "\n\nNow, " << name << ", choose your class entering its number.\n\n";
cout << "1- Warrior\n" << "2- Mage\n" << "3- Paladin\n" << "4- Monk\n\n";
cout << "Class number: ";
cin >> classnum;
switch(classnum){
case 1:
classname = "Warrior";
classchosen = true;
break;
case 2:
classname = "Mage";
classchosen = true;
break;
case 3:
classname = "Paladin";
classchosen = true;
break;
case 4:
classname = "Monk";
classchosen = true;
break;
default:
cout << "\nWrong choice, you have to enter a number between 1 and 4.\n" << endl;
break;
}
}
cout << "\nSo you are a " << classname << " ? Well, tell me something more about you...\n";
cin >> nothing;
return 0;
}
Now, when I run it and input a string (for example "fjdfhdk") when it asks about the class number, the program loops infinitely instead of going in the default statement, writing again the question and letting me choose another class. Why?
Try something like this:
#include <sstream>
#include <string>
using namespace std;
int getInt(const int defaultValue = -1){
std::string input;
cin >> input;
stringstream stream(input);
int result = defaultValue;
if(stream >> result) return result;
else return defaultValue;
}
//..in main
cout << "Class number: ";
int classNum = getInt();
switch(classNum){ .... }
The reason why it fails in your case is because cin is trying to read a bunch of chars into a int variable. You can either read it as a string and convert as necessary, or you can check the cin state explicitly when reading into a int variable by checking if any of the fail bits are set. The fail bits would be set if for example you try to read bunch of chars into an int.
Because you're reading into an int, and the read fails. This
has two effects:
your use of classnum afterwards is undefined behavior, and
the stream has memorized the error condition, so you can
check it later.
As long as the error condition is not cleared, all further
operations on the stream are no-ops. The simplest changes in
your program to make this work would be:
std::cin >> classnum;
if ( !std::cin ) {
classnum = 0;
std::cin.clear();
std::cin.ignore( std::numeric_limits<std::streamsize>::max(), '\n' );
}
switch ( classnum ) // ...
In case of an error, this sets classnum to a known value,
clears the error state, and skips all input up to the next
newline. (Otherwise, you'll just fail again, because the
characters which triggered the error are still there.)
Consider, however, using a separate function to extract the int,
and using getline, as per user814628's suggestion. The above
is more to explain to you what is happening, and why your see
the symptoms you see. user814628's suggestion is far better
software engineering.