Reputation:
Here is my code for an atm machine. It first asks the user for card number then Pin and then expiry date.
char card_number[16];
memset(card_number,0,16);
char pin[4];
memset(pin,0,4);
char exp_date[5];
memset(exp_date,0,5);
printf("Enter Card number \n");
//scanf ("%s",&card_number);
fgets (card_number, 16, stdin);
printf("Enter pin\n");
//scanf ("%s",&pin);
fgets (pin, 4, stdin);
printf("Enter expiry date\n");
//scanf ("%s",&exp_date);
fgets (exp_date, 5, stdin);
char data[25];
memset(data,0,25);
char reply[25];
memset(reply,0,25);
int i = 0;
for(i=0;i<25;i++)
{
if(i<16)
{
data[i] = card_number[i];
}
if(i>=16 && i<20)
{
data[i] = pin[i-16];
}
if(i>=20 && i<25)
{
data[i] = exp_date[i-20];
}
}
printf("data: %s",data);
It doesn't takes the input for pin. It just prints out the first 15 char stored in data array. Nothing else. What is the problem in my code?
Upvotes: 2
Views: 78
Reputation: 311126
The problem is that after this code snippet
if(i<16)
{
data[i] = card_number[i];
}
the array data
contains also the terminating zero character '\0'
that was copied from card_number
and the function printf
printf("data: %s",data);
outputs all characters until this terminating zero is encountered ignoring all other character after it,
Another problem can be that if you entered exactly 16 characters for the array
card_number
then the new line character will be still in the input buffer. In this case the second call of the fgets
will read only this new line character. In this case you should enlarge the arrays by one character.
You should write instead
#include <string.h>
//...
card_number[ strcspn( card_number, "\n" ) ] = '\0';
pin[ strcspn( pin, "\n" ) ] = '\0';
exp_date[ strcspn( exp_date, "\n" ) ] = '\0';
strcpy( data, card_number );
strcat( data, pin );
strcat( data, exp_date );
Or if you do not want to remove the new line character from the strings then exclude these statements
card_number[ strcspn( card_number, "\n" ) ] = '\0';
pin[ strcspn( pin, "\n" ) ] = '\0';
exp_date[ strcspn( exp_date, "\n" ) ] = '\0';
and use only
strcpy( data, card_number );
strcat( data, pin );
strcat( data, exp_date );
Also there is no need to call memset
. This can be done by the compiler itself. Just declare the arrays like
char card_number[16] = { '\0' };
or
char card_number[17] = { '\0' };
^^^^
And it is a bad idea to use magic numbers. It is better to write for example like
fgets( card_number, sizeof( card_number ), stdin);
Upvotes: 2
Reputation: 36637
The last character of card_number
will always be a char
with value zero ('\0'
) - that's what fgets()
does. Your loop will copy that value over. The %s
format will stop when it encounters it.
Your code needs to account for the presence of the '\0'
(in all the strings) when copying, and ensure the last one is copied (to avoid undefined behaviour with %s
).
If you are expecting exactly 16
characters to be input before the user hits ENTER, and the array is 16
in length, then either fgets()
needs to be called twice (to get the total input in two separate pieces) or the buffer needs to be 17
characters or more. fgets()
does not remove the newline (if present) so your code needs to deal with it. Read the documentation for fgets()
.
Upvotes: 1
Reputation: 225697
Your arrays that read user input are not large enough to hold the data you're putting in. You need one extra byte for each one to hold the terminating null byte.
char card_number[17];
memset(card_number,0,sizeof(card_number));
char pin[5];
memset(pin,0,sizeof(pin));
char exp_date[6];
memset(exp_date,0,sizeof(exp_date));
Upvotes: 1