ページ 1 / 1
char型配列?
Posted: 2009年5月19日(火) 17:40
by チルチル
なんかchar型配列に文字列を格納する時は
文字数+1個要素を確保しないといけないって
聞いたんですけど、なぜ1個多く確保する必要があるんですか?
Re:char型配列?
Posted: 2009年5月19日(火) 17:53
by 御津凪
C/C++ では文字列の終端を、ヌル文字('\0')で判断するためです。
strlen 等の関数では、以下のような処理を行って文字列の長さを判別しています。
size_t strlen( const char *s ){
size_t r = 0;
while(s[[/url] != '\0') ++r;
return r;
}
ヌル文字も一文字として扱うので、文字数に1個足した要素分確保する必要がある、ということです。
なので、C/C++ のどの文字列も、文字列の最後にヌル文字があります。
(例外はありますが)
Re:char型配列?
Posted: 2009年5月19日(火) 17:55
by Mist
最後に終端コード'\0'をセットするためです。
printf等の関数は文字列の終わりを'\0'で判断するため、'\0'がないと正しく表示されません。
また、sprintfなどで配列に文字列をセットする場合、'\0'が最後に付けられるので+1しておかないとバッファオーバーランになりメモリ破壊の原因になります。
Re:char型配列?
Posted: 2009年5月19日(火) 19:12
by チルチル
そうなんですか・・
私は要素数8個のchar型配列に
文字入力関数で8文字入力して
結果がおかしくなったので
要素数を10個にして
その配列の中身を要素数8個の
別の配列にfor文でコピーする処理
を行っていましたが
これが例外って事でしょうか?
見た感じ文字出力関数では正常に
表示されていますが
文字出力関数は終端を判断しなくて良いと言う事でしょうか?
Re:char型配列?
Posted: 2009年5月19日(火) 19:31
by 御津凪
> 見た感じ文字出力関数では正常に
> 表示されていますが
> 文字出力関数は終端を判断しなくて良いと言う事でしょうか?
文字出力関数も含め、全ての文字列を扱う関数では、終端(ヌル)文字がないといけません。
見た目正常に表示されていても、終端文字が無ければ
バッファオーバーランにより、文字列の後ろにゴミ文字が発生したり、予期しない動作を引き起こす可能性もあります。
実際、関数に文字列(ポインタ)だけを渡された時、文字列の長さを関数側から判断できるのは
終端文字を探し、その文字までの長さしかありません。
> これが例外って事でしょうか?
例外というのは、終端文字が無くても文字列の長さが判断できる場合(必ず4文字の文字列のデータなど)です。
Re:char型配列?
Posted: 2009年5月19日(火) 19:36
by Mist
> 文字出力関数は終端を判断しなくて良いと言う事でしょうか?
文字出力関数とは具体的に何を指していますか?
使用する関数によっては終端コードはなくても動作させることはできます。
例えば
char str[8] = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h' };
として
printf("%s\n", str);
とした場合は終端コードがないので正しく動作しません。
str[7]の次のメモリが偶然'\0'であれば正しく表示されますが、あくまでも偶然です。
for (int i = 0; i < 8; i++) {
putchar(str);
}
putchar('\n');
このように一文字ずつ表示して文字列の終わりを自前で判断するのであれば終端コードは無くても正常に動作させることはできます。
Re:char型配列?
Posted: 2009年5月19日(火) 19:46
by たかぎ
C++では、終端のナル文字は常に必要というわけではありません。
例えば、std::basic_stringが保持する文字列の末尾には、ナル文字が格納されているとは限りません。
また、アルゴリズム関数も、先頭位置と終端(の次の)位置を指定することになりますので、ナル文字は必須ではありません。
Re:char型配列?
Posted: 2009年5月19日(火) 20:37
by チルチル
やっぱりヌル文字を入れた方がいいのかな・・
描画はDrawFormatString関数
REPLAY.Nameを%8sで描画しています
Nameは構造体のメンバで要素数8個のchar型配列です
そういえばたまに表示がおかしくなる時が・・
Re:char型配列?
Posted: 2009年5月20日(水) 07:24
by toyo
%8sだと文字列終端は必要ですよ
これは8文字未満のときに空白文字を8文字分まで追加するという意味で8文字以上の場合はそのまま出力されます
8文字まで表示の場合は精度をあらわすピリオドをつけましょう
%.8sなら8文字以上の場合終端文字はいりません
Re:char型配列?
Posted: 2009年5月20日(水) 17:32
by チルチル
あれ?これは文字列ですが
普通これは小数点以下の精度では?
ヌル文字付けた方がよさそうですね
今までは8文字以上はありえないし
0で初期化してるから大丈夫だったのかな・・
Re:char型配列?
Posted: 2009年5月21日(木) 07:26
by toyo
ピリオドは小数だけの意味ではありませんよ
#include "DxLib.h"
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow )
{
char* str = "ABCDEFG";
ChangeWindowMode(TRUE);
if( DxLib_Init() == -1 )
{
return -1;
}
DrawFormatString(10, 10, GetColor(255, 255, 255), "%4s", str);
DrawFormatString(10, 30, GetColor(255, 255, 255), "%.4s", str);
DrawFormatString(10, 50, GetColor(255, 255, 255), "%10s", str);
DrawFormatString(10, 70, GetColor(255, 255, 255), "%10.4s", str);
WaitKey() ;
DxLib_End() ;
return 0 ;
}
を実行すると画像のようになります
Re:char型配列?
Posted: 2009年5月21日(木) 19:37
by チルチル
あ~なるほど、こう言う使い方もあるんですね。
どうもありがとうございました。