2017-05-20 6 views
2

これはatmマシンのコードです。まず、ユーザーにカード番号を入力して、ピンと有効期限を尋ねます。アレイ全体が正しく印刷されません。

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]; 
} 

後アレイdatacard_numberからコピーされた終端ゼロ文字'\0'及び機能printf

printf("data: %s",data); 

これまでのすべての文字を出力にも含まれていることですそれ以降の文字を無視してゼロを終了すると、

もう1つの問題は、配列に正確に16文字を入力した場合、新しい行の文字は入力バッファに残ります。 card_numberこの場合、fgetsの2番目の呼び出しでは、この新しい改行文字のみが読み取られます。この場合、配列を1文字ずつ拡大する必要があります。

代わり

#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'これを使用すると、同じ名前の配列を2回宣言していませんか? –

+0

@UmairJavaid配列宣言はありません。関数strcspnは、実際には、改行文字がある配列内の位置を見つけ、値 '\ 0'の代わりになる配列の要素のインデックスとして使用されます。 –

+0

よろしいですか?私の悪い。手伝ってくれてどうもありがとう –

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

card_numberの最後の文字は常に値ゼロ('\0')とcharになります - それはfgets()が何をするかです。あなたのループはその値をコピーします。 %s形式は、それが検出されると停止します。

コピーするときに'\0'(すべての文字列内)の存在を考慮し、最後のコピーが確実にコピーされるようにする必要があります(%sで未定義の動作を避けるため)。

ユーザー・ヒットが入る前に入力する正確16文字を期待している、と配列の長さは16あり、その後、fgets()ニーズ回呼び出される(二つの別々の部分で全入力を取得するため)またはバッファのいずれかの場合17文字以上である必要があります。 fgets()あなたのコードがそれに対処する必要があるように改行(もしあれば)は削除されません。 fgets()のドキュメントをお読みください。

+0

のように書く方が良いです。ピンの入力も尋ねません。有効期限の入力を求めるために直接ジャンプします。そして、私はcard_numberを17に、17に、exp_dateを6に変更しました。それはまだ正しく動作していません。 –

+0

それでは、ゼロまたは改行文字の存在を正しく扱っていません(返信の最初の2つのparasに従って)。 – Peter

関連する問題