Home > Software design >  Using OR in statements with arrays, (C)
Using OR in statements with arrays, (C)

Time:06-14

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 calculates 0|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 your user 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 breaks 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.

  • Related