不能正确打印整个阵列

时间:2017-05-20 00:39:49

标签: c arrays string char

这是我的atm机器的代码。它首先要求用户输入卡号,然后是Pin,然后是有效期。

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);

它不需要输入引脚。它只打印出存储在数据数组中的前15个字符。没有其他的。我的代码有什么问题?

3 个答案:

答案 0 :(得分:2)

问题在于此代码段之后

if(i<16)
{
    data[i] = card_number[i];
}

数组data还包含从'\0'和函数card_number

复制的终止零字符printf
printf("data: %s",data);

输出所有字符,直到遇到此终止零,忽略其后的所有其他字符,

另一个问题可能是,如果您为阵列输入了恰好16个字符 card_number然后新行字符仍将在输入缓冲区中。在这种情况下,fgets的第二次调用将只读取此新行字符。在这种情况下,您应该将数组放大一个字符。

你应该写

#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 );

或者,如果您不想从字符串中删除新行字符,则排除这些语句

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 );

此外,无需致电memset。这可以由编译器本身完成。只需声明像

这样的数组
char card_number[16] = { '\0' };

char card_number[17] = { '\0' };
                ^^^^

使用魔术数字是一个坏主意。最好像

这样编写
fgets( card_number, sizeof( card_number ), stdin);

答案 1 :(得分:1)

读取用户输入的数组不足以容纳您放入的数据。每个数组需要一个额外字节来保存终止空字节。

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));

答案 2 :(得分:1)

card_number的最后一个字符始终为char,其值为零('\0') - 这就是fgets()的作用。你的循环将复制该值。 %s格式会在遇到它时停止。

您的代码需要在复制时考虑'\0'(在所有字符串中)的存在,并确保复制最后一个(以避免使用%s的未定义行为)。

如果您希望在用户点击ENTER之前输入完全16个字符,并且数组的长度为16,则需要调用fgets()两次(以获取两个单独的部分中的总输入)或缓冲区需要17个字符或更多。 fgets()不会删除换行符(如果存在),因此您的代码需要处理它。阅读fgets()的文档。