C Program about Password Validation not working - c

I wrote a program which is supposed to check if an entered password has an uppercase letter , a lowercase letter and a number. It won't return anything if the password is valid and if the password is invalid it should say "Not a valid password!". But this program doesn't work and I don't understand why.
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <math.h>
int main()
{
char pass[20];
int a, i=0;
printf("Enter your password. It must contain an uppercase and a lowercase letter with a number. Password should be less than 19 characters.\n ");
scanf(" %s", pass);
a = strlen(pass);
/* Checking if an uppercase letter is present*/
for(i=0; i<a ; i++)
{
if(!isupper(pass[i] && i!=(a-1)))
{
continue;
}
else if (!isupper(pass[i]))
{
printf("Not a valid Password!");
}
else
{
break;
}
}
/* Checking if a lowercase letter is present */
for(i=0; i<a ; i++)
{
if(!islower(pass[i] && i!=(a-1)))
{
continue;
}
else if (!islower(pass[i]))
{
printf("Not a valid Password!");
}
else
{
break;
}
}
/* Checking if a number is present*/
for(i=0; i<a ; i++)
{
if(!isdigit(pass[i] && i!=(a-1)))
{
continue;
}
else if (!isdigit(pass[i]))
{
printf("Not a valid Password!");
}
else
{
break;
}
}
}

It looks like you have copied the code of the loop that checks uppercase, and used it in the other loops. The else if part in each loop contains the exact same condition.
A better way to do this would be using three flags:
int lower_flag = 0, upper_flag = 0, digit_flag = 0;
for(i=0 ; i<a ; i++) {
if(isupper(pass[i])) upper_flag=1;
else if(islower(pass[i])) lower_flag=1;
else if(isdigit(pass[i])) digit_flag=1;
}
if(upper_flag && lower_flag && digit_flag)
printf("Valid");
else
printf("Invalid");

You don't need 3 loops to check the valid password in your case.
You can do as below with one loop. All you need is 3 bool variables to mark upper,lower & digits presence in your password.
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <math.h>
#include<stdbool.h>
int main()
{
char pass[20];
int a, i=0;
bool upperPresent = false,lowerPresent = false,digitPresent = false;
printf("Enter your password. It must contain an uppercase and a lowercase letter with a number. Password should be less than 19 characters.\n ");
scanf(" %s", pass);
a = strlen(pass);
/* Checking if an uppercase letter is present*/
for(i=0; i<a ; i++){
if(isupper(pass[i])){
upperPresent = true;
}
else if (islower(pass[i])){
lowerPresent = true;
}else if (isdigit(pass[i])){
digitPresent = true;
}
}
if (upperPresent && lowerPresent && digitPresent)
printf("Valid password\n");
else
printf("invalid Password\n");
}

Why don't you add a bool that is triggered if you find an upper or a lower or a number and then exit out of the loop, because right now you are just traversing the whole string. Also you are checking for an upper in the third loop again.

Related

Do while loop continuing to loop after correct input from user

