Detect real numbers beyond whole numbers - c++

This code is meant to detect REAL numbers from a string entered continuously by a user, and return the found real number as a double value . I was able to construct it to the point where it detects whole numbers, but if I try a decimal number it doesn't detect it. I think my error is within my isvalidReal() function, but I'm not sure how to move things around to get it to work.
#include <iostream>
#include <string>
#include <cctype>
using namespace std;
int main()
{
double getaReal(); //function prototype
int value;
cout << "Enter a number: ";
value = getaReal();
cout << "the number entered is a real number: " <<value << endl;
return 0;
}
bool isvalidReal(string str) //function to find real numbers.
{
int start = 0;
int i;
bool valid = true;
bool sign = false;
if (int(str.length()) == 0) valid = false; //check for empty string
if (str.at(0) == '-' || str.at(0) == '+') //check for sign
{
sign = true;
start = 1; //check for real num at position 1
}
if (sign && int(str.length()) == 1) valid = false; //make sure there's atleast 1 char after the sign
i = start;
while (valid && i<int(str.length()))
{
if (!isdigit(str.at(i))) valid = false; //found a non-digit character
i++; // move to next character
}
return valid;
}
double getaReal()
{
bool isvalidReal(string); //function declaration prototype
bool isnotreal = true;
string input;
while (isnotreal)
{
try
{
cin >> input; //accepts user input
if (!isvalidReal(input)) throw input;
}
catch (string e)
{
cout << "No real number has been detected, continue to\n enter string values: ";
continue; //continues user input
}
isnotreal = false;
}
return atof(input.c_str());
}

Related

write a code for checking valid email address,

