I made a simple game program, and a requirement calls for a option for the player to undo a number of moves (undo n).
I have the user enter in a command (undo n) and it takes the back half and puts it into an int. Basically, I want the program to stop the user if they entered in anything but a number. So if the user typed in undo f it won't convert f into it's number form (or at least that's what I think it would do) but it'll cause an error. I searched for a while and couldn't find anything that worked or made sense to me.
try {
int undo;
istringstream is(userInput.substr(5, userInput.length()));
is >> undo;
for (int numOfUndos = undo; numOfUndos > 0; numOfUndos--) {
board.UndoLastMove();
}
moveValidated = true;
}
catch (exception &e) {
cout << "/-----------------------------/" << endl;
cout << e.what() << endl;
cout << "/-----------------------------/" << endl;
}
If possible, I would like to just use how I currently have it or with cin. Also, forgive me, but I'm still learning C++ and don't know many advanced techniques, so if there is a complex way to do this forgive me if it takes me a bit to understand.
Thanks for any help in advance.
This worked for me. Thanks again.
The game description is not really relevent to your problem: how to
convert a string into an integer and check if it failed. To do that,
if (is >> undo) { worked } else { failed } Does UndoLastMove throw an
exception? – Neil Kirk
Related
I just started learning to code, starting with C++ yesterday. I need it for a project I'm doing and I like to build generation tools as an "onboarding" process when I learn a new skills. So I thought I'd try building out a regex generation tool.
I googled, I binged, and I looked through the similar questions and only saw answers pertaining to Ruby, Perl, or JS. Frankly, I'm a bit surprised given the utility and prevalence of C++, not more people have tried this.
I don't know how to go about the task, as I'm not a professional or really knowledgeable about what I'm doing. I'm not sure how to ask such questions, either. Please bare with me while I explain my current thoughts.
I am currently toying around with generating strings using byte arrays (I find the C++ type system and casting is confusing at times). I wanted to see if there were any specific ranges of random values that produce strings with latin characters more than others. I get a lot of different values, and found a few ranges that looked like sweet spots, but I ultimately don't know what numbers correlate to what characters.
I wanted to establish a pattern, then set the rand() ranges to correlate with the projected total byte value of what the pattern should generate as a string, then go fishing. I understand that I have to account for upper bounds for characters. So the generated values would be something like:
//not implemented
int getBoundary(string expression){
srand(time(0));
int boundaries[2] = {0};
boundaries[0] = getCeilingValue(expression)
boundaries[1] = getFloorValue(expression)
return boundaries
}
practice.cpp
/*
Method actually producing the byte strings
*/
void practice::stuub(int boundaries[2]){
srand(time(0)); //seed
basic_string<char> byteArray = {}; //"byte array" instantiation
for (int i = 0; i < 1000; i += 1) {
if(i % 2 ==0){
byteArray.push_back(rand() % boundaries[0]);//ceiling
}else{
byteArray.push_back(rand() % boundaries[1]);//floor
}
}
std::string s(byteArray, sizeof(byteArray)); //convert to string
cout << s << "\n";
}
/*
just a copy pasta validation function that I don't know if I need yet
*/
bool isNumeric(string str) {
for (int i = 0; i < str.length(); i++)
if (isdigit(str[i]) == false)
return false; //when one non numeric value is found, return false
return true;
}
/*
current putzing around. It's just been real fun to play around with,
but I plan to replace the instantiation of values of the "mod" array with
the upper/lower bounds of the string projected values This currently takes
a value and just does random stuff to it on a fishing expedition to see
if I can find any patterns.
*/
void practice::randomStringGen() {
try {
srand(time(0));
int mod[2] = {0};
string choice;
while (choice != "q") {
cout << "\n enter an integer to generate random byte strings or press (q) to quit \n";
cin >> choice;
if(choice != "q") {// make sure its not quit, otherwise it still carries out the tasks
if (isNumeric(choice)) {//make sure its numeric
mod[0] = stoi(choice);
if(mod[0] > 0) {//make sure its not 0
mod[0] = int(pow(mod[0], mod[0]));//do some weirdo math
mod[1] = rand() % mod[0]+1; //get another weirdo number
cout << "\n random string start:\n";
stuub(mod);//generate random string
cout << "\n :random string end\n";
}else{//user entered invalid integer
cout << "\n you did not enter a valid integer. Enter numbers greater than 0";
}
}else{
cout << "\n " << choice << " is not an integer";
}
}
}
}catch(std::exception& e){
cout << e.what();
}
}
I hope that provides enough explanation of what I am trying to accomplish.
I'm not any sort of pro, and I have very little understanding of what I'm doing.
I picked this up yesterday as a absolute beginner.
Talk to me like I'm 5 if you can.
Also, any recommendations on how to improve and "discretize" what I'm currently doing would be much appreciated. I think the nested "ifs" look wonky, but that's just a gut instinct.
Thanks!
This question already has answers here:
Uninitialized variable behaviour in C++
(4 answers)
Closed 2 years ago.
I'm a newbie in the programming world, and i've decided to start with C++ code a few days ago as my first programming language.
I just started to read an online course which i'm guiding on (and aply while i'm reading it).
The course in question assigns a serie of small optional exercises, wich go hand in hand with the topic that is being dealt at that moment.
One of this optional exercises is: "Create a program that multiplies two whole numbers in the following way: it will ask the user for a first whole number. If the number that you type is 0, it will write on the screen "The product of 0 by any number is 0". If a number other than zero has been entered, the user will be prompted for a second number and the product of both will be displayed."
How it says, I did my best to coding that program.
The code of what I did is:
#include <iostream>
using namespace std;
int main ()
{
int a;
int b;
int solve;
cout << "Enter a number: ";
cin >> a;
if (a!=0)
{
cout << "Enter another number: ";
cin >> b;
}
if (b!=0)
{
solve = a * b;
cout << "The result of your operation is: " << solve << endl;
}
else cout << "The product of 0 by any number is 0." << endl;
return 0;
}
So, I press F9 to compile, then F10 to run it.
I proceed to testing it.
I put and different number from zero, I put another one. Throws me a multiplication of both. Nice.
I put and different number from zero, I put another one that actually its zero. Throws me the message of "else" order. Nice.
**BUT
I put and number equal to zero, and throws me the message of the "cout" order of "if (b!=0)".**
I didn't really know what I had done wrong, so, I ask for help from a friend who has some more experience than me, and tells me that actually it's nothing wrong. In fact, he proved me sending to me a screen cap of his Dev C++ with my code in it, and how it runs just how it had to be.
Then, I opened an online compiler (https://www.onlinegdb.com/online_c++_compiler#) to get down my doubts, and yes, there runs correctly too.
So, here's my question?
What's the problem? Why that happens?
I have the DevC++ 5.11 TDM-GCC 4.9.2, and I'm using the deafult compiler.
Please, I would like some of help, I feel more comfortable compiling in PC than online, it's more quick.
Thank you anyway for reading until here.enter image description here
The reason why this happens, as #TrebledJ mentioned, is that you've not initialised the variable b. So you can get over this problem just by initialising b to any value of your choice (preferrably 1 or 0 for simplicity). But there's a workaround if you don't want to initialise the values. I would transform your code to something like this:
if (a!=0)
{
cout << "Enter another number: ";
cin >> b;
if (b!=0)
{
solve = a * b;
cout << "The result of your operation is: " << solve << endl;
}
else cout << "The product of 0 by any number is 0." << endl;
}
else cout << "The product of 0 by any number is 0." << endl;
Basically, what I'm doing is, if the value of a after input is 0, I'm not running the part for taking the user input of b.
Here is an example code demonstrating the problem I'm facing.
#include <iostream>
#include <string>
extern "C" {
#include <unistd.h>
}
int main()
{
std::cout << "Making tests ready!" << std::endl;
std::cout << "\nTo start out, Enter an integer: ";
int a = 0;
std::cin >> a;
std::string input;
sleep(3); // what to do if user enters data during this?
std::cout << "\n Now enter a string";
std::getline(std::cin, input);
std::cout << "\nHere are your values - " << a << " & " << input;
return 0;
}
See the sleep call in between the code? This could be replaced with somewhat long delays while computing something when my program isn't accepting any inputs. Now if user presses some keys during this time, that input is captured by std::getline() in next line of code. I know this is the default behavior since it should capture the input being provided.
But what I want is to clear all that captured input and start fresh with 15th line that is std::cout << "\n Now enter a string";, which is immediately after sleep. I don't know exact term to describe this or else I would have used that. Thanking you.
Edit: I've tried using std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); in my code, but it asks for input and then discards it.
Please mind my english, not a native speaker.
Reading the comments causes me to think that you can't really solve this problem (at least by the means suggested there). There's an inherent race condition in any case. Consider the following lines:
sleep(3);
// (*) <- Potential location 1.
std::cout << "\n Now enter a string";
// (**) <- Potential location 2.
std::getline(std::cin, input);
The various comments show some (very technically-competent) ways to flush the standard input. The problem is, you cannot put them in the location marked (*) nor (**).
First location - you clear the standard input some way. Now you decide it's time to move to the next line (std::cout << ...). While you do that, the user types in some more input. Race!
Second location - You print out the message (std::cout << ...), and proceed to clear the standard input. Before you manage to do that, the user typed in something. Race!
It seems to me that any of the techniques described in the comment require locking the standard input, and I don't think there's a (standard) way to do so.
Before you start wasting your time on me, please keep in mind that this question is more about knowing if this shutdown is legit enough.
Alright.
I read all kinds of ways to shut down a program. I KNOW that it's always best to shut down the program, at the end! So as i said, i read all kinds of topics, but i couldn't really find one that i understood correctly. So i kinda came up with my own way. I just want to make sure it's an okay method.
int main()
{
cout << "Welcome to my fantastic program!" << endl;
cout << "You're the first one to experience my command program!" << endl;
cout << "Let's try with a simple command. Try typing help" << endl;
while (running == 1) {
commands();
if (running == 0) {
exit(0);
}
}
return 0;
}
So i want you to focus on the while loop. This is my method.
void commands()
{
cin >> command;
if (command == "help")
{
cout << "-------------------------------" << endl;
cout << "-this is the <HELP> section----" << endl;
cout << "-exit (exits the program.)" << endl;
cout << "-Stay tuned for more commands--" << endl;
cout << "-------------------------------" << endl;
}
else if (command == "exit")
{
running = 0;
}
else
{
cout << "The command does not exist: " << command << endl;
}
}
And this is my command function. As you see, this changes "running" to 0 (or false). I hope i made this understandable enough.
Thanks.
EDIT: All i want to know is, if this is an okay method :)
FINAL EDIT: Alright! I changed "exit(0);" to "return(0);". So i guess this is a okay good method! Thanks for your help! :)
Using exit() in a program is legal. Though it's generally a bad idea. But if the program is stuck without a way back for some weird reason, you can do it.
Using exit in main() is rude: I just can't think of a sane reson not to use return instead.
The difference between exit() and return from main is that the former will leave all local objects in stack frames from main to the call point hanging, destructor not called. Only the static/global objects get proper shutdown. It may surprise some portions of the code, and leave important things not done.
As C++ has fine exceptions, I'd consider it preferable to replace exit() with throwing something that manages up to main, where regular return happens.
The if (running == 0) but is pointless!
while (running == 1) {
commands();
}
return 0;
Does exactly the same - once running is 0 it falls out the bottom of the loop, and main returns. The whole idea of the global running is getting into side effect programming, which is a bad thing!
Given the boundary conditions in the question exit() does what you want it to. It terminates the process normally, performing the regular cleanup for terminating programs (atexit(), destroying objects without automatic storage etc).
You don't really want to use a global running, so I would rather suggest checking the return parameter of commands().
say
int commands()
{
if(wanna_exit)
return 1;
else
return 0;
}
And if you for some reason cannot just let commands() break the while loop (For example by checking the return parameter and setting running to 0 if it is 1), and you want to exit the program instantly rather than finishing evaluating the rest of the while loop then exit() is ok (although in this particular case return is better (since you are in main in the example) ). Just try to avoid having running as global - might seem innocent right now, but can turn mean later :).
I made a small program that generates primes and lets the user check a number and see if it's a prime or not. Problem is, I'm not sure how to properly design it. This is the program:
#include <iostream>
#include <vector>
typedef unsigned long long bigint;
std::vector<bool> sieve(size_t size)
{
std::vector<bool> primelist(size);
primelist[0] = false;
primelist[1] = false;
for (bigint i = 2; i < size; ++i) { primelist[i] = true; }
for (bigint i = 2; i * i < size; ++i)
{
if (primelist[i])
{
for (bigint j = i; j * i < size; ++j)
primelist[i*j] = false;
}
}
return primelist;
}
int main()
{
bigint range;
bigint number;
std::vector<bool> primes;
std::cout << "Enter range: " << std::endl;
std::cin >> range;
primes = sieve(range);
while (1)
{
std::cout << "Enter number to check: " << std::endl;
std::cin >> number;
if (primes[number])
std::cout << "Prime" << std::endl;
else
std::cout << "Not prime" << std::endl;
}
return 0;
}
The basic flow I want to achieve is: Input range, /handle input/, input number to check, /handle input/
I also want to give the user an option to change the range at any given time, by writing a command like "change range number"
I have a few problems with this:
I want the program to be under control if the user inputs a range bigger than unsigned long long, and if the user basically exceeds any limit(like for example if the range he input was 100 then if he checks for 101) an exception will be caught. I know this needs to be implemented using try/catch/throw, but I have no idea how to do that while keeping the option to change the range and without making my code spaghetti code.
Also, I want the errors to be of enum type(I read that enums are good for exceptions), something like
enum errors
{
OUT_OF_RANGE = 1, //Out of the range specified by the user
INCORRECT_VALUE, //If user input "one" instead of 1
RANGE_SIGNED, //If user inputs a signed value for range
NUM_LIMITS //Number exceeds unsigned long long
};
I have no idea how to use exception handling, not to mention using it with enums. How the hell do I keep this program safe and running, while keeping away from spaghetti code?
I am extremely confused. If someone could help me design this program correctly and maintain readability and efficiency, it will really improve my future program designs.
Thanks for reading!
You asked a lot.
You want to validate user input. Users should not be able to enter huge numbers, non-integers, and so on.
I'm going to start off by answering that this is absolutely not a scenario that exceptions should be used for. Exceptions are used to handle exceptional circumstances. These are ones you can't anticipate or really deal with.
A user enters a number that's too big? You can handle that. Tell them that their number is too big, please enter a number between 1 and X.
A user enters the word apple? You can handle that. Tell them that they can only enter integers.
One way of doing this would be to make a ValidateInput function. You can have it return a number (or an enum, they're basically the same thing) to tell you whether there was an error.
In order to do the validation, you will most likely have to receive input as an std::string and then validate it before turning it into a number. Getting input as an unsigned int or similar integral type doesn't really allow you to check for errors.
This adds a bit of work, since you need to manually validate the input manually. There are libraries with functions to help with this, such as boost::lexical_cast, but that's probably too much for you right now.
Below is some very basic psuedo code to illustrate what I mean. It's only meant to give you an idea of what to do, it won't compile or do the work for you. You could extend it further by making a generic function that returns a message based on an error code and so on.
enum error_code {
SUCCESS, // No error
OUT_OF_RANGE, // Out of the range specified by the user
INCORRECT_VALUE, // If user input "one" instead of 1
RANGE_SIGNED, // If user inputs a signed value for range
NUM_LIMITS // Number exceeds unsigned long long
};
// This function will check if the input is valid.
// If it's not valid, it will return an error code to explain why it's invalid.
error_code ValidateInput(const std::string& input) {
// Check if input is too large for an unsigned long long
if (InputIsTooLarge)
return NUM_LIMITS;
// Check if input is negative
if (InputIsNegative)
return RANGE_SIGNED;
// Check if input is not an integer
if (InputIsNotInteger)
return INCORRECT_VALUE;
// If we make it here, no problems were found, input is okay.
return SUCCESS;
}
unsigned long long GetInput() {
// Get the user's input
std::string input;
std::cin >> input;
// Check if the input is valid
error_code inputError = ValidateInput(input);
// If input is not valid, explain the problem to the user.
if (inputError != SUCCESS) {
if (inputError == NUM_LIMITS) {
std::cout << "That number is too big, please enter a number between "
"1 and X." << std::endl;
}
else if (inputError == RANGE_SIGNED) {
std::cout << "Please enter a positive number." << std::endl;
}
else if (inputError == INCORRECT_VALUE) {
std::cout << "Please enter an integer." << std::endl;
}
else {
std::cout << "Invalid input, please try again." << std::endl;
}
// Ask for input again
return GetInput();
}
// If ValidateInput returned SUCCESS, the input is okay.
// We can turn it into an integer and return it.
else {
return TurnStringIntoBigInt(input);
}
}
int main() {
// Get the input from the user
unsigned long long number = GetInput();
// Do something with the input
}
I like Dauphic's answer, particularly because it illustrates breaking down the problem into bits and solving them individually. I would, however, do GetInput a bit differently:
unsigned long long GetInput() {
// Get the user's input
std::string input;
error_code inputError;
// Repeatedly read input until it is valid
do {
std::cin >> input;
inputError = ValidateInput(input);
if (inputError == NUM_LIMITS) {
std::cout << "That number is too big, please enter a number between "
"1 and X." << std::endl;
}
// ...handle all other cases similarly
} while(inputError != SUCCESS);
// If ValidateInput returned SUCCESS, the input is okay.
// We can turn it into an integer and return it.
return TurnStringIntoBigInt(input);
}
The recursive solution is nice, but has the drawback of, well, being recursive and growing the stack. Probably that's not a big deal in this case, but it is something to watch out for.
As for how to write ValidateInput, basically you're going to be scanning the string for invalid characters and if none are found, testing if the value will fit in your chosen integer type until reading it into a variable with e.g. >>.
note: this solution has a serious flaw in that it doesn't check the state of std::cin. If the user were to pass EOF, i.e. press ^D, the program would get stuck in the loop, which is not good behavior.
Instead of a vector of bool you'd better use a bitset
With that, you can use the Eratosthene method to determine if a number is prime or not.