c++ Validating a Double in a String - c++

Please excuse any amateur mistakes, I'm still quite new to this. For my class we need to convert a double input to a string to use in a different part of the project. The verification for the integers worked just fine and I attempted using some of the code from this previous question Validating a double in c++
though, much to my chagrin it did not work.
Here is my code:
string input;
bool valid;
double num;
//Verification of valid inputs
do
{
valid = true;
cout << "What is the " << name << " rate of the population? (% per year): ";
getline(cin, input);
num = input.length();
if (num == 0)
{
cout << "\nNo data was entered, please enter a number.\n";
valid = false;
}
else
{
for (double i = 0; i < num; i++)
{
if (input.at(i) < '0' || input.at(i) > '9')
{
cout << "\nPlease enter a valid, positive number.\n";
valid = false;
break;
}
}
}
} while (valid == false);
return stod(input);
Thanks.
Edit:
I just found this How do i verify a string is valid double (even if it has a point in it)? and I can safely say I have no idea what is going on.

If you are really keen to do it manually, take a look at the following methods:
How to manually parse a floating point number from a string
https://www.daniweb.com/programming/software-development/code/217315/c-function-stod-string-to-double-convert-a-string-to-a-double
and read the comments. It's not quite straightforward, but it should work. Or even better, check the code of stod from C++.

Why are you using a double as an index for the string? Also, I'd skip using a ++ for increment a double.

