txtファイル文章

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

txtファイル文章

#1

投稿記事 by ice » 16年前

ここで質問させていただくのは2度目になると思いますiceと申します。
もしかするとハンドルネーム前と違うかもしれません
テキストやtxtで検索したのですが該当する投稿がなさそうなので質問させていただきます。

ゲームの会話などのシーンで外部txtファイルから文章読み込みを行いたいのですが、読み込みを行う方法が分かりません。
仮にキーXを押したときに[aaa01.txt]というファイル内3行目にある「こんにちわ」という文書を読み込ませたい場合はどのように書けばよいのでしょうか。
ご教授お願いします。
------------------------------------------------------

void text()
{
txtファイルの読み込み

if( Key[ KEY_INPUT_X ] == 1 )
{
画面に絵画
}
}

------------------------------------------------------
多分このような感じになると思うのですが・・・

朽木

Re:txtファイル文章

#2

投稿記事 by 朽木 » 16年前

char FileBuf[FILE_BUFFER_SIZE + 1]; /* ファイルの文字を読み込むための領域を確保 */
FILE *FilePointer = NULL; /* ファイル構造体へのポインタ */

FilePointer = fopen(FilePath, "r"); /* ファイルをオープンする(エラー処理を省略) */

for (3回) fgets(&FileBuf[0], FILE_BUFFER_SIZE, FilePointer); /* 3回、1行分の文字列をバッファに確保 */

printf(fmt, &FileBuf[0]); /* fmt通りに表示。fmtは必要な形に置き換える */

fclose(FilePointer); /* 必要なくなったので解放 */

FilePointer = NULL; /* 今使ってるアドレスはもう使えないので NULL 化 */
みたいな感じでしょうか。この通りにやって動かなかったらごめんなさい。

ice

Re:txtファイル文章

#3

投稿記事 by ice » 16年前

朽木様、レス有難うございます。
しかしながら申し訳ないのですが、私には少し難解でよく分かりませんorz
私の書いた例文の中にいれるようなスタイルで出来れば分かりそうなのですが・・・

nayo

Re:txtファイル文章

#4

投稿記事 by nayo » 16年前

void text( void )
{

	FILE *fp;		// ファイルポインタ
	char string[80][256];	// 読み込む文字 [最大行][一行あたりの最大文字数]

	// ファイルを開く
	if( ( fp = fopen( "ファイルの名前", "r" ) ) == -1 )
	{	// エラーなので終了
		return;
	}

	// ファイルから80行文字列を読み込む
	for( int i=0; i<80; i++ )
	{	// 一行ずつ読み込み
		fgets( string, 256, fp );
	}
	
	// 使用が終わったので解放
	fclose( fp );

	// 描画処理(Xキーを押しているときのみ)
	if( Key[ KEY_INPUT_X ] == 1 ) 
	{	// 3行目だけ描画したいならstring[2]を描画してやれば良い
		printf( "%s", string[2] );
	} 
}


できるだけわかりやすく書いた分非常に無駄が多く、このままでは実用的ではないです
動作は確認していないのでもしかしたらミスがあるかもしれないです
シルバーで書いてある部分を関数化するなどして、文章を読み込む作業は一回だけにした方がいいです


追記:
printfのところは変えてください
処理としては文字列が必要になりそうなら読み込み関数を呼び出しておき、描画が必要になったら描画用の関数を呼び出す、
といった感じにするといいかと思います

SCI

Re:txtファイル文章

#5

投稿記事 by SCI » 16年前

少し補足ですが、fopenは読取りオープンでエラーが発生したらNULLを返します。

nayo

Re:txtファイル文章

#6

投稿記事 by nayo » 16年前

SCIさん補足ありがとうございます
いやはや、しっかり確認しとくべきですね

さらに追記ですがC++だとstringは標準ライブラリ名でしたね
色々とミスが多いので当たり前ですが参考程度、ということで見てください

ice

Re:txtファイル文章

#7

投稿記事 by ice » 16年前

