指定されたプログラムで 4 つの文字列をすべて出力しようとしています。しかし、文字列を印刷できません。以下のコードでは、奇妙な出力が得られます。
int main()
{
char szStr[] = "India\0Japan\0America\0Australia";
char *p = szStr;
while(p)
{
printf("%c", p);
p++;
}
return 0;
}
while(p)
と同じです
while(p != NULL)
もちろん、これは常に真です。文字列リテラルは有効なメモリ位置を指しています。私はあなたがこれを混同していると感じます
while(*p)
または同等のもので
while(*p != 0)
これは、文字列内で 0 ターミネータが見つかるまで実行されるためです。しかし、それでも十分ではありません。どの文字列を印刷したかわかりません。文字列の数を手動で追跡する必要があります。printf()
また、表示するすべてのバイトに対して非常に高価な関数を呼び出して、文字ごとに出力するのはなぜですか? それはただ無駄です。のようなものはどうですか
char szStr[] = "India\0Japan\0America\0Australia";
char *p = szStr;
for (int i = 0; i < 4; i++) {
puts(p);
p += strlen(p) + 1;
}
それでも、単純に文字列の配列を格納するよりも、なぜこれが簡単なのか、それとも優れているのか、私にはわかりません。このような:
const char *strings[] = {
"India",
"Japan",
"America",
"Australia"
};
for (int i = 0; i < sizeof(strings) / sizeof(strings[0]); i++)
puts(strings[i]);
これはテスト済みで動作します:
#include <stdio.h>
int main()
{
char szStr[] = "India\0Japan\0America\0Australia\0";
char *p = szStr;
while(*p)
{
p += printf("%s", p);
p++;
fputc('\n', stdout);
}
return 0;
}
文字列の余分な null ターミネータに注意してください。文字列リテラルには独自の null 項があるにもかかわらず、これは実際には重要です。while ループを正しく終了するには、2 つのヌル項が必要です。
printf
書き込まれた文字数、つまり、null ターミネータを含まない各文字列の長さを返します。したがって、これを に追加すると、null ターミネータp
を指したままになります。p
再びインクリメントp
すると、次の文字列の先頭になります。その文字列の長さが 0 の場合、p
は再び null ターミネータを指しているため、while ループは失敗します。そのため、文字列の末尾に余分な null ターミネータが必要です。
while(p)
行を に変更しwhile(*p)
ます。
ではc
、0 以外は true と見なされ、0 は false と見なされます。
したがって、p
は 0 ではなく、while
ループが何度も繰り返されます。
ただし*p
、文字列の最後では 0 になります。
%c
単一の文字を印刷するためのフォーマット指定子です。%s
代わりに使用してください。それでも printf は、最初の文字までの文字列のみを出力します\0
。4 つの文字列を出力する場合は、印刷する前に何らかの分割を実行する必要があります。sscanf
と一緒に使うかも"%s%s%s%s"
。
*p
が指す値を取得することを忘れないでくださいp
。
これはうまくいきます:
int main()
{
char szStr[] = "India\0Japan\0America\0Australia\0";
char *p = szStr;
int numOfStrings = 4;
for(int i = 0; i < numOfStrings; i++)
{
while(*p)
{
printf("%c", *p);
p++;
}
printf(" "); //print a space character to separate your strings
p++; //advance pointer to skip '\0' between strings
}
return 0;
}