i was writing a code on code blocks for checking a valid email address by checking following conditions:
1.must have at least one uppercase.
2.should have characters above 8 and less than 50
3.should have # sign
i have used 3 while loops for checking individual condition , but after entering the email address the program gets stopped . here is my code ,does anyone know what is the problem?
enter code here
#include<iostream>
using namespace std;
#include<stdio.h>
#include<conio.h>
void check_mail()
{
int i = 0;
char email[25];
int measure = 0;
cout<<" \n \n \n enter an email address ::";
gets(email);
while(email[i] != '\0')//for checking uppercsae //
{
if( (int)email[i] >= 65 && (int)email[i] <= 90)
{
measure = 1;
}
if( measure != 1)
{
cout<<"\n there is no uppercase letter in the email address ";
break;
}
}
while(email[i] != '\0') //checking # sign//
{
if((int)email[i] == 64)
{
cout<<" \n found the # character at :: "<<i<<endl;
}
}
int counter = 0;
while(email[i] != '\0')
{
counter = counter +1 ;
}
if(counter >=8 && counter <=50)
{
cout<< "\n valid number of characters are present in the mail :: ";
}
else if(counter <8)
{
cout<<" \n number of characters are less than 8 ";
}
else if(counter >=51 )
{
cout<<"\n the elements are greater than 50 ";
}
else
{
cout<<"\n enter a valid email address::";
}
}
int main()
{
cout<<" \n \n enter a email address ";
check_mail();
return 0;
}
This code below is a working and a way better implementation of your code:
#include <iostream>
#include <string>
bool check_mail(const std::string email)
{
if (email.size() < 8 || email.size() > 50) return false;
int upper_letters = 0;
for (int i = 0; i < email.size(); i++)
{
if (std::isupper(email[i])) upper_letters++;
if (email[i] == '#')
{
if (i < 8) return false;
else if (upper_letters == 0) return false;
return true;
}
}
return false;
}
int main()
{
std::cout << " \n \n Enter an email address ";
std::string email; std::cin >> email;
std::cout << check_mail(email) << std::endl;
return 0;
}
If you need to know what exactly caused the email to get rejected, you can do the following:
#include <iostream>
#include <string>
enum email_states { correct, under_char, over_char, no_upper, no_at_the_rate };
email_states check_mail(const std::string email)
{
if (email.size() < 8) return email_states::under_char;
else if (email.size() > 5) return email_states::over_char;
int upper_letters = 0;
for (int i = 0; i < email.size(); i++)
{
if (std::isupper(email[i])) upper_letters++;
if (email[i] == '#')
{
if (i < 8) return email_states::under_char;
else if (upper_letters == 0) return email_states::no_upper;
return email_states::correct;
}
}
return email_states::no_at_the_rate;
}
int main()
{
std::cout << " \n \n Enter an email address ";
std::string email; std::cin >> email;
std::cout << check_mail(email) << std::endl;
return 0;
}
For the 2'nd code, if the output is:
0 - correct
1 - under_char
2 - over_char
3 - no_upper
4 - no_at_the_rate
Also, using namespace std is considered as a bad practice. For more info on this look up to why is "using namespace std" considered as a bad practice.
You could consider using std::string and utilizing the standard library:
#include <iostream>
#include <string>
constexpr int kMinEmailCharacters = 8;
constexpr int kMaxEmailCharacters = 50;
constexpr char kAtSign = '#';
bool IsValidEmail(const std::string &email) {
auto email_length = email.length();
auto contains_uppercase = std::count_if(email.begin(), email.end(), isupper);
auto contains_at_sign = email.find(kAtSign) != std::string::npos;
return email_length > kMinEmailCharacters &&
email_length < kMaxEmailCharacters && contains_uppercase &&
contains_at_sign;
}
int main() {
std::cout << "Enter email: ";
std::string user_email;
std::cin >> user_email;
auto valid_email = IsValidEmail(user_email);
std::cout << "Valid email: " << (valid_email ? "true" : "false") << '\n';
return 0;
}
Example Usage 1:
Enter email: tejaspatil#mail.com
Valid email: false
Example Usage 2:
Enter email: Tejaspatil#mail.com
Valid email: true
There are some logic errors in the code:
in the first loop you print "there is no uppercase letter in the email address" when the first character is not an uppercase letter. You need to check all letters before you know if there was an uppercase
after the first loop, i is already at the end of the string, the next loop will not have a single iteration.
Further
use std::string
conio.h is windows only. You don't need it when you can use std::cin.
while(email[i] != '\0') is error-prone (you need to corrceclty manage the index, which your code fails to do). Use a range based loop instead
try to avoid magic numbers.
don't use C-style casts
in particular there is no need to cast the characters to int. You can compare directly to 'A' and 'Z'.
after you checked if the size of the input is <8 or >=8 && <=50 or >51 there is no other case, the else is superfluous.
Your code with this fixes:
#include<iostream>
using namespace std;
void check_mail()
{
int i = 0;
std::string email;
int measure = 0;
cout<<" \n \n \n enter an email address ::";
//gets(email);
std::cin >> email;
for (char c : email) {
if( c >= 'A' && c <= 'Z') { measure = 1; }
}
if( measure != 1) {
cout<<"\n there is no uppercase letter in the email address ";
//break;
}
for (char c : email) {
if(c == '#') {
cout<<" \n found the # character at :: "<<i<<endl;
}
}
int counter = email.size();
if(counter >=8 && counter <=50) {
cout<< "\n valid number of characters are present in the mail :: ";
}
else if(counter <8) {
cout<<" \n number of characters are less than 8 ";
}
else if(counter >=51 ) {
cout<<"\n the elements are greater than 50 ";
}
}
int main()
{
cout<<" \n \n enter a email address ";
check_mail();
return 0;
}
Produces expected output for input "Foo#bar.com":
enter a email address
enter an email address ::
found the # character at :: 0
valid number of characters are present in the mail ::
I suppose for the last output you also wanted to add email.size() to the output.
You consider using Regex for check email:
// C++ program for the above approach
#include <iostream>
#include <regex>
using namespace std;
// Function to check the email id
// is valid or not
bool isValid(const string& email)
{
// Regular expression definition
const regex pattern(
"(\\w+)(\\.|_)?(\\w*)#(\\w+)(\\.(\\w+))+");
// Match the string pattern
// with regular expression
return regex_match(email, pattern);
}
// Driver Code
int main()
{
// Given string email
string email = "mail#gmail.com";
// Function Call
bool ans = isValid(email);
// Print the result
if (ans) {
cout << email << " : "
<< "valid" << endl;
}
else {
cout << email << " : "
<< "invalid" << endl;
}
}

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);
}

Why isn't the program outputting true regardless of case?