返信有難うございます。
今確認したところ
DXライブラリにある例文
http://homepage2.nifty.com/natupaji/DxL ... html#R19N1
だと1行目の読み込みは出来たのですが、voidで外に出す(表現はこれでいいのだろうか)と上手くいきません。
nayoさんの書かれた上記例文ではSCIさんが書かれているようにやはりエラーが出ました。
プログラムは難しいですねー。うまくいくと楽しいのですがw

ひよっこ

Re:txtファイル文章

#8

投稿記事 by ひよっこ » 16年前

nayoさんのコードでエラーとなる場所は読み込みでしょうか。

ファイルのストリームを開く際にパスの階層が異なっているかもしれませんので
確認してみてください。

その読み込み関数のあるフォルダからの階層になります。
fgetsあたりでエラーが返るのであれば、NULLチェックをしてみてください。

forで80回回すことになっていますが
if (string != NULL)
等を追加したほうが安全かもしれません。

hamanov

Re:txtファイル文章

#9

投稿記事 by hamanov » 16年前

こんにちは。

こんな感じで読み込んでみたらいかがですか?
void text()
{
	//txtファイルの読み込み
	FILE *fp;
	const char *path = "./aaa01.txt";
	
	fp = fopen(path, "r");
	if( fp == NULL)
	{
		return;
	}

	if( Key[ KEY_INPUT_X ] == 1 )
	{
		//画面に絵画
		drw_txt(fp,3);
	}
	
	fclose(fp);
} 

void drw_txt(FIEL *fp,unsigned int line)
{
	char str[256]="";
	int view_flg;
	int n;
	
	view_flg = 0;
	n = 1;
	
	if((fp == NULL) || (line == 0))
	{
		return;
	}
	
	for(;feof(fp) == 0;)
	{
		if(n == line)
		{
			view_flg = 1;
			break;
		}
		
		if(fgetc(fp) == '\n')
		{
			n++;
		}
	}
	
	if(view_flg == 1)
	{
		fgets(str,sizeof(str),fp);
		DrawString( 0, 0, str, GetColor( 255,255,255 ) ) ;
	}
	
	rewind(fp);
}
コンパイルしていないので間違っていたらごめんなさい。

朽木

Re:txtファイル文章

#10

投稿記事 by 朽木 » 16年前

毎度のように、質問文を全く見てませんでした。ごめんなさい@@;

分かりにくかったですか、、、すみません。今度はちゃんと分かると思います(`・ω・´)。

DxLibに依存する形に直しました。前の方同様、吐いてません。動かなかったらごめんなさい。
---------- プロトタイプ宣言ここから ----------
int MyFunc_getLine(int FileHandle, int LineNo, char *StrBuf, int BufSize);
---------- プロトタイプ宣言ここまで ----------

---------- main()とかに追加ここから ----------
char Buf[1023 + 1]; /* ファイル内文字列格納用 */
---------- main()とかに追加ここまで ----------

---------- 以下、text()内に追加 ----------
int FileHandle; /* FileHandle は int型を推奨 */
int ret; /* 自作関数からの返り値 */

FileHandle = FileRead_open(ファイル名);

if ( FileHandle == 0 )
    ; /* エラー処理(ファイルが何らかの理由で読めない。パスミス?権限?) */

/* 自作関数。詳しくは下。 */
ret = MyFunc_getLine(FileHandle, 3, Buf, 1023 + 1);

if ( ret )
    ; /* エラー処理 */

[color=Yellow">if[/color] ( FileRead_close(FileHandle) == -1 ) /* 使い終わったら後片付け */
    ; /* エラー処理 */

FileHandle = 0; /* 使わないので、FileRead_open()のエラー値へ変更 */
---------- text()内追加ここまで ----------

---------- 自作関数ここから ----------
[color=RoyalBlue">/* MyFunc_getLine() 関数
 * FileHandle = 既に開いたファイルへのポインタ
 * LineNo = 取得したい行の番号(最初の行の番号は1です)
 * StrBuf = 読み込んだ文字列を格納する領域への先頭アドレス(少なすぎると行数が変になる?)
 * BufSize = StrBufで確保している、番兵までのサイズ( == 確保サイズ - 1 は不要)
 * 正常であれば 0、それ以外の場合は 0以外 が返る
 */[/color]
int MyFunc_getLine(int FileHandle, int LineNo, char *StrBuf, int BufSize)
{
    int Loop = 0, BeforePos;
    
    /* 元のファイルポインタの位置を取得しておく
     * DXライブラリのリファレンス見たら、バイト位置を得るのに成功値が 0 なんだけど大丈夫かな…
     * 使い方間違っていたらごめんなさい。
     */
    if ( ( BeforePos = FileRead_tell(FileHandle) ) == -1 )
        [color=Yellow">return[/color] 1; /* ハンドル値が不正? */
    
    /* (!)ファイルの読込位置を先頭に変更 */
    (void)FileRead_seek( FileHandle, 0, SEEK_SET);
        
    for (Loop = 0; LineNo > Loop && FileRead_eof(FileHandle) == 0;) {
        (void)FileRead_gets(StrBuf, BufSize, FileHandle);
        Loop++;
    }
    
    /* 返る前に、ファイルポインタの位置を元に戻す */
    (void)FileRead_seek(FileHandle, BeforePos, SEEK_SET);
    
    /* Loop行読み込んだが、それが欲しい行ではなかったら */
    if ( Loop != LineNo )
        return 2;
    
    return 0;
}
---------- 自作関数ここまで ----------
下に続く…
(※同日8:49, 9:03 所々ミスがあったので修正)

朽木

Re:txtファイル文章

#11

投稿記事 by 朽木 » 16年前

メッセージ長いって言われた…(´・ω・`) 以下追加分

