2

C のすべての文字列は '\0' 文字で終わることを知っています。文字列がいつ終了するかを知る必要がある場合に非常に便利です。ただし、文字列を印刷する場合と、それなしで文字列を印刷する場合の使用法を理解することはできません。私は次のコードを持っています:-

/* Printing out an array of characters */
#include<stdio.h>
#include<conio.h>
int main()
{
    char a[7]={'h','e','l','l','o','!','\0'};
    int i;
    /* Loop where we do not care about the '\0' */ 
    for(i=0;i<7;i++)
    {
        printf("%c",a[i]);
    }
    printf("\n");
    /* Part which prints the entire character array as string */
    printf("%s",a);
    printf("\n");
    /* Loop where we care about the '\0' */
    for(i=0;i<7&&a[i]!='\0';i++)
    {
        printf("%c",a[i]);
    }
}

出力は次のとおりです。

hello!
hello!
hello!

私は違いを理解することができません。説明はありますか?

4

9 に答える 9

3

この場合:

for(i=0;i<7;i++)
{
    printf("%c",a[i]);
}

何度もループし(7)、その後終了します。これがループの終了条件です。何があっても終了します。

もう1つのケースでは、ループを7回以上実行せずに、別の条件を追加しただけです。これは、すでにカウントを保持しているため、実際には機能しません。次の場合:

 int index = 0;
 while (a[index] != '\0') { printf("%c", a[index]); index++; } 

これで、ゼロ終了文字がそこにあることに依存します。文字列に含まれていなかった場合while、プログラムがクラッシュするか、何かが強制的に終了するまで、ループは永久に続きます。おそらく画面にゴミを印刷します。

于 2013-01-13T20:33:36.170 に答える
2

\0文字列のデータの一部ではありません。文字列の終わりを示します。文字列の長さがわからない場合は、このインジケータを探してください。その助けを借りて、あなたはあなたのサイクルを置き換えることができます:

for(i=0;i<7&&a[i]!='\0';i++) { ...

と:

for(int i=0; a[i]; ++i) { ...

したがって、forループとprintfは同じ文字列を表示しています。あなたがそれを印刷する方法の唯一の違い。

于 2013-01-13T20:34:05.843 に答える
1

ゼロ文字を終了する目的は、文字列を終了することです。つまり、文字列の長さ情報を文字列自体に間接的にエンコードすることです。文字列の長さがすでにわかっている場合は、終了するゼロ文字に依存せずに正しく機能するコードを記述できます。基本的にはこれですべてです。

さて、あなたのコードサンプルでは、​​最初のサイクルはあまり意味のないことをします。実際に長さが6の文字列から7文字を印刷します。つまり、終了ゼロも印刷しようとします。

于 2013-01-13T20:35:29.840 に答える
1

'\0'表示可能な文字に対応していません。そのため、最初と最後のバージョンが同じように見えます。

2 番目のバージョンは同じです。ボンネットの下では、printfに到達するまで反復するだけだから'\0'です。

于 2013-01-13T20:31:35.043 に答える
1

最初の文字から最後まで文字列を印刷したい場合。\0文字列が(Print characters until )で終わる場合、その文字列の長さを知る必要はありません\0したがって、 string の長さを格納するために追加の変数は必要ありません

実際、文字列は多くのさまざまな表現を持つことができますが、消費されるメモリを最小限に抑えること (これは C 設計者にとって重要でした) により、設計者はゼロで終わる文字列を定義するようになります。

各文字列表現には、速度、メモリ、および柔軟性の間でトレードオフがあります。たとえば、配列の最初の要素に文字列の長さを格納する Pascal 文字列と同じ文字列定義を使用できますが、その文字列の長さは制限されますが、文字列の長さの取得は、ゼロで終わる文字列 (各文字をカウントする) よりも高速です。まで\0)。

于 2013-01-13T20:40:21.837 に答える
0

ループでは、実際にヌル文字を出力します。これは非印刷、非制御文字であるため、通常、これは効果がありません。ただしprintf("%s",a);、nulはまったく出力されません。これは、番兵の値として使用されます。したがって、ループは%s形式の出力と同等ではありません。

あなたが言うことを試みるならば:

char a[] = "123456" ;
char b[]={'h','e','l','l','o','!' } ;  // No terminator
char c[] = "ABCDEF" ;

printf( "%s", a ) ;
printf( "%s", b ) ;
printf( "%s", c ) ;

nulターミネータが不可欠である理由がはっきりとわかるかもしれません。私の場合、次のように出力されます。

123456
hello!╠╠╠╠╠╠╠╠╠╠123456
ABCDEF

マイレージは異なる場合があります。結果は未定義の動作ですが、この場合、出力は隣接する文字列に到達しますが、コンパイラは「ジャンク」を含む未使用のスペースを挿入します。特定のコンパイラがメモリ内のデータをどのように順序付けているかを知る方法がないため、終了していない文字列の両側に文字列をパックしました。ちなみに、文字列のstatic場合は文字列を宣言したところ、文字列bは「ランオン」なしで出力されました。周囲の「ジャンク」がすでにゼロになっている場合があります。

于 2013-01-13T23:04:12.977 に答える
0

文字列の印刷とそれなしの文字列の印刷での使用法を理解できません

通常、このような文字列を1文字ずつ印刷することはありません。文字列全体を印刷します。このような場合、Cライブラリはゼロが見つかるまで出力します。

于 2013-01-13T20:32:50.103 に答える
0

終端のゼロ文字の目的は、文字列を終了することです。つまり、文字列自体に文字列の長さ情報を間接的にエンコードすることです。なんらかの方法で文字列の長さがわかっている場合は、その末尾のゼロ文字に依存せずに正しく機能するコードを記述できます。基本的にはそれだけです。

さて、あなたのコード サンプルでは、​​最初のサイクルであまり意味のないことをしています。実際には長さ 6 の文字列から 7 文字を出力します。つまり、終端のゼロも出力しようとします。なぜそれをしているのですか - 私にはわかりません。つまり、コードによって生成される最初の出力は、記号の直後にゼロ文字を出力する効果が含まれているため、残りの出力と形式的に異なります!。あなたのプラットフォームでは、その効果がたまたま画面上で「見えない」ため、最初の出力が他の出力と同じであると想定したのでしょう。ただし、出力をファイルにリダイレクトすると、実際にはまったく異なることがわかります。

コード内の他の出力メソッドは、文字列を終端のゼロ文字まで (ゼロ文字は含まない) 単純に出力します。最後のサイクルには冗長な条件チェックがあります。これは、サイクルがゼロ文字で停止することがわかっているため、i7 にヒットする可能性があるためです。

それ以外は、あなたがどのような「違い」を求めているのかわかりません。これで解決しない場合は、質問を明確にしてください。

于 2013-01-13T20:36:41.867 に答える
0

可変長の文字列を出力する場合、最後に到達したことを示す「シグナル」が必要です。通常、これは '\0' 文字です。strcpy、strcat、printf などのほとんどの C 標準呼び出しは、ゼロで終了する文字列に依存しているため、'\0' 文字で終了します。これは、2 番目の例に対応します。

最初の例は、固定長の文字列を出力することです。これは、あまり一般的ではありません。

3 番目の例は両方を組み合わせたもので、ゼロターミネータ ('\0' 文字) または最大 7 文字を探します。これは、たとえばstr n cpy などの呼び出しに対応します。

于 2013-01-13T20:36:43.353 に答える