My program is continuing a loop instead of breaking out of it.
After entering the incorrect password, the program will ask the user to re-enter the password (as it should). Although, if the user enters the password correctly, after previously entering the incorrect password, the program will continue to ask them to re-enter the password when it should break out of the loop.
My program will execute if the user enters the correct password on first attempt, although it makes the user click the enter key twice instead of once.
I can't figure out what is wrong. Any help is appreciated.
#define ENTER 13
#define TAB 9
#define BKSP 8
#define SPACE 32
#define PASSWORD "HelloWorld"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(){
char password[100];
char ch;
int i = 0;
do {
printf("\n\n\t\t\t\t\tPlease enter your password: ");
while (1) {
ch = getch();
if (ch == ENTER) {
password[i] = '\0';
break;
}
else if (ch == BKSP) {
if (i > 0) {
i--;
printf("\b \b");
}
}
else if (ch == TAB || ch == SPACE) {
continue;
}
else {
password[i] = ch;
i++;
printf("*");
}
}
} while((strcmp(password, PASSWORD) != 0));
return 0;
}
The minimal fix would be to move the int i = 0; into the do {} loop so it's reset each each wrong password:
do {
int i = 0;
printf("\n\n\t\t\t\t\tPlease enter your password: ");
As you rely on a fixed sized buffer, you should also check that i < 100. For example:
#define PASSWORD_MAX_LEN 99
char password[PASSWORD_MAX_LEN + 1];
...
while(i < PASSWORD__MAX_LEN) {
ch = getch();
if (ch == ENTER) {
break;
}
...
}
password[i] = '\0';
...

C Program to Check for Palindrome String

I wrote two sample programs to check for a palindrome string. But in both I am getting output like, its not a palindrome number. What I am missing?
I strictly assume somehow code is executing my if statement and put flag in to 1. May be because of that length calculation. Anyone has a better idea?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h>
int main(void) {
setbuf(stdout,NULL);
char name[100];
int i,length,flag=0,k;
printf("Enter your name");
/*scanf("%s",name);*/
gets(name);
length=strlen(name);
for(i=0;i<=length-1;i++)
{
for(k=length-1;k>=0;k--)
{
if(name[i]!=name[k])
{
flag=1;
break;
}
}
}
if(flag==0)
{
printf("Give word is a palindrome");
}
if(flag==1)
{
printf("This is NOT a palindrome word");
}
return 0;
}
and
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h>
int main(void) {
setbuf(stdout,NULL);
char name[100];
int i,length,flag=0;
printf("Enter your name");
/*scanf("%s",name);*/
gets(name);
length=strlen(name);
for(i=0;i<=length/2;i++)
{
if(name[i]!=name[length-1])
{
flag=1;
}
}
if(flag==0)
{
printf("Give word is a palindrome");
}
if(flag==1)
{
printf("This is NOT a palindrome word");
}
return 0;
}
First Algorithm
The algorithm you are using in the first program involves comparing each letter to every other letter which does not help in determining if the number is a palindrome and it does not seem fixable.
Second Algorithm
The problem with the second approach, however, is you are always comparing name[i] to name[length]. Instead change it to length-i-1. This will start comparing from length-1 and decrement the length of the character by 1 for every next iteration:
for(i = 0;i <= length / 2;i++)
{
if(name[i] != name[length-i-1])
{
flag=1;
break;
}
}
gets() and buffer overflow
Do not use gets. This method is susceptible to a buffer overflow. If you enter a string longer than 100 characters, it will result in undefined behavior. Use fgets instead for deterministic behavior:
fgets(name, sizeof(name), stdin);
This takes in the size of the buffer and only reads up to sizeof(name) characters.
Full code
Ideally, you should consider wrapping the logic to check if the string is a palindrome in a function:
int is_palindrome(char*);
int main(void)
{
char name[100];
setbuf(stdout,NULL);
printf("Enter your name");
fgets(name, sizeof(name), stdin);
if(is_palindrome(name))
{
printf("The given word is a palindrome");
}
else
{
printf("This is NOT a palindrome word");
}
return 0;
}
int is_palindrome(char* name)
{
int length = strlen(name);
int flag = 0, i;
for(i = 0;i <= length / 2; i++)
{
if(name[i]!=name[length-i-1])
{
return 0;
}
}
return 1;
}
There is plenty wrong with both your attempts. I strongly suggest using a debugger to investigate how your code works (or doesn't).
Your first attempt performs length2 (incorrect) comparisons, when clearly only length / 2 comparisons are required. The second performs length / 2 comparisons but the comparison is incorrect:
name[i] != name[length-1] ;
should be:
name[i] != name[length - i - 1] ;
Finally you iterate exhaustively when you could terminate the comparison as soon as you know they are not palindromic (on first mismatch).
There may be other errors - to be honest I did not look further than the obvious, because there is a better solution.
Suggest:
#include <stdbool.h>
#include <string.h>
bool isPalindrome( const char* str )
{
bool is_palindrome = true ;
size_t rev = strlen( str ) - 1 ;
size_t fwd = 0 ;
while( is_palindrome && fwd < rev )
{
is_palindrome = (str[fwd] == str[rev]) ;
fwd++ ;
rev-- ;
}
return is_palindrome ;
}
In use:
int main()
{
const char* test[] = { "xyyx", "xyayx", "xyxy", "xyaxy" } ;
for( size_t t = 0; t < sizeof(test)/sizeof(*test); t++ )
{
printf("%s : %s palindrome\n", test[t],
isPalindrome( test[t] ) ? "Is" : "Is not" ) ;
}
return 0;
}
Output:
xyyx : Is palindrome
xyayx : Is palindrome
xyxy : Is not palindrome
xyaxy : Is not palindrome
Try this
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
char text[100];
int begin, middle, end, length = 0;
printf("enter the name: ");
scanf("%s",text);
while ( text[length] != '\0' ){
length++;}
end = length - 1;
middle = length/2;
for ( begin = 0 ; begin < middle ; begin++ ) {
if ( text[begin] != text[end] ) {
printf("Not a palindrome.\n");
break;
}
end--;
}
if( begin == middle )
printf("Palindrome.\n");
return 0;
}
The problem with the first piece of code is you are comparing it more than required, compare it with length-i-1.
The main problem with the second code is you are comparing it with only the last letter of a word.
Hope you understood your mistake

Whenever i run the following code i get 'great password' as output irrespective of the input

This program asks the user for a password. It requires to test whether their password has an uppercase letter, lowercase letter, and a digit. If it does, the program says the great password. If not, it says choose another password.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
int main(void) {
// This part takes input from the user
int i;
int hasupper, haslower, hasdigit;
char password[20];
printf("eneter a password not more then eight characters long: \n");
scanf("%s", password);
// This part executes the loop to check the elements of the input.
for (i = 0; i < strlen(password); i++) {
if (isupper(password[i])) {
hasupper = 1;
continue;
}
if (islower(password[i])) {
haslower = 1;
continue;
}
if (isdigit(password[i])) {
hasdigit = 1;
}
}
// This part shows the outcome
if ((hasdigit) && (haslower) && (hasupper)) {
printf("great password\n");
} else {
printf("choose another password please\n");
}
}
Now, whenever I run my program I see great password on the screen as output for whatever input I give.
Your helper variables are uninitialized and therefore untrustworthy (besides causing UB)
// int hasupper, haslower, hasdigit;
int hasupper = 0, haslower = 0, hasdigit = 0;

How can I monitor user input with getchar

I need to get a user input and check if it is a valid input.
The input must:
Start with space(may be multiple) or a number.
(Assuming condition one satisfied) After the number there may be any kind of characters as long as I manage to extract the number
Clarification for number valid values:
Can be multiple digit
Can't be negative number
Can't contain decimal point
Can't be scientific notation
Can't be hexadecimal
So I wrote this basic code which simply gets the input but I have no clue on where to start on applying these conditions
printf("Enter size of input:\n");
int c;
while((c=getchar())!='\n' && c!=EOF){
printf("%c",c);
}
For example :
Input - 4##2311413sadokalda ; expected output - 4
Input - !4a ; expected output - Invalid Size
You can have state machine as below.
printf("Enter size of input:\n");
int c;
int state = 0; //0 = space, 1 = number, 2 = number read
int number = 0;
while((c=getchar())!='\n' && c!=EOF){
switch(state)
{
case 0:
if (isdigit(c))
state = 1;
else if (c == ' ')
break;
else
//error
break;
case 1:
if (isdigit(c))
{
number = number*10 + (c-'0');
break;
}
else {
state = 2;
}
case 2:
printf ("%d\n",number);
}
}
You probably want something like this:
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
int main(int argc, char* argv[]) {
printf("Enter size of input:\n");
char input[100];
fgets(input, sizeof input, stdin);
if (!isdigit(input[0]))
{
printf("Invalid Size\n");
}
else
{
int inputsize = strtol(input, NULL, 10);
printf("%d\n", inputsize);
}
}
Based on the problem statement you have given, i think this should give you your desired output
EDITED (After a few clarifications):
int main()
{
int c;
int i=0;
while((c=getchar())!='\n' && c!=EOF)
{
if(isdigit(c) || (char)c==' ') //isdigit() function check if given variable is a digit
{ printf("%c",c);
i+=1;
}
else
{
break;
}
}
if(i==0)
{ printf("Invalid size"); }
}

Why is my password checking code not working correctly? It gives same output regardless of whatsoever input

I made a password checking program which checks for the following criteria:-
Should have atleast
1 uppercase
1 lower case
1 special character
1 number
Should be lesser than 100 characters
and thats it. I have not given any lower limit. And no matter what input I give (correct or incorrect), the program gives me the same or similar output as attached in my screenshot.
For eg:- Pratik10, pratik10, pratikten, pr#tiK10, I get the same output "Password is fine and valid".
Why is my program not checking the defined conditions correctly? It is not even printing the counters of the password correctly.
Following is my code:
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#include <ctype.h>
#include <math.h>
#include <string.h>
int main()
{
char x[100];
int i;
int uc=0;
int lc=0;
int num=0;
int misc=0;
printf("enter your password\n");
scanf("%s",x);
for(i=0;i<100;i++) {
if (isalpha(x[i])) {
if (isupper(x[i])) {
uc++;
}
if (islower(x[i])) {
lc++;
}
}
if (isdigit(x[i])) {
num++;
}
else {
misc++;
}
}
printf("checking your password\n");
printf("%d uc\n",uc);
printf("%d lc\n",lc);
printf("%d num\n",num);
printf("%d misc\n",misc);
if ((uc > 0) && (lc > 0) && (num > 0) && (misc > 0)) {
printf("password is fine and valid\n");
}
else {
if(lc<=0) {
printf("lowercase character(s) missing cannot proceed without inclusion\n");
}
if(uc<=0) {
printf("uppercase character(s) missing cannot proceed without inclusion\n");
}
if(num<=0) {
printf("number(s) missing cannot proceed without inclusion\n");
}
if(misc<=0) {
printf("special character(s) missing cannot proceed without inclusion\n");
}
printf("please include all the missing parameters in combination to validate the password and try again\n\n");
}
return 0;
}
How to correct this?
Output:
The problem is that you are checking the whole array, which is mostly uninitialized and contains all kind of characters at random.
Therefore, you have to exit the loop when you encounter a '\0' character.
You should check only the null-terminated string provided as input by the user.
In other words, you should iterate x until you encounter the null-character.
Change this:
for (i = 0; i < 100; i++)
To this:
for (i = 0; x[i] != 0; i++)
A second problem is that you are not using if/else properly.
As a result, every character which is not a digit is counted as misc.
Change this:
if (isdigit(x[i]))
To this:
else if (isdigit(x[i]))
Other answers have mentioned the main problem. There is still one more problem: There is a missing else before if (isdigit(x[i])) {num++;},
for(i=0; x[i]!=0; i++)
{
if (isalpha(x[i]))
{
if (isupper(x[i])) {uc++;}
if (islower(x[i])) {lc++;}
}
else if (isdigit(x[i])) {num++;} // a missing else
else {misc++;}
}

Resources