後々考えてみると、描画ループでファイル読み込みは怖いので、

別々にした方が良いかもしれません。
char Key[256];

text(&Buf[0]); /* void text(char *Buf) */

[color=Yellow">while[/color] ( device is running )
{
    BeginScene
    [color=Yellow">if[/color] ( ReloadFlag is true ) {
        text(&Buf[0]); /* 再読み込みを行う */
    }
    /* キーの押下状態を取得 */
    if ( GetHitKeyStateAll(&Key[0]) == 0 ) {
        if ( Key[ KEY_INPUT_X ] == 1 )
            (void)DrawString(,,Buf,);
    }
    EndScene
}

にするとか。
(※追加: キー判定忘れてました)

ice

Re:txtファイル文章

#12

投稿記事 by ice » 16年前

こんばんわ
皆様ご指導有難うございます。
昨晩より色々いじって考えているのですが、fopenに対してこのようなエラーが出ました。

"microsoft visual studio 9.0\vc\include\stdio.h(237) : 'fopen' の宣言を確認してください。"
他にも
"warning C4996: 'fopen': This function or variable may be unsafe. Consider using fopen_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details."

詳しくないのでよく分からないのですが、Microsoft Visual C++ 2008では使えないのでしょうか。


ただたんにtxtの1行目を読むなら
以下ような文でいいのかと思いDXライブラリ、リファレンス例文を書き換えてみました。
しかし、エラーは出ないもののテキストは読み込みませんでした。
一筋縄にはいかないようです。画像ならDXライブラリだと簡単に絵画出来るのにorz

void text()
{
int FileHandle ;
char String[256] ;

// test.cpp ファイルを開く
FileHandle = FileRead_open( "aaa01.txt" ) ;

// 一行読む
FileRead_gets( String, 256, FileHandle ) ;

// 画面に描画
DrawString( 0, 0, String, GetColor( 255,255,255 ) ) ;

// キー入力を待つ
WaitKey() ;

// ファイルを閉じる
FileRead_close( FileHandle ) ;


}

SCI

Re:txtファイル文章

#13

投稿記事 by SCI » 16年前

絵画できる→描画できる、のことですね?
ファイルが存在していればそれで出来るはずですが・・・
もちろん、基本的なループ部分は作り、WaitKey()ではキーを押して処理を進めていますよね?

朽木

Re:txtファイル文章

#14

投稿記事 by 朽木 » 16年前

1. 'fopen' の宣言を確認してください。

#include <stdio.h> を追加

2. warning C4996

代わりにfopen_sを使えば消えます
解決できなかったらごめんなさい

御津凪

Re:txtファイル文章

#15

投稿記事 by 御津凪 » 16年前

朽木さんの発言の補足です。

2. warning C4996

により、

1. 'fopen' の宣言を確認してください。

の補足文章が出ています。

つまり、この2行で一つの事象に対する文章です。

また、 warning と単語がある通り、これは警告です。
プログラムは生成され、実行できますが、
コンパイラは「これでいいのか?」という時に出してきます。
(コンパイルオプションでその度合いを調整できます)

この場合の警告(C4996)は、より安全な関数を使用してください、というような警告なので、
特に実行に問題はありません。(正しい使い方をしていれば)
なので、他にエラーが出ていなければプログラムは実行できるはずです。

ちなみに、同様の警告を出すものとして、 strcpy や strcat などがあります。
それぞれ _s がついた関数を使用することで警告を無くすことができます。
(引数が違ったり、戻り値が違ったりするので注意)


> 朽木さん
> #include <stdio.h> を追加

これは既に追加・あるいは別のところでインクルードされていると思います。
そうでなければ、本当のエラーが出てくるはずです。

ice

Re:txtファイル文章

#16

投稿記事 by ice » 16年前

SCI様
先ほど投稿したNo:30858のプログラムですが、
裏画面使用後に必要な1行、text();が抜けていました。
修正後、描画出来ました有難うございます。

しかし、ソフト起動後テキストは読み込むのですが、他のプログラムが同時に動きません。
キー入力後は他のプログラムが動く(テキストは消えます)のですが、
なぜテキスト描画と同時に動かないのでしょうか。
後、初めに書いていた
if( Key[ KEY_INPUT_X ] == 1 )
で構文を間に入れてたりして色々試してみましたが、
(既に他のプログラムが動いている時)Xキーを押してもテキストを読み込みせず何も起こりませんでした。

朽木様
申し訳ないのですが、
今の私のレベルでは難しいので、もう少し理解してから参考にさせていただきます。

SooA

Re:txtファイル文章

#17

投稿記事 by SooA » 16年前

御津凪さんが書いておられるように warning C4996 は
警告文で特に問題はありません、表示が気になるようであれば、
下記一文を追加してやれば非表示にすることができます。
#pragma warning( disable : 4996 )

SCI

Re:txtファイル文章

#18

投稿記事 by SCI » 16年前

>他のプログラム
文字列描画以外の処理、ということですか?

修正したループ処理はどのように書いたのでしょう。

#本当は読み込みと描画を分けたほうがいいのですが、これは後からでもいいでしょう。

ice

Re:txtファイル文章

#19

投稿記事 by ice » 16年前

SCI様
プログラムを勉強していたわけではないので専門用語には疎いのですが
他のプログラムというと
ゲームでのキャラクターの描画、他の画像読み込み、BGMとかです。
今回テキストを読み込んだ後キー入力しないとそれらが動作始めませんでした。
そしてテキスト読み込みする際にキー入力を必要にした場合はテキストの読み込みが出来ませんでした。

ループ処理というとどういうことでしょうか。
テキスト関係はtext.cppに書いておりそれをmain.cppで読み込みしています。(表現はこれでいいのでしょうか)

text.cppには
----------------------------------------------------------
#include "DxLib.h"
#include "extern.h"

void text()
{
int FileHandle ;
char String[256] ;
// test.cpp ファイルを開く
FileHandle = FileRead_open( "text00.txt" ) ;
// 一行読む
FileRead_gets( String, 256, FileHandle ) ;
// 画面に描画
DrawString( 0, 0, String, GetColor( 255,255,255 ) ) ;
// キー入力を待つ
WaitKey() ;
// ファイルを閉じる
FileRead_close( FileHandle ) ;
}
----------------------------------------------------------

main.cppはこんなかんじです。(色々入ってますが、そのままおいておきます///)
----------------------------------------------------------
#include "DxLib.h"
#include "global.h"

int WINAPI WinMain( HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow )
{
extern void img_sound_load();
extern void SetColor();
extern void Background();
extern void playerstatus1();
extern void Bgm();
extern void enemydata1();
extern void playerdata1();
extern void playercontrol1();
extern void enemycontrol1();
extern void Target();
extern void FpsTimeFanction();
extern void text();
int RefreshTime=0;

ChangeWindowMode( TRUE ) ;
if( DxLib_Init() == -1 ) return -1;

SetDrawScreen( DX_SCREEN_BACK ) ; //裏画面を使用する。

img_sound_load();
SetColor();
playerdata1();
enemydata1();
text();
Bgm();

int aaa,bbb;
aaa=0;
bbb=0;
while(ProcessMessage() == 0 && GetHitKeyStateAll(Key) == 0)
{

if( Key[ KEY_INPUT_SPACE ] == 1 )
{
bbb++;
if(aaa==1&&bbb==1){
aaa=0,
WaitTimer(100),
bbb=0;}
else if (bbb==1){

aaa=1,
WaitTimer(100),
bbb=0;}
}
RefreshTime = GetNowCount(); //今の時間を取得
ClearDrawScreen(); //裏画面のデータを全て削除
Background();

DrawFormatStringToHandle(0,20, color_white,font_status,"bbb%d" , bbb);
DrawFormatStringToHandle(0,40, color_white,font_status,"aaa%d" , aaa);

if(aaa==0)
{
playerstatus1();
enemycontrol1();
playercontrol1();
Target();
FpsTimeFanction();
}
ScreenFlip(); //裏画面データを表画面へ反映
counter++;

if(Key[KEY_INPUT_ESCAPE]==1) break; //Escapeが押されたら終了
while(GetNowCount() - RefreshTime < 17);//1周の処理が17ミリ秒になるまで待つ
}


DxLib_End() ;
return 0 ;
}
----------------------------------------------------------

nayo

Re:txtファイル文章

#20

投稿記事 by nayo » 16年前

画像ハンドルなどと同じように会話文も保存するための変数を用意して画像などと一緒に文章もロードしてやれば良いかと思います
すでに書かれてますが読み込みと描画は分けるべきです

あとはゲームの状態が文章の描画が必要な状態になったら描画関数を画像を描画するのと同じように毎ループ呼び出してやればいいかと
ちょっと分かりづらいですがこんな流れです

朽木

Re:txtファイル文章

#21

投稿記事 by 朽木 » 16年前

>No:30863(御津凪さん)
指摘ありがとうございます。

>No:30868(iceさん)
お役に立てなくてごめんなさい(´・ω・`)

SCI

Re:txtファイル文章

#22

投稿記事 by SCI » 16年前

iceさん
やはり、読み込みと描画を分けて作ったほうが分かりやすいかも知れません。
このソースだと「読み込み&表示」を最初に1度だけ行っています。
「読み込み」は最初の1度でいいのですが、「表示」は毎フレーム行う必要があります。

まず、文字数や行数は無制限なのでしょうか?

ice

Re:txtファイル文章

#23

投稿記事 by ice » 16年前

こんばんは
nayo様
本日まだプログラムをいじっていないので
上に書かれていることを試していないので後でやってみますね。

朽木様
サンプルお手数おかけしました。
必要となるプログラムがこんなに長文になるとは思ってませんでした。
コピペしてあるのでもう少し勉強してから試してみます。

SCI様
表示を毎フレームというのはtextのことでしょうか。(他のプログラムも毎フレーム行っていない?)
文字数は1行30文字程度、行数は80もあれば十分だと思います。
最終的に作りたいものはゲームで言うと決定ボタンクリックで3行ずつ読むようなかんじでしょうか。
なおtxtで読ませたい理由は、ゲームの型を作ってから知人達と作成していく際の都合です。

ice

Re:txtファイル文章

#24

投稿記事 by ice » 16年前

今やっと同時に表示できました!有難うございます!!
表示に関してはOKってことで、キー入力で表示するところまでは成功しました。
そしてこのままですと1フレームごとに1行ずつ表示するようです。(キーを押しっぱなしにするとすぐに最終行まで行く)
2行同時に出すとかキー入力にウェイトを置くとか、このスレッドにある皆様のプログラムを見ながら考えてみます。

09/03/18追記
うまくいきました有難うございます。

閉鎖

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