unexpected infinite loop in c++ - c++

I'm working in a project and the task is to make the signup function
so when I try several test cases in password function I got stuck in an infinite loop when I try to type an invalid password without giving me a chance to retype the password.
Thanks in advance...
#include <iostream>
#include <string>
#include <cstring>
#include <conio.h>
#include <stdio.h>
using namespace std;
#define size 40
int main(){
bool flag = true;
while (flag){
bool flagS = false, flagN = false; int count = 0;
char password[size] = { 0 };
cout << "Type your Password .....\n Note :: Must be more than 8 characters including at least one number and one special character...\n";
cin.get(password, size);
count = strlen(password);
for (int z = 0; z < count; z++){
if (password[z] >= 48 && password[z] <= 57)
flagN = 1;
if ((password[z] >= 33 && password[z] <= 47) || (password[z] >= 58 && password[z] <= 64))
flagS = 1;
}
if ((flagS == 1) && (flagN == 1) && (count >= 8))
{
cout << "Valide Password ...\nCongrats!! ..you created a NEW account.." << endl;
flag = false;
}
else
{
cout << "invalide password..\nPlease try again..\n";
flag = true;
}
}
}

You must write cin inside of while loop. And this will fix your problem:
#include <iostream>
#include <cstring>
#include <stdio.h>
using namespace std;
#define size 40
int main(){
bool flag = true;
bool flagS = false, flagN = false; int count = 0;
char password[size] = { 0 };
cout << "Type your Password .....\n Note :: Must be more than 8 characters including at least one number and one special character...\n";
while (cin >> password && flag){
count = strlen(password);
for (int z = 0; z < count; z++){
if (password[z] >= 48 && password[z] <= 57)
flagN = true;
if ((password[z] >= 33 && password[z] <= 47) || (password[z] >= 58 && password[z] <= 64))
flagS = true;
}
if ((flagS) && (flagN) && (count >= 8))
{
cout << "Valide Password ...\nCongrats!! ..you created a NEW account.." << endl;
flag = false;
}
else
{
cout << "invalide password..\nPlease try again..\n" << "Type your Password .....\n Note :: Must be more than 8 characters including at least one number and one special character...\n";;
flag = true;
}
}
}

std::istream::get does not remove the newline from the stream. This means the next call to std::istream::get immediately finds the newline and reads nothing into the buffer, sets the failbit, and returns. Because the steream is now in the fail state all subsequent reads instantly fail. You could cin.ignore() the newline, but a more direct approach is to use std::istream::getline because it removes the newline for you.
Always test the stream state after an IO transaction to make sure it succeeded.
Side note:
Prefer to use std::string and std::getline to raw character arrays and functions that use them. std::istream::get and std::istream::getline both mark the stream as failed if the buffer provided is too small. The string provided to std::getline will be resized, so as long as you have dynamic storage remaining, buffer over runs and the errors raised to prevent them are a non-problem. If the system cannot allocate a buffer of sufficient size for the string an exception is thrown to make you aware of the problem.
Prefer to use letters, for example 'A' to a raw ASCII code. For one thing the intent of 'A" is immediately recognizable to even the most raw of programmers and there is always the possibility that the implementation does not use ASCII as the default encoding.

Related

C++ Code keeps crashing after a validation

