2017-12-29 25 views
0

私はいつも変更する必要があるので、私はポインタを使用していないので、私はコードを実行するたびに私は奇妙な動作を取得する文字列が必要なので、 31回目の繰り返し。言い換えればランダムな文字が奇妙に定義された動作

コード

int i = 0; 
char name[100]; 
srand(getpid()); 


while(i<100) { 

    name[i] += (char)'A'+(rand()%26); 
    printf("%d strlen\n", i+1); 
    printf("%s\n", name); 
    printf("/////\n"); 
    i++;  
} 

出力

///// 
30 strlen 
IKXVKZOLKHLTKBFFTUZCYXHYVEBZOY 
///// 
31 strlen 
IKXVKZOLKHLTKBFFTUZCYXHYVEBZOYJ 
///// 
32 strlen 
IKXVKZOLKHLTKBFFTUZCYXHYVEBZOYJWttime 
///// 
33 strlen 
IKXVKZOLKHLTKBFFTUZCYXHYVEBZOYJW�time 
///// 
34 strlen 
IKXVKZOLKHLTKBFFTUZCYXHYVEBZOYJW��ime 
///// 
35 strlen 
IKXVKZOLKHLTKBFFTUZCYXHYVEBZOYJW���me 
///// 
36 strlen 
IKXVKZOLKHLTKBFFTUZCYXHYVEBZOYJW����e 
///// 
37 strlen 
IKXVKZOLKHLTKBFFTUZCYXHYVEBZOYJW����� 

それは常にttime 31日文字などを印刷した後、コードは、その単語の各文字を上書きし、私は、結果として疑問符を取得します。物事に行く

は、最終的な出力

100 strlen 
IKXVKZOLKHLTKBFFTUZCYXHYVEBZOYJW�����K��ȶ������MKRLHALEV�SNNRVWNOEXUVQNJUHAEWN�W�YPMCW�N�PXHNT��0� 
///// 

これはなぜ起こるのでしょうか?でさらに悪化外観を得ますか

+0

'name'のをやっている

name[i] += (char)'A'+(rand()%26); 

をしているのではない '0'アウトゲームが始まる前に、その後、C-文字列として扱われます。悪名高い未定義の行動が再び襲います。 – alk

+0

私は他の言語での経験があることを賭けています。 Cの文字列は奇妙ですが、予測可能です。 'string + = 'x''はあなたの考えをしません。 – usr2564301

+0

@alkゲームが始まる前に0になっていないのはどういう意味ですか? –

答えて

1

よくごみ値を印刷しています。 (未定義の振る舞い)私は、あなたの乱数に加えられたそれらのゴミ値がいくつかの文字のASCII値かもしれないし、それらがいくつかの非印刷物であるかもしれない。文字配列を\0で初期化する必要があります。これは、実行文字列に\0を追加し、追加して印刷可能であることを確認するか、またはを割り当てるだけです。

name[i] = 'A'+(rand()%26); 

また、文字列の末尾に\0を挿入します。それ以外の場合は、\0が見つかるまで配列のインデックスにアクセスしようとしますが、定義されていない動作が呼び出されます。

31は特別なものではありません。次に実行するときは何でもかまいません。

コード:番目のインデックス99でNUL終端文字があるので、我々は、インデックス番目98までループしている

#include <stdio.h> 
#include <stdlib.h> 
#include <unistd.h> 
int main(void) { 
    size_t i = 0; 
    char name[100]={0}; // = ""; 
    srand(getpid()); 

    while(i<99) { // till 99 making sure you won't overwrite the last NUL 

     name[i] ='A'+(rand()%26); 
     printf("%d strlen\n", i+1); 
     printf("%s\n", name); 
     printf("/////\n"); 
     i++;  
    } 
    return 0; 
} 

注意。

1

char name[100];は、デフォルトでは文字列ではありません。これはちょうど別の100要素char配列です。

はC文字列は、文字列の終わりをマークするために(少なくとも)1つの'\0'文字を運ぶ常にあります。 printf()、ほとんどすべてのstr*()関数と他の多くの関数は、この終わりに依存します'\0'

また、配列要素に追加する考えは何ですか?

name[i] += ... 

これらの値は設定されていません。それらはゴミです。価値があっても、それを加えることは初期化されていないメモリ1stを読み取ることを意味し、その結果、未定義の動作が引き起こされます。

while (i < 99) { 
    name[i] = (char) 'A' + (rand() % 26); 
    name[i + 1] = '\0'; 

または任意の偶数開始する前に、すべての'\0'nameを初期化怠惰なアプローチのために行く:だから、さらには手でターミネータを追加するには、コードのドロップを修正する

char name[100] = ""; /* or ... = {0}; */ 

(このname[i] += ...に従うことができますが、すべての要素が0であるため、追加は使用されません)。

任意ケース最後の要素(ここでは100)までループしませんが、最後の要素が1つ少なくなると、末尾に予約されます'\0'

+0

ありがとうございました。それは本当に解決策です。私は前に彼が答えたので、私は他の人に投票しました。 –

0

char name[100]配列が関数内のローカル変数である場合、その初期値は定義されていません。それで、それは前の記憶の塊の中にあったランダムなジャンクを含んでいます。したがって

あなたが実際に

name[i] = RANDOM JUNK + (char)'A'+(rand()%26); 
関連する問題