「strcat」について

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
こんばんは

「strcat」について

#1

投稿記事 by こんばんは » 8年前

C言語初心者です、下記のコードにて私では理解することの出来ない部分が多々ありましたので、どなたかご指導お願いします。

コード:

int field[5][5];

void initField()
{
	int i,j;

	for(j = 0 ; j < 6 ; j++)
	{
		for(i = 0 ; i < 6 ; i++)
		{
			field[j][i] = 1;
		}
	}

	for(i = 0 ; i < 6 ; i++)
	{
		field[i][0] = 0;
		field[i][6 - 1] = 0;
		field[0][i] = 0;
		field[6 - 1][i] = 0;
	}
}

//strcatで使用する
char *str2[6] = {"◇","1","2","3","4","△"};
//-----------------

int main(void)
{
	int i,j;

	initField();
	
	for(j = 0 ; j < 6 ; j++)
	{
		char str1[13];
		
		str1[0] = '\0';//-----------------------なぜこの処理をしなければならないのかわかりません

		for(i = 0 ; i < 6 ; i++)
		{
			switch(field[j][i])
			{
			case 0:

				if(j == 0)
					strcat(str1,str2[i]);//ここの処理はstr1[]にstr2[i]番目の値を連結していくですよ
//                                                                                            ね?次の処理では1行目の処理で「str1[]に6個+NULL」の
//                                                                                            入った 所に2行目表示の処理str1[]が入る
//                                                                                             これを繰り返すとchar str1[13];を溢れてしまうのですが・・・
				else if(i == 0)
					strcat(str1,str2[j]);
				else                                                   
					strcat(str1,"□");
				break;

			case 1:
					strcat(str1,"・");
			}
		}
		printf("%s\n",str1);
	}
}
上記でコメントをしている部分が理解できないため全体的に把握でいていない状態です。

box
記事: 1747
登録日時: 9年前

Re: 「strcat」について

#2

投稿記事 by box » 8年前

本題へ行く前に、initField()で、field[][]の定義範囲外の
領域にアクセスしまくっているのを何とかする必要がありそうです。
バグのないプログラムはない。
プログラムは思ったとおりには動かない。書いたとおりに動く。

こんばんは

Re: 「strcat」について

#3

投稿記事 by こんばんは » 8年前

本題へ行く前に、initField()で、field[][]の定義範囲外の
領域にアクセスしまくっているのを何とかする必要がありそうです。

すみませんでした、int field[5][5]; → int field[6][6];

こう直すということでしょうか?

こんばんは

Re: 「strcat」について

#4

投稿記事 by こんばんは » 8年前

コメントのインデント及び、field[][]を修正しました。

コード:

int field[6][6];

void initField()
{
	int i,j;

	for(j = 0 ; j < 6 ; j++)
	{
		for(i = 0 ; i < 6 ; i++)
		{
			field[j][i] = 1;
		}
	}

	for(i = 0 ; i < 6 ; i++)
	{
		field[i][0] = 0;
		field[i][6 - 1] = 0;
		field[0][i] = 0;
		field[6 - 1][i] = 0;
	}
}

//strcatで使用する
char *str2[6] = {"◇","1","2","3","4","△"};
//-----------------

int main(void)
{
	int i,j;

	initField();
	
	for(j = 0 ; j < 6 ; j++)
	{
		char str1[13];
		
		str1[0] = '\0';//-----------------------なぜこの処理をしなければならないのかわかりません

		for(i = 0 ; i < 6 ; i++)
		{
			switch(field[j][i])
			{
			case 0:

				if(j == 0)
					strcat(str1,str2[i]);//ここの処理はstr1[]にstr2[i]番目の値を連結していくですよ
//                          ね?次の処理では1行目の処理で「str1[]に6個+NULL」の
//                          入った 所に2行目表示の処理str1[]が入る
//                          これを繰り返すとchar str1[13];を溢れてしまうのですが・・・
				else if(i == 0)
					strcat(str1,str2[j]);
				else                                                   
					strcat(str1,"□");
				break;

			case 1:
					strcat(str1,"・");
			}
		}
		printf("%s\n",str1);
	}
}
上記でコメントをしている部分が理解できないため全体的に把握でいていない状態です。[/quote]

アバター
へにっくす
記事: 630
登録日時: 8年前
住所: 東京都

Re: 「strcat」について

#5

投稿記事 by へにっくす » 8年前

コード:

str1[0]='\0'; // 文字列を初期化 (strcatは'\0'の位置にstrcpyする関数)
この後 i のループで最初(i=0)は、必ずstr1の先頭に文字列をコピーすることになります。
その後、i = 1~5 までstr1に文字列を追加することになります。
追加する文字列はいずれも全角1文字(=2bytes)なので、6 回追加すると 6 x 2 = 12
str1のサイズは、それに終端文字を含めたサイズ 13 バイトになっているのです。
(つまり i のループに入る前に必ず str1 の初期化を行っているのでサイズオーバーにならない
だから str1[0] = '\0';の1行を外せば、あなたの懸念通り、str1 のサイズをオーバーするよ)

こんな説明で分かるかな?
#文字列は終端文字があってはじめて文字列と言えるのだよ。
written by へにっくす

こんばんは

Re: 「strcat」について

#6

投稿記事 by こんばんは » 8年前

へにっくす様
大変わかりやすい解答ありがとうございました。

「\0'の位置にstrcpy」 「必ずstr1の先頭に文字列をコピーする」 ←この事を知りませんでしたので勉強になりました。

i のループを一回終え j++ をし 「str1[0]='\0'; 」、もう一度 i のループに入る

この時str1[]の中は{"\0", "1", "2", "3", "4", "△","\0"}だと思います

「必ずstr1の先頭に文字列をコピーする」 ⇔ 必ず「先頭にある終端文字」から文字列をコピーしていく

このように解釈したのですが、正しいでしょうか

アバター
へにっくす
記事: 630
登録日時: 8年前
住所: 東京都

Re: 「strcat」について

#7

投稿記事 by へにっくす » 8年前

こんばんは さんが書きました:必ず「先頭にある終端文字」から文字列をコピーしていく
この解釈はいいんだけどねえ。
こんばんは さんが書きました:この時str1[]の中は{"\0", "1", "2", "3", "4", "△","\0"}だと思います
この書き方じゃ、文字列の配列になるよ。こう書かないと。

コード:

str1[] = "◇1234△"; // str1[0]に'\0'が書かかれる前の文字列
これを文字列はcharの配列とみなすと、こう書ける。

コード:

str1[] = {0x81, 0x9E, 0x82, 0x50, 0x82, 0x51, 0x82, 0x52, 0x82, 0x53, 0x81, 0xA2, 0x00}; // Shift-JISだった場合
これにstr1[0] = '\0';だから、
こう書かないといけないね。

コード:

str1[] = {0x00, 0x9E, 0x82, 0x50, 0x82, 0x51, 0x82, 0x52, 0x82, 0x53, 0x81, 0xA2, 0x00}; // Shift-JISだった場合
これをまともに文字列化すると、

コード:

str1[] = "\0\x9E1234△"; // str1[0]に'\0'が書かれた後の文字列
こうなる。文字列と文字列の配列をごっちゃにしないでね。
written by へにっくす

こんばんは

Re: 「strcat」について

#8

投稿記事 by こんばんは » 8年前

すみません、返信遅くなりました。
文字列リテラル等、配列についての勉強不足を痛感いたしました。

へにっくす様 最後まで大変ありがとうございました。

閉鎖

“C言語何でも質問掲示板” へ戻る