My assignments requires me to keep accepting input from the user and output whether or not it is a palindrome until the word DONE is inputed.
Also, words like Bob must have an output of true because we must disregard case (upper/lower.)
This is my first time using C++.
#include <iostream>
#include <string>
using namespace std;
int main()
{
string wordInput;
while (wordInput != "DONE")
{
cout << "Please enter a word: ";
cin >> wordInput;
int wordLength = wordInput.length();
int wordHalf = (wordLength / 2);
bool flag = false;
for (int i = 0; i <wordHalf; i++)
{
if (tolower((wordInput[i]) == tolower(wordInput[wordLength-1-i])))
{
flag = true;
}
else
{
flag = false;
break;
}
}
if (flag == true)
{
cout << "true"<<endl;
}
else
{
cout << "false"<<endl;
}
}
return 0;
}
It might have something to do with 'wordInput' being declared twice, once right before the while loop and once within it. It is mixing up what the while loops condition is looking at.
Your issue with words not being correctly identified comes from this line:
if(tolower((wordInput[i]) == tolower(wordInput[wordLength-1-i])))
If you look carefully, you set the parentheses incorrectly. Try this instead:
if(tolower(wordInput[i]) == tolower(wordInput[wordLength-1-i]))

Validating User String User Input

So I've been trying to create this program that will take up to 12 digits from the user using string and string classes. The issue I'm having is:
Ignoring the (-) sign.
Ignoring the decimal point.
Giving an error when more than 12 digits are entered.
Only accepting digits (i.e no letters)
So far this is what I have:
#include <iostream>
#include <string>
#include <cctype>
#include <iomanip>
using namespace std;
bool test(char [] , int);
int main()
{
const int SIZE= 13;
char number[SIZE];
int count;
cout<< "Please enter a number up to "<< (SIZE-1) <<" digits long." << endl;
cout<< "The number may be positive or negative" << endl;
cout<< "and may include fractions (up to two decimal positions)" << endl;
cout<< "Sign and decimal dot(.) are not included in the digit count:"<< "\t";
cin.getline (number, SIZE);
if (test(number, SIZE))
{
while (number[count]!='\0')
{
cout<< "The currency value is: \t $";
cout<< setprecision(2) << number[count];
count++;
}
}
else
{
cout << "Invalid number: contains non-numeric digits.";
}
return 0;
}
bool test(char testNum[], int size)
{
int count;
for (count = 0; count< size; count++)
{
if(!isdigit(testNum[count]))
return false;
}
return true;
}
Any help is very much appreciated, but the most important to me at the moment is the 4th point. No matter what the input is, the output is "Invalid number:...." and I'm not sure why that is.
Your test function always test 13 chars even if the input is shorter.
Instead pass a string and use the range based for-loop so that you only test the valid chars - something like:
bool test(string testNum)
{
for (auto c : testNum)
{
if(!isdigit(c))
return false;
}
return true;
}
Further you should change your main-loop (where you print the value) as well, i.e. use string instead of char-array.
BTW - notice that this will only check for digits. Your description of the valid input format will require a more complex test-function.
For instance to check for sign you could add:
bool test(string testNum)
{
bool signAllowed = true;
for (auto c : testNum)
{
if (c == '-')
{
if (!signAllowed) return false;
}
else
{
if(!isdigit(c)) return false;
}
// Sign not allowed any more
signAllowed = false;
}
return true;
}
But you still need more code to check for the dot (.)
If you don't want to use a range-based for loop, you can do:
bool test(string testNum)
{
for (int i = 0; i < testNum.size(); i++)
{
if (testNum[i] == '-')
{
// Sign is only allowed as first char
if (i != 0) return false;
}
else
{
if(!isdigit(testNum[i])) return false;
}
}
return true;
}

Distinguishing between an int and a double

