ユーザーが1つずつ入力する文字を格納するために使用しているchar配列バッファーがあります。以下の私のコードは機能しますが、理解できないいくつかの不具合があります。
誰かが私に何が起こっているのか、そしておそらく私がこれを修正する方法を説明してもらえますか?ありがとう。
char Buffer[8]; //holds the byte stream
int i=0;
if (/* user input event has occurred */)
{
Buffer[i] = charInput;
i++;
// Display a response to input
printf("Buffer is %s!\n", Buffer);
}
出力:
tagBufferは1┬┬w! tagBufferは12┬w! tagBufferは123w! tagBufferは1234! tagBufferは12345! tagBufferは123456 =! tagBufferは1234567! tagBufferは12345678!
tagBufferは123456789です!
文字列は\ 0文字で終了する必要があります。そのため、これらはゼロ終端文字列と呼ばれます。
\ 0を保持するために1文字余分に割り当てることも賢明です。
Printf()関数に渡すのは、文字列の最初の文字へのポインタだけです。 printf()には、配列のサイズを知る方法がありません。 (ポインタは単なるメモリアドレスであるため、実際の配列であるかどうかさえわかりません。)
printf()およびすべての標準c文字列関数は、文字列の末尾に0があることを前提としています。たとえば、printf()は、関数に渡した文字から始まり、0に達するまで、メモリ内の文字を出力し続けます。
したがって、コードを次のように変更する必要があります。
char Buffer[9]; //holds the byte stream
int i=0;
if( //user input event has occured )
{
Buffer[i] = charInput;
i++;
Buffer[i] = 0; // You can also assign the char '\0' to it to get the same result.
// Display a response to input
printf("Buffer is %s!\n", Buffer);
}
ゼロ終了に関する以前のコメントに加えて、独自のバッファをオーバーフローさせない責任も受け入れる必要があります。コードが停止していないため、8文字で停止しません。次のようなものが必要です(ジェレミーの提案にピギーバック):
#define DATA_LENGTH 8
#define BUFFER_LENGTH (DATA_LENGTH + 1)
char Buffer[BUFFER_LENGTH]; //holds the byte stream
int charPos=0; //index to next character position to fill
while (charPos <= DATA_LENGTH ) { //user input event has occured
Buffer[i] = charInput;
Buffer[i+1] = '\0';
// Display a response to input
printf("Buffer is %s!\n", Buffer);
i++;
}
つまり、環境が何をプッシュしようとしているかに関係なく、最大長に達したときにデータの受け入れを停止するようにしてください。
誰もこの可能性について言及していないのは奇妙なことです。
_char Buffer[8]; //holds the byte stream
int i = 0;
while (i < sizeof(Buffer) && (charInput = get_the_users_character()) != EOF)
{
Buffer[i] = charInput;
i++;
// Display a response to input
printf("Buffer is %.*s!\n", i, Buffer);
}
_
Printf()形式の文字列のこの表記は、表示される文字列の最大長を指定し、ヌル終了を必要としません(ただし、少なくともこのループを離れると、最終的にはヌル終了が最善の方法です)。
while
ループは単純なif
よりも妥当であり、このバージョンでは、バッファーの終わりがオーバーフローしないことが保証されます(ただし、末尾のNULに十分なスペースを残すことは保証されません_'\0'
_。これを処理する場合は、sizeof(Buffer) - 1
を使用して、ループの後にNULを追加します。
Buffer
は初期化されていないため、9つのガベージ値すべてから始まります。観測された出力から、2番目、3番目、4番目、5番目、6番目、7番目、8番目、および2つのすぐ隣のメモリ位置(配列外)の要素は、明らかに'T'
、'T'
、'W'
、 '\0'
、'\0'
、'='
、'\0'
、'\0'
、'\0'
。
文字列は、NULL文字が表示されるまですべての文字を消費します。そのため、すべての反復で、配列要素が1つずつ割り当てられるため、ガベージNULLが存在する部分までバッファが出力されます。
つまり、文字配列が'\0'
で終わっていない場合、文字列の動作は未定義です。バッファの最後に'\0'
用の余分なスペースを設けることで、これを回避できます。
CまたはC++でプログラミングしている場合は、次の点に注意する必要があります。1)文字列は\ 0文字で終了します。 2)Cには文字列での境界チェックがなく、単なる文字配列です。