Figured it out.
Just had to add something to an if statement.
if ((input.at(i) < '0' || input.at(i) > '9') && input.at(i) != '.')
{
cout << "\nError! illegal character was entered.\n";
valid = false;
break; // 12w345
if (input.at(i) == '.')
ct++;
if (ct > 1)
{
cout << "Error! Only one dot allowed.";
valid = false;
With ct being an integer with value 0 to count the dots and ensure only one was entered.

Related

When the input is a character or a word, it doesn't display "Invalid input"

When the input is >2 or <0 it display "Invalid input.". But when the input is an alphabet or a word it does not display "Invalid input."
int main()
{
int userInput, gesture;
cout << "Rock(0), Paper(1), Scissor(2): ";
cin >> userInput;
srand(time(0));
gesture = rand() % 3;
if (isdigit(userInput) && userInput >= 0 || userInput <= 2) //I think it's a logic error, but idk how to fix it.
{
switch (gesture)
{
case (0):
if (userInput == gesture)
cout << "The computer is rock. You are rock too. It is a draw." << endl;
else if (userInput == 1 && gesture == 0)
cout << "The computer is rock. You are paper. You win." << endl;
else if (userInput == 2 && gesture == 0)
cout << "The computer is rock. You are scissor. You lose." << endl;
break;
}
}
else
cout<<"Invalid input.";
return 0;
}
Let's look at this:
if (isdigit(userInput) && userInput >= 0 || userInput <= 2)
The signature of isdigit is this:
int isdigit( int ch );
so one might be fooled into thinking that it expects an int, like 1 or 34. In reality, it expects an argument of type unsigned char converted into an int. Why, you'd ask? Because it was included into C++ via the standard library of the C language, and in C there's a special marker EOF that marks the "end of file" in a stream of characters (just like \0 marks the end of a string). The problem is that EOF cannot be represented as a char, hence many C functions designed to handle strings accept ints. The only thing we know about EOF is that it is negative.
So, the usual usage of isdigit is something like this:
unsigned char c = '0';
// ...
if (isdigit(c)) { /* ... */ }
What you should do, then?
Well, the simpler, the better
if (userInput >= 0 && userInput <= 2)
If you want to check for completely invalid user input, check the state of cin
if (std::cin && userInput >= 0 && userInput <= 2)
An alternative is to initialize userInput with a plain wrong value, e.g. with -1. If cin fails, you'll know something wrong has happened anyway, because userInput woul'd have an ivalid value -1.
Use std::cin.clear() to clear the "fail state" flag in std::cin and unblock it.

Console is being flooded when error checking for things that are not an int

I'm trying to only allow integer values into my program, so I've made the following function. The function is similar to other ones I've seen online, and mine seems to work just fine up until I add an ! in front of it to check if something is not an int.
Function to check if input is an integer:
bool isInteger(std::string s)
{
for (int i = 0; i < s.length(); i++)
{
if (isdigit(s[i]) == false)
{
return false;
}
return true;
}
}
Function being put to use:
int getLevel()
{
int level;
std::cout << "Level One\n";
std::cout << "Level Two\n";
std::cout << "Level Three\n";
std::cout << "Level Four\n";
std::cout << "Level Five\n";
std::cout << "Enter your level (1-5): ";
std::cin >> level;
while (!isInteger(std::to_string(level)) || level < 1 || level > 5)
{
std::cout << "Enter an integer value between 1-5 inclusive: ";
std::cin >> level;
}
clrscr();
return level;;
}
I believe the function works just fine until I put the ! in front of it. I am trying to only allow integer input into my program, and when I enter a double or string, the console becomes flooded with the message "Enter an integer value between 1-5 inclusive: " and doesn't give any time to enter an input. I am fairly new to c++ programming and could use some advice. Thank you!
std::cin >> level;
will try to read an integer and it will never read anything other than an integer. If this fails std::cin's failbit is set and further input operations (like std::cin >> level; inside the loop) are skipped.
You need to check if the reading succeeded and ignore the current input if not. Like this for example:
std::cout << "Enter your level (1-5): ";
while(!(std::cin >> level) || level < 1 || level > 5) {
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
std::cout << "Enter an integer value between 1-5 inclusive: ";
}
As little semi-related hint: level will always be an integer. Converting it to a string will always be the string-representation of an integer, so isInteger(std::to_string(level)) will always be true, unless level is negative, because you don't check for the sign.
Also that return true; in isInteger must be outside the loop, else you only check the first character.
Thanks to all the replies and clarification, I've managed to come up with a solution of my own.
New isInteger function that now checks for everything that is needed including inputs like "0004" that a user suggested above:
bool errorCheck(std::string s)
{
int intLevel;
std::stringstream tempLvl(s);
tempLvl >> intLevel;
for (int i = 0; i < s.length(); i++)
{
if (isdigit(s[i]) == false || s[0] == '0' || intLevel < 1 || intLevel > 5)
{
return false;
}
}
return true;
}
The method in action:
std::cout << "Enter your level (1-5): ";
std::cin >> stringLevel;
while (!errorCheck(stringLevel))
{
std::cout << "Enter an integer value between 1-5 inclusive: ";
std::cin >> stringLevel;
}
std::stringstream lvl(stringLevel);
lvl >> level;
clrscr();
return level;
}
Please let me know if you spot any problems with the code or have any easier solutions. Thanks for all the help!
ok i am gonna tell u the fact that console input extracts the input from console so if u ever tried to do something like that
i.e read string in place of integer the cin is going to be in bad state you can check this fact by putting an if like this
if(!cin>>level) break;
and u will find it working actually stream takes input from the console and convert it to boolean value so u can always check it's state bad state return false else true...... ..
SO,finally the bug is in cin>>level...
I hope u understood.... also check out that return true statement..
i am gonna put u reference link for more answer on this bug...
user enters String instead of Int

Count the occurrence of numbers in C++?

I just recently created a code in C++ where I have to display the occurrence of numbers from a text file that I made using this code:
using namespace std;
int main()
{
bool isCovered[99] = {};
int number;
// Read each number and mark its corresponding element covered
while (cin.good())
{
cin >> number;
if (number == 0)
{
break;
}
if ((number >= 1) && (number <= 99))
{
isCovered[number - 1] = true;
}
}
// Check if all covered
bool allCovered = true; // Assumes all covered initially
for (int i = 0; i < 99; i++)
if (!isCovered[i])
{
allCovered = false; //Finds one number not covered
break;
}
// Display result
if (allCovered)
cout << "The tickets cover all numbers" << endl;
else
cout << "The tickets don't cover all numbers" << endl;
return 0;
}
It's not displaying a result, is the program too complex, or is it something that I'm missing?
EDIT: Thanks #selbie for the edit to my code, i was able to figure out that it was a user input but when i put in a zero for the final input. It displays the messages "The tickets don't cover all numbers", why is that?
The bug, if any, is here:
cin >> number;
while (number != 0)
{
isCovered[number - 1] = true;
cin >> number;
}
Two possible issues:
If reading from a redirected file, there's no detection of an end-of-file condition. Such would be the case if the program was invoked as program.exe < input.txt and the input.txt did not contain a 0. Without checking for eof, the program will hang when reading from an input file redirection.
Further, there's nothing to guard against bad input. i.e. numbers outside the range of [1..99]. Without guarding against out of range numbers, undefined behavior will get introduced. Or more likely, the stack will get trashed as a result of inserting into a memory address out of range.
The easy fix is this:
while (cin.good())
{
cin >> number;
if (number == 0)
{
break;
}
if ((number >= 1) && (number <= 99))
{
isCovered[number - 1] = true;
}
}

jumping outside loop in a specific case

I am writing a code that, for one or several lines of strings, find if the overall input has only "cool" (it's first middle and last string are the same) lines, only "uncool" lines or a mix of both.
The problem I'm having is whenever I input an even number the while loop terminates. Debugging I found that, just before jumping out n gets value 0 but I don't understand how this would make the loop end.
This is the code:
#include <iostream>
using namespace std;
int main () {
// Bool has control if we have found a cool line/non-cool line
bool cool = false;
bool uncool = false;
int n; //lenght of input
while (cin >> n) {
if (cool and uncool) break; // we have found one of each so we know it is a mixed input
else if (n%2 == 0) uncool = true; // if the lenght is even there is no middle string
else {
// we are trying to see if the middle and last string are equal to the first
string comparing_string;
cin >> comparing_string;
string rest_of_sequence;
bool this_is_cool = true;
for (int i = n-2; i >= 0; i--) { // we input the rest of strings and compare them to the first
cin >> rest_of_sequence;
if ((i == n/2 or i == 0) and rest_of_sequence != comparing_string) this_is_cool = false;
}
if (this_is_cool) cool = true;
else uncool = true;
}
}
if (cool and uncool) cout << "both types" << endl;
else if (cool and not uncool) cout << "all cool" << endl;
else if (uncool and not cool) cout << "none cool" << endl;
}
Any help is appreciated! I'm currently in first year of uni and always open to recommended books/webpages/videos to continue learning :)
The problem was that I thought the program would just ignore input that wasn't an integer in the while loop, but it doesn't.
Now the code is correct:
else if (n%2 == 0) {// if the lenght is even there is no middle string
uncool = true;
string just_passing_input;
for (int i = n; i > 0; i--) cin >> just_passing_input;
}
Thanks for the helpful feedback, I shall now continue learning.

C++ cin.ignore To ignore spaces, numbers, and characters to test a palindrome

I need to process a user input to see if it is a palindrome. Our professor said to use cin.ignore() to ignore spaces, numbers, and other characters so we will just compare the letter inputs.
So far I have just found code that ignores just one of these at a time and the code is more advanced than my learning so I do not know how to modify or apply it to my code.
I have the code to check the palindrome, I just do not know how to make it ignore the unwanted inputs.
Sorry this sort of question has been asked many times over but I cannot seem to figure it out.
Thanks in advance.
do
{
checkInput = false;
cout << "Enter the Palindrome: ";
getline(cin, input);
len = input.length();
if (len == 0)
{
cout << "\nNo data was entered, please enter a palindrome.\n";
checkInput = false;
}
} while (checkInput);
for (int i = 0, j = input.size() - 1; i < input.size(); i++, j--)
{
if (input[i] != input[j] && input[i] + 32 != input[j] && input[i] - 32 != input[j])
{
isPalindrome = false;
break;
}
}
if (isPalindrome)
{
cout << "This is a Palindrome!!" << endl;
}
else
{
cout << "This is not a Palindrome." << endl;
}
im assuming that input is a string. if so then what we want to do before your for loop is have another for loop to run through the string and remove anything unwanted from the string. I am going to assume that all you want to deal with are the upper and lowercase letters, as we are focusing on the ascii values between 65-90 and 97-122. source http://www.ascii-code.com/
to so do we can simply check each index in the string to see if it falls between these two ranges, and if it doesn't, then delete it.
for(unsigned int i = 0; i<input.size();i++)
{
if(input[i]< 65 || (90 <input[i] && input[i] < 97) || input[i] > 122)
{
input.erase(i,1);
i--
}
}
that should work.