Reputation: 679
I'm trying to practice my C programming skills by building a Bank Management program. I start off by making the user create his/her account with the username and password stored in 2 different arrays. I'm having trouble comparing them though. I looked up if there was any library or function that could do the job for me but found nothing. So I decided to build my own header file and include that in my main program. But for some reason, it's returning the wrong values. In my program I ask the user to login to his/her account and want to check to see if the credentials that they inputted matched what they created. I included the header file and was able to execute the function but even though the credentials match, The program still thinks that it's wrong. Here is my main.c code:
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include "comparingArrays.h"
char username[20];
char password[20];
char username_input[20];
char password_input[20];
void create_account(char* usrname, char* passwd) {
printf("==================================CREATE BANK ACCOUNT==================================\n");
while(1) {
printf("Enter a username that is less than 20 characters: ");
scanf("%s", usrname);
if (strlen(usrname) <= 20)
break;
printf("That is not less than 20 characters, try again...\n");
}
while(1) {
printf("Enter a password that is less than 20 characters: ");
scanf("%s", passwd);
if (strlen(passwd) <= 20) {
break;
}
}
printf("Thank you, please sign in now...\n");
sleep(2);
}
void login() {
while(1) {
printf("Enter Username: ");
scanf("%s", username_input);
printf("Enter Password: ");
scanf("%s", password_input);
if (compareStringArr(username, password, 20, 20) != 1) {
printf("Incorrect Username or Password. Try again...\n");
sleep(2);
}
else {
break;
}
}
}
int main(void) {
create_account(username, password);
login();
}
And here is my header file code:
#include <stdio.h>
#include <stdbool.h>
char test_arr1[20] = {'h','e','l','l','o',' ','w','o','r','l','d'};
char test_arr2[20] = {'h','e','l','l','o',' ','w','o','r','l','d'};
bool compareStringArr(char* arr1, char* arr2, int size1, int size2) {
int i, j;
for (i = 0; i < size1; i++) {
for (j = 0; j < size2; j++) {
if (arr1[i] == arr2[j]) {
continue;
}
else {
return false;
}
}
}
return true;
}
The output of this code is shown in the linked photo.
Can someone please help me with this? I'm pretty sure it's a simple fix but I'm still a beginner at C. Thanks!
Upvotes: 0
Views: 892
Reputation: 84642
You have two arrays containing strings -- BUT -- only because C11 Standard - § 6.7.9 Initialization (p21) applied. (... If there are fewer initializers in a brace-enclosed list than there are elements ... all subobjects that are not initialized explicitly shall be initialized implicitly the same as objects that have static storage duration.) Which is initialized to zero.
If you are initializing an array with strings, better to initialize with a String-Literal and let the array be sized to the number of characters in the string, plus the nul-terminating character, e.g.
char test_arr1[] = "hello world";
(much less typing also)
When comparing strings, there is no reason to provide the size
. In C, every string ends with the nul-terminating character '\0'
(which is simply ASCII 0
, so '\0'
and 0
are equivalent in this regard). Since all strings end with the nul-terminating character, you can simply scan forward in the string until the nul-terminating character is reached. That is what strcmp()
does for you and there is no need for a separate function to contain strcmp()
, you can just use it alone, e.g.
if (strcmp (test_arr1, test_arr2) != 0)
puts ("arrays: differ");
else
puts ("arrays: are equal");
Your complete example can reduce to the following using the ternary to handle the result of the comparison:
#include <stdio.h>
#include <string.h>
int main (void) {
char test_arr1[] = "hello world",
test_arr2[] = "hello world";
printf ("arrays: %s\n", strcmp (test_arr1, test_arr2) ? "differ" : "are equal");
}
Example Output
$ ./bin/strcmparr
arrays: are equal
Generic Array Comparison
When comparing any array, regardless whether they contains strings are not, you want to know the number of elements filled, not just how big the array is. You want to compare filled elements. (at the time of comparison, there is know way to know whether a brace or "..."
initializer was used and whether the complete array was initialized). If you attempt to access elements that were not initialized -- you invoke Undefined Behavior (another good reason to always initialize your arrays)
A generic compare array would be:
...
#include <string.h>
...
bool compareArr(char* arr1, char* arr2, size_t nelem1, size_t nelem2)
{
if (nelem1 != nelem2) /* validate sizes are equal */
return false;
/* validate contents are equal */
return memcmp (arr1, arr2, nelem1 * sizeof *arr1) == 0;
}
That does essentially the same thing that strcmp()
does, but for a generic array and it is limited to a true / false
result. The number of filled elements is needed in this case. (both strcmp()
and memcmp()
require string.h
). A short implementation taken from your original code would be:
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
char test_arr1[] = {'h','e','l','l','o',' ','w','o','r','l','d'};
char test_arr2[] = {'h','e','l','l','o',' ','w','o','r','l','d'};
bool compareArr(char* arr1, char* arr2, size_t nelem1, size_t nelem2)
{
if (nelem1 != nelem2) /* validate sizes are equal */
return false;
/* validate contents are equal */
return memcmp (arr1, arr2, nelem1 * sizeof *arr1) == 0;
}
int main (void) {
printf ("arrays: %s\n",
compareArr (test_arr1, test_arr2,
sizeof test_arr1, sizeof test_arr2) ?
"are equal" : "differ");
}
(same output)
Note: when you change the return type of your function to bool
instead of int
, you loose the information that strcmp()
provides related to which element would sort before the other. With bool
the only information your are left with is simply whether the arrays are equal or not. A better alternative may be to simply return int
and return the actual result of strcmp()
or memcmp()
directly.
Look things over and let me know if you have further questions.
Upvotes: 1
Reputation:
By looking at your code, I understand that you want to check whether each element of an array matches with the corresponding element in the second array.
So the way you're going to archieve this is by looping throungh both arrays and checking if the content in the same element number match.
The function compareStringArr()
would be as follows :
bool compareStringArr(char* arr1, char* arr2)
{
bool valid = false ;
int sizeOfArr_1 = strlen(arr1) ; // get the length of the 1st array
int sizeOfArr_2 = strlen(arr2) ; // get the length of the 2nd array
if(sizeOfArr_1 == sizeOfArr_2) // if the arrays are NOT of equal length, obviously they don't match
{
for(int index = 0 ; index < sizeOfArr_1 ; index++)
{
if(arr1[index] == arr2[index])
{
valid = true ;
}
else
{
valid = false ;
break ; // break out of the loop right away when the content of a specific element in arr1[] is not the same as the content in arr2[]
}
}
}
return valid ;
}
In your code, the line where you call compareStringArr()
, you've passed in the wrong parameters. You have got to call the compareStringArr()
twice
If either(i.e, the entered username or entered password) of them don't match, you have got to ask the user to enter again. So the login()
function would be :
void login() {
while(1)
{
printf("Enter Username: ");
scanf("%s", username_input);
printf("Enter Password: ");
scanf("%s", password_input);
// you have got to check whether BOTH, the entered username and entered password, match to the original ones
if(compareStringArr(username_input, username) != true || compareStringArr(password_input, password) != true)
printf("Incorrect Username or Password. Try again...\n") ;
else
break ;
}
}
The same task done in compareStringArr
can be archived by the function strcmp()
function in C. This is mentioned in the previous answer.
#include<stdio.h>
#include<string.h>
int main(int argc, char const *argv[])
{
char arr_1[5] = "Tom" ;
char arr_2[5] = "Tom" ;
int result = strcmp(arr_1, arr_2) ;
printf("%d\n", result);
return 0;
In the code above, the result will be 0. strcomp()
returns a 0 if both strings passed as parameters are identical. A 1 is returned if they don't match.
Upvotes: 0
Reputation: 371
You could update your function to be the following:
#include <stdio.h>
#include <string.h>
char test_arr1[20] = {'h','e','l','l','o',' ','w','o','r','l','d'};
char test_arr2[20] = {'h','e','l','l','o',' ','w','o','r','l','d'};
bool compareStringArr(char* arr1, char* arr2) {
return strcmp(arr1, arr2) == 0;
}
If the strings are equal the strcmp
function returns 0
which is why to get a true/false boolean it is comparing strcmp(...,...) == 0
Also if you want to accept 20 characters input from the user you will need to make your username,password,username_input,password_input
arrays at least a length of 21 (c strings have an extra '\0'
character appended to the end that specifies end of string
Then in your login function you probably want to compare username to username_input and password to password_input
if (compareStringArr(username, username_input) != 1 ||
compareStringArr(password, password_input) != 1) {
printf("Incorrect Username or Password. Try again...\n");
sleep(2);
}
else {
break;
}
Upvotes: 1