web-dev-qa-db-ja.com

末尾にガベージ文字を含む文字列配列

ユーザーが1つずつ入力する文字を格納するために使用しているchar配列バッファーがあります。以下の私のコードは機能しますが、理解できないいくつかの不具合があります。

  1. printfを実行してBufferの内容を確認すると、いっぱいになりますが、最後にガベージ文字が表示されます
  2. char Buffer [8]として宣言されているにもかかわらず、8文字で停止することはありません。

誰かが私に何が起こっているのか、そしておそらく私がこれを修正する方法を説明してもらえますか?ありがとう。

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です!

12
Steve

文字列は\ 0文字で終了する必要があります。そのため、これらはゼロ終端文字列と呼ばれます。

\ 0を保持するために1文字余分に割り当てることも賢明です。

28
Toon Krijthe

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
Jeremy Ruten

ゼロ終了に関する以前のコメントに加えて、独自のバッファをオーバーフローさせない責任も受け入れる必要があります。コードが停止していないため、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++; 

}

つまり、環境が何をプッシュしようとしているかに関係なく、最大長に達したときにデータの受け入れを停止するようにしてください。

3
joel.neely

誰もこの可能性について言及していないのは奇妙なことです。

_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を追加します。

0

Bufferは初期化されていないため、9つのガベージ値すべてから始まります。観測された出力から、2番目、3番目、4番目、5番目、6番目、7番目、8番目、および2つのすぐ隣のメモリ位置(配列外)の要素は、明らかに'T''T''W''\0''\0''=''\0''\0''\0'

文字列は、NULL文字が表示されるまですべての文字を消費します。そのため、すべての反復で、配列要素が1つずつ割り当てられるため、ガベージNULLが存在する部分までバッファが出力されます。

つまり、文字配列が'\0'で終わっていない場合、文字列の動作は未定義です。バッファの最後に'\0'用の余分なスペースを設けることで、これを回避できます。

0
Mani Kanth

CまたはC++でプログラミングしている場合は、次の点に注意する必要があります。1)文字列は\ 0文字で終了します。 2)Cには文字列での境界チェックがなく、単なる文字配列です。

0
Edmundo