I have written a piece of code to validate a keyword, it validates and makes sure that the word is 5 letters long and it is all letters with no numbers in it. However, when I run it, the code seems to stop working at all and doesn't prompt me for the next question, I've tested it without this code and this part of the code is the problem, as it works fine without it.
The code:
cout<<name1<<", please enter the keyword (5 characters): "<<endl;
cin>>key;
for(int i = 0; i < keylength; i++){
if(isalpha(key[i]) == 1){
validnum += 1;
}
}
if(validnum == keylength && key.length() == keylength){
validated = true;
}
else{
validated = false;
}
As mentioned in the comments, there is no need for any loops to determine if the key is 5 characters and is all alphabetic.
Using std::all_of will test if all the characters are alphabetic:
#include <algorithm>
#include <string>
#include <cctype>
#include <iostream>
bool isValidData(const std::string& key)
{
return key.size() == 5 && std::all_of(key.begin(), key.end(), ::isalpha);
}
int main()
{
//Test data
std::string testKeys[] = {"1abcdef", "abcde", "abcdefghijkl", "a", "xyzab"};
for (size_t i = 0; i < std::size(testKeys); ++i)
{
// Output results
std::cout << testKeys[i] << " " << (isValidData(testKeys[i])?"OK":"BAD") << "\n";
}
}
Output:
1abcdef BAD
abcde OK
abcdefghijkl BAD
a BAD
xyzab OK
Also, if you took a look at your code, it is not clear what the goal of the code is without running the code. Compare that to the function isValidData: if you say what that function has in it, it reads almost as your description:
"The key size must be 5, and all of the characters must be alpha".
Before the for loop you need to check that key.length() is equal to keyLength. Otherwise the loop can invoke undefined behavior when the user enters a string with the length less than keyLength.
Also the function isalpha does not necessary returns 1. It can return any positive value.
Change your code something like the following
validated = key.length() == keyLength;
if ( validated )
{
size_t i = 0;
while ( i < keyLength && isalpha( ( unsigned char )key[i] ) ) ++i;
validated = i == keyLength;
}

I am currently trying to save a set of integers in a int array, by redefining string into numbers, then store it in the array

I am trying to convert input text/numbers (string), which will include any characters, but I want to separate the numbers from the characters and store them into an integer array, once it is converted from a string.
I believe the problem is where the string is converting to an integer by use of stoi(), but I cannot seem to spot the problem.
Currently, the code accepts any input and turns it into a string, the string is then checked character by character, and all the numbers without separation with comma or space is added together, once a comma or space, or any other character separates the number, the number as a whole is added to the array, and then continues to check the string for more numbers.
Any ideas?
Input Example1: 12, 13, 15
Input Example2: 12 13 15
Input Example3: 12ab13cd15ef
Result in integer array: 0[12] 1[13] 2[15]
These numbers will be used in the specific order, by using the numbers within the array.
#include<iostream>
#include<string>
#include <sstream>
using namespace std;
int main()
{
string datainput, str1, str3;
cin >> datainput;
int n = 0, raycount = 0, c;
int myray[10];
while (datainput[n])
{
if (datainput[n] == ('0') || datainput[n] == ('1') || datainput[n] == ('2') || datainput[n] == ('3') || datainput[n] == ('4') ||
datainput[n] == ('5') || datainput[n] == ('6') || datainput[n] == ('7') || datainput[n] == ('8') || datainput[n] == ('9'))
{
str1 = datainput[n];
str3 += str1;
}
else
{
c= stoi(str3);
c >> myray[raycount];
raycount++;
}
n++;
}
cout << myray[0] << endl;
cout << myray[1] << endl;
cout << myray[2] << endl;
cout << myray[3] << endl;
system("pause");
return 0;
}
I see quite a few issues with your code.
Prior to C++11, while (datainput[n]) has undefined behavior once n reaches the end of the string.
The way you are checking for numeric digits can be greatly simplified using std::isdigit(), or even just a simple range check using the >= and <= operators.
You are not correctly accounting for numbers that are separated by other characters, or when the last number in the string is at the very end of the string.
The statement c >> myray[raycount]; needs to be changed to myray[raycount] = c; instead. And you are not breaking your loop if raycount reaches the max capacity of myray[].
You are not resetting str3 back to an blank string after converting it with std::stoi(). You just keep appending new digits to the end of previous digits with no break in between numbers.
With that said, try something more like this instead:
#include <iostream>
#include <string>
using namespace std;
int main()
{
string datainput, str3;
cin >> datainput;
int myray[10];
int raycount = 0;
bool gettingDigits = false;
for (int n = 0; n < datainput.size(); ++n)
{
char ch = datainput[n];
//if (isdigit(ch))
if (ch >= '0' && ch <= '9')
{
if (!gettingDigits)
{
str3 = "";
gettingDigits = true;
}
str3 += ch;
}
else
{
if (gettingDigits)
{
myray[raycount] = stoi(str3);
raycount++;
str3 = "";
gettingDigits = false;
if (raycount == 10) break;
}
}
}
if (gettingDigits && (raycount < 10))
{
myray[raycount] = stoi(str3);
raycount++;
}
for (int n = 0; n < raycount; ++n)
cout << myray[n] << endl;
system("pause");
return 0;
}
Live Demo
Alternatively:
#include <iostream>
#include <string>
using namespace std;
int main()
{
string datainput, str3;
cin >> datainput;
int myray[10];
int raycount = 0;
string::size_type start = datainput.find_first_of("0123456789");
string::size_type end;
while (start != string::npos)
{
end = datainput.find_first_not_of("0123456789", start+1);
if (end == string::npos)
{
str3 = datainput.substr(start);
myray[raycount] = stoi(str3);
raycount++;
break;
}
str3 = datainput.substr(start, end-start);
myray[raycount] = stoi(str3);
raycount++;
if (raycount == 10) break;
start = datainput.find_first_of("0123456789", end+1);
}
for (int n = 0; n < raycount; ++n)
cout << myray[n] << endl;
system("pause");
return 0;
}
Live Demo
So, you want to segregate numbers and characters into different arrays.
In if block, you are checking for characters, so, I suspect stoi() wouldn't work.
Better typecast it to an integer.
int temp[10];
if (datainput[n] == ('0') || ...) {
temp[n] = int(datainput[n]);
}
This way your temp array would contain the numbers.

