I've been trying to make a username and password interface and I was wondering if it was possible to have an or statement within strcmp
and if I could also use all values of the array within 1 string, Thanks!
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <string.h>
int main(int argc, char *argv[]) {
int u, p;
char Iuser[50],Ipass[50];
char user[3][50] = { "user1", "user2", "user3" };
char pass[3][50] = { "pass1", "pass2", "pass3" };
printf("\n Enter your username:");
gets(Iuser);
u = strcmp(user[0|1|2], Iuser);
if (u == 0) {
printf("\n Enter your password");
scanf("%s", &Ipass);
} else {
printf("\n Invalid Username, Try Again !");
}
}
CodePudding user response:
No, you can't do like that in C.
I'm stealing Aconcagua's comment about what it actually does:
user[0|1|2]
first calculates0|1|2
, then accesses the array. Result of bitwise OR-ing 0, 1 and 2 is 3, though, which already is out of bounds of youruser
array, thus undefined behaviour
So, instead of
u=strcmp(user[0|1|2],Iuser);
if(u==0) {
You should do:
#include <stdbool.h>
bool u = strcmp(user[0], Iuser) == 0 ||
strcmp(user[1], Iuser) == 0 ||
strcmp(user[2], Iuser) == 0;
if(u) {
If the array of users is long or the number of users is not known at compile-time:
bool u = false;
for(int i = 0; i < number_of_users; i) {
if(strcmp(user[i], Iuser) == 0) {
u = true;
break;
}
}
if(u) {
Note: Don't use bitwise OR
, |
, for these comparisons. Using the logical OR
, ||
, enables short-circuit evaluation so that it stops testing as soon as one condition is true
, just like the loop above which break
s out as soon as one condition has been found true
.
CodePudding user response:
strcmp
cannot be used this way: user[0|1|2]
evaluates to user[3]
, which accesses an element of the array beyond the end of the array: strcmp()
will have undefined behavior when it reads from this place.
The C library does not have a generic function to locate a string in an array, so you should write:
u = strcmp(user[0], Iuser) && strcmp(user[1], Iuser) && strcmp(user[2], Iuser);
Which is quite verbose and specific.
Note that you should always ask for a password to avoid giving information about user names to an intruder, so the code should be modified as:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[]) {
char Iuser[50];
char Ipass[50];
char user[3][50] = { "user1", "user2", "user3" };
char pass[3][50] = { "pass1", "pass2", "pass3" };
int nusers = sizeof(user) / sizeof(user[0]); // number of users
int u;
for (;;) {
printf("\n Enter your username:");
if (scanf("Is", Iuser) != 1)
return 1;
printf("\n Enter your password");
if (scanf("Is", Ipass) != 1)
return 1;
for (u = 0; u < nusers; u ) {
if (strcmp(user[u], Iuser) == 0 && strcmp(pass[u], Ipass) == 0)
break;
}
if (u < nusers)
break;
printf("\n Invalid Username and/or password, Try Again !");
}
// user has been authenticated.
// ...
return 0;
}
Note also that password should be read without echoing the characters to the terminal, which is tricky but can be achieved on unix systems via getpass
:
#include <pwd.h>
#include <unistd.h>
char *getpass(const char *prompt);
Passwords should not be stored in clear text as you do, nor as encrypted text because they would be too easy to find. Computing a cryptographic hash is recommended, in addition to more advanced techniques.
CodePudding user response:
You should do
u=strcmp(user[0],Iuser)!=0 && strcmp(user[1], Iuser)!=0 && strcmp(user[2],Iuser)!=0;
if(u==0) {
//User exists so ask password
because strcmp accepts only two strings to compare. If you do a OR as u said it would be something strange like bitwise operation inside char arrays, I doubt it would ever compile and we don't want to do that.
Have a good day.