2017-05-20 107 views
2

這是我的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

的問題是,此代碼後片斷

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

card_number [strcspn(card_number,「\ n」)] ='\ 0'如果我使用這個,是不是我聲明瞭兩次具有相同名稱的數組? –

+0

@UmairJavaid沒有數組聲明。函數strcspn實際上在數組中找到了新行字符所在的位置,並將其用作將替換值'\ 0'的數組元素的索引。 –

+0

哦,好的。我的錯。非常感謝你的幫助 –

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

card_number的最後一個字符將永遠是一個char值爲零('\0') - 這就是fgets()一樣。您的循環將複製該值。當遇到它時,%s格式將停止。

複製時,您的代碼需要考慮'\0'(在所有字符串中)的存在,並確保複製最後一個(以避免與%s發生未定義的行爲)。

如果期待完全相同16字符將被輸入的用戶點擊回車之前,並且陣列的長度16,可稱之爲然後要麼fgets()需要兩次(以獲得在兩個獨立的部分的總輸入)或緩衝需要是17個字符以上。 fgets()不會刪除換行符(如果存在),因此您的代碼需要處理它。閱讀fgets()的文檔。

+0

它也不會詢問pin的輸入。它直接跳轉以詢問輸入的到期日期。我將card_number更改爲17,將引腳更改爲17,將exp_date更改爲6.它仍然無法正常工作。 –

+0

然後你仍然沒有正確處理零或換行符的存在(按照我的回覆的前兩個部分)。 – Peter