I've searched for this answer, and no one seems to know how to fix this error. I want the input to be strictly an int. If the input is a double, I want it to send an error.
int creatLegs = 0;
string trash;
bool validLegs = true;
do
{
cout << "How many legs should the creature have? ";
cin >> creatLegs;
if(cin.fail())
{
cin.clear();
cin >> trash; //sets to string, so that cin.ignore() ignores the whole string.
cin.ignore(); //only ignores one character
validLegs = false;
}
if (creatLegs > 0)
{
validLegs = true;
}
if (!validLegs)
{
cout << "Invalid value, try again.\n";
}
} while (!validLegs);
It seems to almost work. It sends the error, but only after moving onto the next loop. How can I fix this? And why is it still showing the error message but still moving on before showing it?
An input can be something else than a representation of an integer or of a floating point number.
Remember that numbers are not their representation(s): 9 (decimal), 017 (octal, à la C), 0b1001 (binary, à la Ocaml), IX (Roman notation), 8+1 (arithmetic expression), neuf (French) are all representations of the same number nine.
So you have to decide if you accept an input like 9 x, or 9 (with several spaces after the digit), ... More generally you have to define what are the acceptable inputs (and if the input is ending at end of line or not, if spaces or punctuation should be accepted, etc...).
You could read an entire line (e.g. with std::getline) and use e.g. sscanf (where the %n control format is useful, and so is the item count returned by sscanf) or std::stol (where you use the end pointer) to parse it
Notice also that the phrasing of your question ("Distinguishing between an int and a double") is wrong. There is no single "int or double" type in C++ (but int is a scalar type, and double is a scalar type in C++, and you could define a class with a tagged union to hold either of them). AFAIU, if you declare int x; then use std::cin >> x; with the user inputting 12.64 the dot and the digits 64 after it won't be parsed and x would become 12.
I think that you should read data as string, and then check it char by char to verify that it is integer - if every char is a digit, then we have integer and we can parse it.
Problem with streams is, that if you're trying to read integer but decimal is passed, it reads the number up to the dot. And this part is a proper integer, so cin.fail() returns false.
Sample code:
#include <iostream>
#include <string>
#include <cctype>
#include <cstdlib>
using namespace std;
int main() {
int creatLegs = 0;
bool validLegs = true;
do
{
cout << "How many legs should the creature have? ";
string input;
getline(cin, input);
validLegs = true;
for (string::const_iterator i = input.begin(); validLegs && i != input.end(); ++i) {
if (!isdigit(*i)) {
validLegs = false;
}
}
if (!validLegs)
{
cout << "Invalid value, try again.\n";
} else {
creatLegs = atoi(input.c_str());
}
} while (!validLegs);
cout << creatLegs << endl;
}
This of course is not a perfect solution. If there any leading or trailing spaces (or any other characters like + or -), the program will fail. But you always can add some code to handle those situations, if you need to.
int creatLegs = 0;
do
{
cout << "How many legs should the creature have? ";
cin >> creatLegs; // trying to get integer
if(!cin.fail()) // if cin.fail == false, then we got an int and leave loop
break;
cout << "Invalid value, try again.\n"; // else show err msg and try once more
cin.clear();
} while (1);
This question already has an accepted answer, however I'll contribute a solution that handles all numbers that are integral, even those that are expressed as a floating point number (with no fractional part) and rejects input that contains anything other than spaces following the number.
Examples of accepted values, these all represent the number 4:
4
4.
4.0
+4
004.0
400e-2
Examples of rejected values:
3.999999
4.000001
40e-1x
4,
#include <iostream>
#include <sstream>
#include <cctype>
#include <string>
using namespace std;
bool get_int( const string & input, int & i ) {
stringstream ss(input);
double d;
bool isValid = ss >> d;
if (isValid) {
char c;
while( isValid && ss >> c ) isValid = isspace(c);
if (isValid) {
i = static_cast<int>(d);
isValid = (d == static_cast<double>(i));
}
}
return isValid;
}
int main( int argc, char *argv[] )
{
int creatLegs = 0;
bool validLegs = false;
do
{
string line;
do {
cout << "How many legs should the creature have? ";
} while (not getline (cin,line));
validLegs = get_int( line, creatLegs );
if (creatLegs <= 0)
{
validLegs = false;
}
if (not validLegs)
{
cout << "Invalid value, try again." << endl;
}
} while (not validLegs);
cout << "Got legs! (" << creatLegs << ")" << endl;
return 0;
}
If you want strictly integers (no decimal period and no scientific notation) then use this simpler get_int function:
bool get_int( const string & input, int & i ) {
stringstream ss(input);
bool isValid = ss >> i;
if (isValid) {
char c;
while(isValid && ss >> c) isValid = isspace(c);
}
return isValid;
}