Problem with boolean variable in email validation program [duplicate]

This question already has answers here:
What is a debugger and how can it help me diagnose problems?
(2 answers)
Closed 3 years ago.
I am trying to create an email validation program without using the regex library. In one of my functions, I want to return a Boolean to check if there is an # sign in the email address and also if it is in a valid position (the # sign cannot be one of the first three characters of the string). However I am having problems with it because every time I run the program by entering in an email address with the # sign in an invalid position, it keeps telling me that the email is valid. Please help!
valid = checkEmail(email); //function call
if(valid == true)
cout << "Your email is valid!" << endl;
else
cout << "Your email is invalid!" << endl;
bool checkEmail(string email)
{
int counter;
int length;
bool firstThree; //checks to make sure # is not in the first three chars
counter = 0;
length = email.length();
firstThree = false;
for(int i = 0; i < length; i++)
{
if(email[i] == '#')
counter++;
}
for(int y = 0; y < length; y++)
{
if(email[0] == '#' || email[1] == '#' || email[2] == '#')
firstThree = true;
else
firstThree = false;
}
cout << "\n" << counter << endl; //check to see if counter works
if(counter != 1 && firstThree == true)
return false;
else
return true;
}
I guess you need to define the function bool checkEmail(string email) at the begining of the program. Basically flip if else and the function definition.
bool checkEmail(string email)
{
int counter;
int length;
bool firstThree; //checks to make sure # is not in the first three chars
counter = 0;
length = email.length();
firstThree = false;
for(int i = 0; i < length; i++)
{
if(email[i] == '#')
counter++;
}
for(int y = 0; y < length; y++)
{
if(email[0] == '#' || email[1] == '#' || email[2] == '#')
firstThree = true;
else
firstThree = false;
}
valid = checkEmail(email); //function call
if(valid == true)
cout << "Your email is valid!" << endl;
else
cout << "Your email is invalid!" << endl;
There seem to be a lot of beginner mistakes here, so I suggest learning the basics of programming and c++ first and like others suggested, use a debugger. Here are some of the mistakes:
Function definition
c++ is not like other common languages in the sense that functions need to be defined before they can be used. This means that you either need to move your checkEmail function above the function call, or create a separate definition above the function call like:
bool checkemail(string email);
as an exmaple.
Incorrect if-statement logic; Unnecessary for loop:
I'm assuming that based on how emails are formatted, you want the checkEmail function to return false if it doesn't match the correct formatting, and based on what your function currently does, that means that it will return false if the first three characters are # or if there isn't exactly one # symbol in the email. However, you used a && operator, which signifies and, meaning it will return true even when you don't want it to (much like how #Yastanub stated in his first comment). Better yet, that entire logic and if statement can be simplified greatly using std::string::find with a while loop and a vector (similar to this method):
vector<size_t> posVec;
size_t pos = email.find('#', 0); //note that this can be an int instead of size_t, but it can cause stack overflow with bigger numbers
while(pos != string::npos){
posVec.push_back(pos);
pos = email.find('#', pos+1);
}
switch(posVec.size()){
//if there is only one # symbol found
case 1:
bool firstThree = false;
for(int i = 0; i <= 2; i++)
//if there is only one # but it's in the first 3 positions, the email isn't valid
if(posVec[0] == i)
firstThree = true;
return !firstThree;
//otherwise the email doesn't work
default:
return false;
}
Remember to include the required libraries in order for this part to work:
#include <string>
#include <vector>
This also eliminates the second for loop in your function that is useless because the variable y is not being used, and the counter that was being used for testing
Another note
Using if (valid == true) is unnecessary as well. You can just use if (valid) because of how booleans work with if-statements.

Substring is out of range

I am writing up a function that reverses the order of the string "rdd" to "ddr",
when I run it I get an error that substring is out of range. Any help is appreciated!
#include <iostream>
#include <string>
#include <stdio.h>
#include <ctype.h>
using namespace std;
string reverse(const string & s);
int main() {
cout << reverse("rdd") << endl;
}
string reverse(const string & s) {
string rname(s);
for (unsigned i = rname.size()-1; i >= 0; i--) {
cout << rname[i];
}
return rname;
}
This is problem:
for (unsigned i = rname.size()-1; i >= 0; i--) {
Since i is unsigned, i-- will take it from 0 to UINT_MAX. The test i >= 0 can never fail for unsigned int. After this happens you access out of bounds in the loop body.
Instead the loop could look like:
for (unsigned i = rname.size(); i --> 0; )
(using the --> operator), or a better option would be to use C++ idioms:
for (auto it = rname.rbegin(); it != rname.rend(); ++it)
cout << *it;
Also see reverse adapters although that might be overkill for this case.
Your i is unsigned, therefore the condition i >= 0 is always satisfied. Consider:
unsigned int i = 0;
i--; // i will undeflow, and assume the largest unsigned number possible
if(i < 0) printf("Works?"); // suprise! It will be false and printf does not fire!
for (unsigned i = rname.size()-1; i >= 0; i--) {
The problem is in the above statement because -
rname.size() will return length of string. So this loop will run from rname.size()-1to 0(both including) then i-- will be UINT_MAX and condition which is i>=0, will always be true but your string size may less than UINT_MAX so it will return an error which is out of bound error.

c++ binary to decimal converter input to only accept 1 or 0

Hello I am trying to do a programming assignment that converts a binary number to a decimal. The problem states that I have to get the users input as a sting and if there is anything other than a 1 or a 0 in the users input it should give an error message then prompt them to give a new input. I have been trying for a while now and I cant seem to get it right can anyone help me?
so far this is my best attempt it will run every input of the string into a if statement but it only seems to care about the last digit i cant think of a way to make it so if there is a single error it will keep while loop statement as true to keep going.
#include <iostream>
#include <string>
using namespace std;
string a;
int input();
int main()
{
input();
int stop;
cin >> stop;
return 0;
}
int input()
{
int x, count, repeat = 0;
while (repeat == 0)
{
cout << "Enter a string representing a binary number => ";
cin >> a;
count = a.length();
for (x = 0; x < count; x++)
{
if (a[x] >= '0' &&a[x] <= '1')
{
repeat = 1;
}
else
repeat = 0;
}
}
return 0;
}
return 0;
}
Change your for loop as this:
count = a.length();
repeat = 1;
for (x = 0; x < count; x++)
{
if (a[x] != '0' && a[x] != '1')
{
repeat = 0;
break;
}
}
The idea is that repeat is assumed to be 1 at first (so you assume that your input is valid). Later on, if any of your input characters is not a 0 or 1, then you set repeat to 0 and exit the loop (there's no need to keep looking for another character)