ページ 11

strcpy関数の戻り値を変数に保存したい

Posted: 2017年9月25日(月) 22:48
by ロコン
以下のようなコードを実行してstrcpyの結果をprintfで表示させたいのですが想定とは異なる結果となりました。
想定
タイトル
サブタイトル
結果
END
END
という風に表示されました
何がいけなかったのでしょうか?

コード:

#pragma warning(disable:4996)
#include <stdio.h>
#include <string.h>

#define MAX 2048
int main(void) {
	FILE *fp;
	char buf[500];// [MAX];
	char *title, *subtitle;
	if ((fp = fopen("test.txt", "r")) != NULL) {
		while (fgets(buf, MAX, fp) != NULL) {
			if (strstr(buf,"#END") != NULL) break;//STARTでヘッダ終了
			if ((strstr(buf, "TITLE:") != NULL) && (strstr(buf, "SUBTITLE:") == NULL)) {//タイトル
				title = strcpy(buf + 1, buf + 6);
				continue;
			}
			if ((strstr(buf, "SUBTITLE:") != NULL)) {
				subtitle = strcpy(buf + 1, buf + 9);
				continue;
			}
		}
	}
	printf("%s", title);
	printf("%s", subtitle);
	while(1){}
	return 0;
}
test.txt

コード:

TITLE:タイトル
SUBTITLE:サブタイトル
#END

Re: strcpy関数の戻り値を変数に保存したい

Posted: 2017年9月25日(月) 23:39
by みけCAT
まず、一般的な文字コードでは全角カタカナは2バイト以上で表されるので、重なった領域間でのstrcpyをすることになり、未定義動作になります。
次に、titleやsubtitleにはbuf[1]を指すポインタが格納されています。(未定義動作なので何が起こってもおかしくないですが、strcpyの通常の動作およびENDが出力されていることからこう予想できます)
bufの中身はfgetsによって上書きされるので、strcpyの戻り値を代入した時の文字列をそのまま保持することはできません。
最後に、fopenしたのにfcloseしていないこと、そしてtitleやsubtitleがtest.txtの中身によっては不定のままprintfに渡されてしまうのもよくないように思えます。
ロコン さんが書きました:何がいけなかったのでしょうか?
「以下のようなコードを実行してstrcpyの結果をprintfで表示させたい」「strcpy関数の戻り値を変数に保存したい」と考えたのがいけなかったのでしょう。
想定の結果を得るには、「strcpy関数の戻り値を変数に保存する」のではなく、「mallocなどで確保した領域へのポインタを変数に保存し、そこにstrcpyする」のがいいでしょう。
文字列を格納する領域は、少なくとも文字列の長さ(strlenで得られる)+1(最後のナル文字の分)バイト必要です。

Re: strcpy関数の戻り値を変数に保存したい

Posted: 2017年9月26日(火) 20:19
by ロコン
ありがとうございます!!
うまくいきました!