ページ 11

ファイルの読み込み

Posted: 2008年11月04日(火) 15:22
by 初心者
現在visualc++6.0で勉強しています。課題であるテキストファイルを読み込んで(数字と英大文字のみのテキストファイル)数字と英大文字を切り分けて一行ずつ表示するプログラムを作れという課題がでました。

私がやったのはダイアログ上のEditボックスにテキストファイルを読み込んで一行ずつ貼り付けていく
というプログラムをまず考えました。そこから切り分けの作業を組み込もうと考えてるのですが
思いつきません。

void(){
FILE *p;
CString a;
cha buf[1001];
CFileDialog fdlg(TRUE,"","*.*");
if(fdlg.DoModal()!=IDOK)
return;
a=fdlg.GetPathName();
CEdit *p;
p=(CEdit *)GetDlgItem(IDC_EDIT1);
if((fp=fopen(a,"r"))==NULL)
return
while(fgets(buf,1000,fp)!=NULL){
buf[strlen(buf)-1]='\0';
strcat(buf,"\r\n");
int n=p->GetWindowTextLength();
p->SendMessage(EM_SETSEL,n,n);
p->SendMessage(EM_REPLACESEL,0,(LPARAM)buf);
}
fclose(fp);
}

というプログラムでダイアログのEditボックスにファイルを読み込み
一行ずつ貼り付けていくという作業ができました。

このプログラムにさらに文字と数字を切り分けて表示する作業を組み込みたいのです。
例えば1行目に
M02M61X0F2.5B1FG1231などが書かれているテキストファイルを

[M][02][M][61][x][0][F][2.5][1][FG][1231]
などのように分けて表示するプログラムです。

教えてください

Re:ファイルの読み込み

Posted: 2008年11月04日(火) 15:55
by いけやん
数値かどうか::isdigit
アルファベットかどうか::isalpha

この辺りを使って、
C = 判定したいもの
isdigit、isdigitも0以外が返ってくると
正なので、0以外が返って来たら表示としてみては、どうでしょう?

リンクです。
http://homepage3.nifty.com/mmgames/c_gu ... ib.html#S3

Re:ファイルの読み込み

Posted: 2008年11月04日(火) 16:02
by 御津凪
とりあえずその分けるプログラムだけを書きました。(ブロック処理です)
{
	bool isNum;
	char* ch = buf;
	char* nh = buf + strlen(buf);
	char  subbuf[128];
	int   n = 0;

	while(ch < nh){
		if(n == 0){
			inNum = (isupper(*ch) == 0); // 最初に大文字かどうかをチェック
			subbuf[n] = *ch;
			++n;
		}
		else if(isNum != (isupper(*ch) != 0)){ // 一つ前の文字タイプと違う場合
				subbuf[n] = '\0';
				n = 0;
				/* ここで subbuf に対して一行出力を行う */
			}
			subbuf[n] = *ch;
			++n;
		}
		++ch;
	}
}
何をしているのか読み取ってから適切な場所に書き込んでください。


特に質問とは関係はないですが、提示したソースはコンパイルが通りません。
あとソースはプレタグで囲んでくださいね。

Re:ファイルの読み込み

Posted: 2008年11月04日(火) 18:27
by 初心者
{
bool isNum;
char* ch = buf;
char* nh = buf + strlen(buf);
char subbuf[128];
int n = 0;

// このプログラムで読み込むテキストファイルは英大文字と数字のみの構成なので大文字かどうかは
判断するプログラムは省きました。

while(ch < nh){
if(isNum != (isupper(*ch) != 0)){ // 一つ前の文字タイプと違う場合
subbuf[n] = '\0';
n = 0;
/* ここで subbuf に対して一行出力を行う */

                   while(fgets(subbuf,80,fp)!=NULL){
buf[strlen(subbuf()-1]='\0';
strcat(subbuf,"\r\n");

int m=p->GetWindowTextLength();
   p->SendMessage(EM_SETSEL,m,m);      //カレットを文字列の最後尾に移動してそこに貼り付ける
   p->SendMessage(EM_REPLACESEL,o,(LPARAM)buf); //ファイルから入力した一行を張り込む
  }
fclose(fp);
}

}
buf[n] = *ch;
++n;
}
++ch;
}
}


とすると予期せぬEOFが検出されましたとでて実行できません。
どこか間違ってるでしょうか
※ファイルのオープンとエデットボックスのプログラムは省いております。
初心者の為浅い探りしかできなくて申し訳ない。

Re:ファイルの読み込み

Posted: 2008年11月04日(火) 18:31
by Mist
規約を守って字下げしてもらえませんか。
読みにくいです。

Re:ファイルの読み込み

Posted: 2008年11月04日(火) 18:40
by Mist
私のほうで字下げしてみましたが、提示のソースは中カッコの数が不一致で
解析できませんけど。
{ 
    bool isNum; 
    char* ch = buf; 
    char* nh = buf + strlen(buf); 
    char subbuf[128]; 
    int n = 0; 

    // このプログラムで読み込むテキストファイルは英大文字と数字のみの構成なので大文字かどうかは 
    判断するプログラムは省きました。 

    while(ch < nh){ 
        if(isNum != (isupper(*ch) != 0)){ // 一つ前の文字タイプと違う場合 
            subbuf[n] = '\0'; 
            n = 0; 
            /* ここで subbuf に対して一行出力を行う */ 

            while(fgets(subbuf,80,fp)!=NULL){ 
                buf[strlen(subbuf()-1]='\0'; 
                strcat(subbuf,"\r\n"); 

                int m=p->GetWindowTextLength(); 
                p->SendMessage(EM_SETSEL,m,m);      //カレットを文字列の最後尾に移動してそこに貼り付ける 
                p->SendMessage(EM_REPLACESEL,o,(LPARAM)buf); //ファイルから入力した一行を張り込む 
            } 
            fclose(fp); 
        } 
    }
    buf[n] = *ch; 
    ++n; 
} 
++ch; 
} 
}

Re:ファイルの読み込み

Posted: 2008年11月04日(火) 19:00
by 御津凪
> このプログラムで読み込むテキストファイルは英大文字と数字のみの構成なので大文字かどうかは
> 判断するプログラムは省きました。

isupper 関数は、『英字の大文字』かをチェックする関数です。
(英大文字とはこの意味ですよね?)

また、それを省いた状態だと、
isNum が初期化されないままになってしまいます。(最初の部分が正しく分けられない)

私の書いたプログラムにある、
/* ここで subbuf に対して一行出力を行う */
の部分時点で、既に subbuf には数値と英大文字に分けた形で入っています。
それに、 buf に既に読み込んだデータがある(ファイルから全て読み出した後)
として書いたプログラムですので、これでは正しく処理できません。

# どういう処理が行われていくのか理解できていますでしょうか?
# 他人のソースコードを解読するのも勉強です。

Re:ファイルの読み込み

Posted: 2008年11月04日(火) 19:25
by たかぎ
ほとんど揚げ足に近いですが...

> isupper 関数は、『英字の大文字』かをチェックする関数です。

厳密にいうと違います。
isupper関数は、大文字、またはiscntrl、isdigit、ispunctもしくはisspaceのいずれも真とならない文化圏固有の文字集合の中の文字かどうかを判定するものです。
つまり、ラテン文字であっても英字(英語の文字)以外の文字(具体的にはアクセントやウムラウトがついた文字など)や、キリル文字やギリシャ文字などの非ラテン文字の大文字かどうかを判定することも可能です。

一応念のため。

Re:ファイルの読み込み

Posted: 2008年11月04日(火) 19:30
by バグ
もし、ソース内のCStringがMFCのCStringであるならば、色々と便利なメソッドが用意されていると思いますよ。そうでないならば、失礼しました(^_^;)

Re:ファイルの読み込み

Posted: 2008年11月04日(火) 19:51
by 初心者
今一度しっかり見直します。それでわからなかったらまた教えてください。
※字下げの件は特殊なコマンドが必要なの知らなかったので・・申し訳ない。
※一番上のソースはおそらく最初の文がおかしいのだと思います。コード編集すると最初から
書かれているのがそれです。誤解しやすいように書いてしまいました。

Re:ファイルの読み込み

Posted: 2008年11月05日(水) 11:37
by 初心者
上記のプログラムでは
読み込み→仕分け→また読み込みになるのか同じ結果(仕分けがされていない状態での1行表示)
になってしまいました。

Re:ファイルの読み込み

Posted: 2008年11月05日(水) 13:12
by 御津凪
> 読み込み→仕分け→また読み込みになるのか同じ結果(仕分けがされていない状態での1行表示)

そのプログラムを見せていただけませんか?
…と、その前に、
p->SendMessage(EM_REPLACESEL,0,(LPARAM)buf);
では無く、
p->SendMessage(EM_REPLACESEL,0,(LPARAM)subbuf);
としないと、せっかく subbuf に仕分けた文字列が表示されません。



> たかぎさん
そうでした。MSDNライブラリでも「英字」とはかかれていませんでしたね。

Re:ファイルの読み込み

Posted: 2008年11月05日(水) 13:35
by 初心者
{
bool isNum;
	char* ch = buf;
	char* nh = buf + strlen(buf);
	char  subbuf[128];
	int   n = 0;
FILE *fp; 
CString a; 
char buf[1001]; 
CFileDialog fdlg(TRUE,"","*.*"); 
if(fdlg.DoModal()!=IDOK) 
return; 
a=fdlg.GetPathName(); 
CEdit *p; 
p=(CEdit *)GetDlgItem(IDC_EDIT1); 
if((fp=fopen(a,"r"))==NULL) 
return


while(ch < nh){
if(n == 0){
			isNum = (isupper(*ch) == 0); // 最初に大文字かどうかをチェック
			subbuf[n] = *ch;
			++n;
		}
		else if(isNum != (isupper(*ch) != 0)){ // 一つ前の文字タイプと違う場合
				subbuf[n] = '\0';
				n = 0;
				/* ここで subbuf に対して一行出力を行う */
                                   while(fgets(subbuf,80,fp)!=NULL){ 
                buf[strlen(subbuf()-1]='\0'; 
                strcat(subbuf,"\r\n"); 

                int m=p->GetWindowTextLength(); 
                p->SendMessage(EM_SETSEL,m,m);                                                  p->SendMessage(EM_REPLACESEL,o,(LPARAM,subbuf);           } 
            fclose(fp); 

			}
			subbuf[n] = *ch;
			++n;
		}
		++ch;
	}
今仕分け入力が全くされてないことに気づきました・・
printfが何か使えないのでどうしたものかと

Re:ファイルの読み込み

Posted: 2008年11月05日(水) 14:08
by いけやん
Printfの代わり
VC++だという事ですが、
MFCなんですか?わかりませんが、
MFCとかなら
MessageBox系が使えますよ。

moji = "あああ"
AfxMessageBox(moji)

結果
あああ

Re:ファイルの読み込み

Posted: 2008年11月05日(水) 14:15
by Mist
人に見てもらうプログラムとしては誤字多すぎです。

ちょっと見ただけでも

> FILE *p;
*pじゃなくて*fpよね。

> cha buf[1001];
chaじゃなくてcharよね。

isNumもinNumになってたりしますし。

Re:ファイルの読み込み

Posted: 2008年11月05日(水) 14:19
by 初心者
MFCです。
その入力の仕方は知っているのですが今求められてるのは
ファイルから読み込んで仕分けした内容を表示していきます。
ER121DF45F4TT5という文字列がテキストファイルの一行目にあれば
[E[/url][121][DF][45][F][4][TT][5]などのようにです。
これもMessageBoxでできるのでしょうか

Re:ファイルの読み込み

Posted: 2008年11月05日(水) 14:26
by 御津凪
とりあえず提示していただいたコードから修正しました。
(そのままコンパイルが通るか確認していませんが)
どう変わっているか、よく読んでくださいね。
(ファイルから読み込む配列 buf と仕分け用の作業領域の subbuf を間違えないように)
{

    FILE *fp;
    CString a;
    char buf[1001];

    bool  isNum;
    char* ch = buf;
    char* nh = buf + strlen(buf);
    char  subbuf[128];
    int   n = 0;

    CFileDialog fdlg(TRUE,"","*.*");
    if(fdlg.DoModal()!=IDOK) return;
    a=fdlg.GetPathName();
    CEdit *p;
    p=(CEdit *)GetDlgItem(IDC_EDIT1);
    if((fp=fopen(a,"r"))==NULL) return;


    while(fgets(buf,1000,fp)!=NULL){
        buf[strlen(buf)-1]='\0';
    }
    fclose(fp);


    while(ch < nh){
        if(n == 0){
            isNum = (isupper(*ch) == 0); // 最初に大文字かどうかをチェック
        }
        else if(isNum != (isupper(*ch) != 0)){ // 一つ前の文字タイプと違う場合
            subbuf[n] = '\0';
            n = 0;
            /* ここで subbuf に対して一行出力を行う */

            int m=p->GetWindowTextLength();
            p->SendMessage(EM_SETSEL,m,m);
            p->SendMessage(EM_REPLACESEL,o,(LPARAM)subbuf);

        }
        subbuf[n] = *ch;
        ++n;
        ++ch;
    }
}
> 人に見てもらうプログラムとしては誤字多すぎです。
Mist さんのおっしゃるとおり、実行できているコードそのままを提示していただけると
助かるのですが…。

> isNumもinNumになってたりしますし。
あ、すいません、そこは私の間違いでした(汗

Re:ファイルの読み込み

Posted: 2008年11月05日(水) 14:34
by バグ
MFCならば、こういう場合は、EditBoxよりもListBoxを使うべきじゃないかな?

Re:ファイルの読み込み

Posted: 2008年11月05日(水) 14:35
by 初心者
申し訳ないです。プログラムできるPCとネットできるPCが完全に分かれている為、
手書きで写して書いています。

Re:ファイルの読み込み

Posted: 2008年11月05日(水) 14:52
by 初心者
ビルドしてみましたがエラーは出ないのですが
Debug Assertion Failed!
program:ファイル名
files:fgets.c
Line:60

Expression str!=NULL

と出て実行できないのですがどこが悪いのでしょう

Re:ファイルの読み込み

Posted: 2008年11月05日(水) 15:08
by 御津凪
恐らく、 fgets 関数に渡す 第一引数が NULL になっているのではないでしょうか?
上記のプログラムの通りに書かれていれば、そこに buf が入るはずですが。

ブレイクポイントを使って変数の値を確かめてみましたか?

ブレイクポイントを付けると、実行時にそこで一旦止まるので、
その時の変数等をチェックすることができますよ。
詳しい方法は↓に書かれています。
http://www.play21.jp/board/formz.cgi?ac ... 2971#22933

Re:ファイルの読み込み

Posted: 2008年11月05日(水) 15:12
by バグ
m_listbox1 = 数字表示用リストボックス
m_listbox2 = アルファベット表示用リストボックス

上記の2つのコントロールをリソースエディタで追加してください。
void FileRead()
{
	// リストボックスのアイテムを全て消去する
	INT i = 0;
	for (i = 0; m_listbox1.GetCount(); ++i) m_listbox1.DeleteString(0);
	for (i = 0; m_listbox2.GetCount(); ++i) m_listbox2.DeleteString(0);

	// ファイルを読み込んでリストボックスへ割り当てる
	CFileDialog dlg(TRUE);
	if (dlg.DoModal() == IDOK)
	{
		CHAR buf = '\0';
		BOOL isnum = FALSE;
		CString data = "";
		CFile file(dlg.GetPathName(), CFile::modeRead);

		while (file.Read(&buf, 1) >= 1)
		{
			// 0~9かドット(小数点?)の場合は数字として扱い、それ以外はアルファベットとする
			if (isdigit((int)buf) != 0 || buf == '.')
			{
				if (data.GetLength() == 0)
				{
					data += buf;
					isnum = TRUE;
				}
				else if (isnum == FALSE)
				{
					m_listbox2.AddString(data);
					data = buf;
					isnum = TRUE;
				}
				else
				{
					data += buf;
				}
			}
			else
			{
				if (data.GetLength() == 0)
				{
					data += buf;
					isnum = FALSE;
				}
				else if (isnum == TRUE)
				{
					m_listbox1.AddString(data);
					data = buf;
					isnum = FALSE;
				}
				else
				{
					data += buf;
				}
			}
		}

		// 最後に読み込んだ文字列をリストボックスへ追加する
		if (isnum == TRUE)
		{
			m_listbox1.AddString(data);
		}
		else
		{
			m_listbox2.AddString(data);
		}

		// ファイルを閉じる
		file.Close();
	}
}

Re:ファイルの読み込み

Posted: 2008年11月05日(水) 15:15
by バグ
すみません、ちょっと修正…
VOID FileRead() 
{
	// リストボックスのアイテムを全て消去する
	INT i = 0;
	for (i = 0; m_listbox1.GetCount(); ++i) m_listbox1.DeleteString(0);
	for (i = 0; m_listbox2.GetCount(); ++i) m_listbox2.DeleteString(0);

	// ファイルを読み込んでリストボックスへ割り当てる
	CFileDialog dlg(TRUE);
	if (dlg.DoModal() == IDOK)
	{
		CHAR buf = '\0';
		BOOL isnum = FALSE;
		CString data = "";
		CFile file(dlg.GetPathName(), CFile::modeRead);

		while (file.Read(&buf, 1) >= 1)
		{
			// 0~9かドット(小数点?)の場合は数字として扱い、それ以外はアルファベットとする
			if (isdigit((int)buf) != 0 || buf == '.')
			{
				if (data.GetLength() == 0)
				{
					data += buf;
					isnum = TRUE;
				}
				else if (isnum == FALSE)
				{
					m_listbox2.AddString(data);
					data = buf;
					isnum = TRUE;
				}
				else
				{
					data += buf;
				}
			}
			else
			{
				if (data.GetLength() == 0)
				{
					data += buf;
					isnum = FALSE;
				}
				else if (isnum == TRUE)
				{
					m_listbox1.AddString(data);
					data = buf;
					isnum = FALSE;
				}
				else
				{
					data += buf;
				}
			}
		}

		// 最後に読み込んだ文字列をリストボックスへ追加する
		if (data.GetLength() != 0)
		{
			if (isnum == TRUE)
			{
				m_listbox1.AddString(data);
			}
			else
			{
				m_listbox2.AddString(data);
			}
		}

		// ファイルを閉じる
		file.Close();
	}
}

Re:ファイルの読み込み

Posted: 2008年11月05日(水) 15:16
by Mist
現在のソースがどのような状態かわからないので推測になりますが
fgetsの引数にNULLを渡したときに上記のエラーになったと記憶しています。
(str!=NULLとなっているのでたぶんfp側かな?)

御津凪さんのソースであればそうはならないはずですが、何か間違ってませんか?

Re:ファイルの読み込み

Posted: 2008年11月05日(水) 15:46
by 初心者
見る限り全く同じです。
そのブレイクポイントなんですがその記事見る限りVisualC++2008系で
私が使っているVisualC++6.0のMFCには上記の通りではできませんでした。
もう1回最初から書き直してみます。

Re:ファイルの読み込み

Posted: 2008年11月05日(水) 15:49
by バグ
VC++6.0でのブレイクポイント設定方法は、ブレイクポイントを設定したい行へカーソルを合わせて、手の形をしたアイコンを押せば設定されます。削除したい場合は再度同じ操作を行って下さい。

Re:ファイルの読み込み

Posted: 2008年11月05日(水) 16:05
by 初心者
ブレイクポイントを

while(fgets(buf,1000,fp)!=NULL){

の←につけてビルド、実行、ファイル指定、ok、の順に押しても同じ結果に・・
変数はどこでチェックできるのでしょうか

Re:ファイルの読み込み

Posted: 2008年11月05日(水) 16:29
by 初心者
書き直すとDebugの件はでなくなりましたが
フフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフ4Fなど文字化けしてしまいます。
これはどこが悪いのでしょうか

Re:ファイルの読み込み

Posted: 2008年11月05日(水) 16:30
by バグ
ブレイクポイントでプログラムは停止しましたか?
停止したのならば、その状態でコードエディタの確認したい変数へマウスカーソルを合わせれば表示されます。
継続的に確認をしたいのならば、変数へマウスカーソルを合わせて右クリックした後に、クイックウォッチをクリック、そして追加ボタンをクリックすれば変化を追いかける際に便利です。

Re:ファイルの読み込み

Posted: 2008年11月05日(水) 16:32
by バグ
>>書き直すとDebugの件はでなくなりましたが
フフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフフ4Fなど文字化けしてしまいます。
これはどこが悪いのでしょうか


そういわれましても、書き直したソースと読み込んだファイルが無ければ誰にも分からないと思いますよ。

Re:ファイルの読み込み

Posted: 2008年11月05日(水) 16:47
by 初心者
[
FILE *fp;
    CString a;
    char buf[1001];

    bool  isNum;
    char* ch = buf;
    char* nh = buf + strlen(buf);
    char  subbuf[128];
    int   n = 0;

    CFileDialog fdlg(TRUE,"","*.*");
    if(fdlg.DoModal()!=IDOK) return;
    a=fdlg.GetPathName();
    CEdit *p;
    p=(CEdit *)GetDlgItem(IDC_EDIT1);
    if((fp=fopen(a,"r"))==NULL) return;


    while(fgets(buf,1000,fp)!=NULL){
        buf[strlen(buf)-1]='\0';
    }
    fclose(fp);


    while(ch < nh){
        if(n == 0){
            isNum = (isupper(*ch) == 0); // 最初に大文字かどうかをチェック
        }
        else if(isNum != (isupper(*ch) != 0)){ // 一つ前の文字タイプと違う場合
            subbuf[n] = '\0';
            n = 0;
            /* ここで subbuf に対して一行出力を行う */

            int m=p->GetWindowTextLength();
            p->SendMessage(EM_SETSEL,m,m);
            p->SendMessage(EM_REPLACESEL,o,(LPARAM)subbuf);

        }
        subbuf[n] = *ch;
        ++n;
        ++ch;
    }
}

上記がソースで

読み込んだファイルは
M70
M67
M85
G40
G92X2.203Y40.078
H1=138
G01G41X0.F2.5H1E1051M90
Y0.
X5.321
Y3
X10.781Y46.211
などが20行ぐらい続いてるファイルです。

Re:ファイルの読み込み

Posted: 2008年11月05日(水) 17:16
by 御津凪
char* ch = buf;
    char* nh = buf + strlen(buf);
この部分を、
char* ch;
    char* nh;
として、ファイルからデータを読み込んだ後( fclose(fp); 以降)に、
ch = buf;
    nh = buf + strlen(buf);
を、入れてください。
変数宣言時での代入時では buf には不正な値が入ったままなので、
そこの strlen が正常に動作しませんでした。

Re:ファイルの読み込み

Posted: 2008年11月05日(水) 17:22
by バグ
ソース云々以前に何点かツッコミをさせてください。

>>読み込んだファイルは
>>M70
>>M67
>>M85
>>G40
>>G92X2.203Y40.078
>>H1=138
>>G01G41X0.F2.5H1E1051M90
>>Y0.
>>X5.321
>>Y3
>>X10.781Y46.211
>>などが20行ぐらい続いてるファイルです。


これって、"="はあるし…


>>数字と英大文字のみのテキストファイル


と書かれていた前提が崩れている気がするのですが…

更に言えば


>>X5.321

こういう場合は、[X][5.321]とするようですけど…

>>Y0.

というような場合はどういう風に扱うのですか?

後だし条件が多すぎですね。詳細な仕様を提示しなければ、いつまでたってもイタチごっこですよ。

Re:ファイルの読み込み

Posted: 2008年11月05日(水) 17:24
by バグ
あと、提示されたソースではコンパイルを通りません。

>> p->SendMessage(EM_REPLACESEL,o,(LPARAM)subbuf);

この行で、突然に謎の"o"という変数が現れています。
おそらく数値のゼロと書き間違えたのだろうとは思いますが…。

Re:ファイルの読み込み

Posted: 2008年11月05日(水) 17:25
by Mist
御津凪さんのソースをあまりしっかり見てなかったんですが

> while(fgets(buf,1000,fp)!=NULL){
> buf[strlen(buf)-1]='\0';
> }

この部分はちょっとおかしくないですかね?
これだと最後の一行しかbufに残らないですよね。(それでいいのだったら無視してください)
あと、
> buf[strlen(buf)-1]='\0';
ファイルの最後の行が以下のような場合、最後の文字列の最後の一文字を消してしまいますよね。



文字列[改行]
文字列[EOF]

もうひとつ、空のファイルの場合にbufが不定値のままですね。

Re:ファイルの読み込み

Posted: 2008年11月05日(水) 17:36
by 初心者
>>これって、"="はあるし…


数字と英大文字のみのテキストファイル


と書かれていた前提が崩れている気がするのですが…


この部分は私も課題出されたときに表示されていませんでした。ですのでこの部分はどう表示されてても構いません。

>>>Y0.

というような場合はどういう風に扱うのですか?

[Y][0.]です。



先ほど御津凪さんに指摘されたところを修正し実行してみると、何も表示されませんでした。

Re:ファイルの読み込み

Posted: 2008年11月05日(水) 18:10
by フリオ
 
 差し支えなければ、その課題文を丸々ここに載せてはどうですか。
 

Re:ファイルの読み込み

Posted: 2008年11月05日(水) 18:19
by 初心者
添付したテキストファイルを一行ずつ文字と数字に切り分けて表示するようなプログラムを作成せよ
例えばG01G41X0.F2.5H1E1061M90なら
[G][01]
[G][41]
[X][0.]
[F][2.5]
[H][1]
[E][1061]
[M][90]
の様にです。

Re:ファイルの読み込み

Posted: 2008年11月05日(水) 18:41
by バグ
それならば、私が投稿した(No:23522の記事)ソースで動きませんか?(^_^;)
ちょっと改造したのを、もう一度載せときますね。
あらかじめ、ListBoxコントロールをダイアログに2つ貼り付けておいてください。

void ReadFile()
{
	// リストボックスのポインタを取得する
	CListBox* listbox1 = (CListBox*)GetDlgItem(IDC_LIST1);
	CListBox* listbox2 = (CListBox*)GetDlgItem(IDC_LIST2);

	// リストボックスのアイテムを全て消去する
	INT i = 0;
	for (i = 0; listbox1->GetCount(); ++i) listbox1->DeleteString(0);
	for (i = 0; listbox2->GetCount(); ++i) listbox2->DeleteString(0);

	// ファイルを読み込んでリストボックスへ割り当てる
	CFileDialog dlg(TRUE);
	if (dlg.DoModal() == IDOK)
	{
		CHAR buf = '\0';
		BOOL isnum = FALSE;
		CString data = "";
		CFile file(dlg.GetPathName(), CFile::modeRead);

		while (file.Read(&buf, 1) != FALSE)
		{
			// 0~9かドット(小数点?)の場合は数字として扱い、それ以外はアルファベットとする
			if (isdigit((int)buf) != 0 || buf == '.')
			{
				if (data.GetLength() == 0)
				{
					data += buf;
					isnum = TRUE;
				}
				else if (isnum == FALSE)
				{
					listbox2->AddString(data);
					data = buf;
					isnum = TRUE;
				}
				else
				{
					data += buf;
				}
			}

			if (isalpha((int)buf) != 0)
			{
				if (data.GetLength() == 0)
				{
					data += buf;
					isnum = FALSE;
				}
				else if (isnum == TRUE)
				{
					listbox1->AddString(data);
					data = buf;
					isnum = FALSE;
				}
				else
				{
					data += buf;
				}
			}
		}

		// 最後に読み込んだ文字列をリストボックスへ追加する
		if (data.GetLength() != 0)
		{
			if (isnum == TRUE)
			{
				listbox1->AddString(data);
			}
			else
			{
				listbox2->AddString(data);
			}
		}

		// ファイルを閉じる
		file.Close();
	}
}

Re:ファイルの読み込み

Posted: 2008年11月05日(水) 20:06
by 初心者
わかりやすい回答ありがとうございます。
少し試してみて考えてみます。

Re:ファイルの読み込み

Posted: 2008年11月06日(木) 08:29
by バグ
すみません、上記のソースで間違いを発見しました…orz
もとのソースでも、結果オーライ的に問題はないのですが、気持ち悪いので下記のように修正してください。
// リストボックスのアイテムを全て消去する
INT i = 0;
for (i = 0; i < listbox1->GetCount(); ++i) listbox1->DeleteString(0);
for (i = 0; i < listbox2->GetCount(); ++i) listbox2->DeleteString(0);

Re:ファイルの読み込み

Posted: 2008年11月06日(木) 10:04
by 初心者
バグさんのプログラム実行してみたんですがエラーは出ませんでしたが
仕分けされていないプログラムが1行listbox1に表示されるだけでした。

Re:ファイルの読み込み

Posted: 2008年11月06日(木) 11:19
by バグ
勘違いしてました。更に修正をお願いします。

// リストボックスのアイテムを全て消去する
INT i = 0;
for (i = 0; i < listbox1->GetCount(); ++i) listbox1->DeleteString(0);
for (i = 0; i < listbox2->GetCount(); ++i) listbox2->DeleteString(0);

この部分を…

// リストボックスのアイテムを全て消去する
listbox1->ResetContent();
listbox2->ResetContent();

こう変更してください。
これで、こちらでは問題なく動きます。

Re:ファイルの読み込み

Posted: 2008年11月06日(木) 11:24
by バグ
一応、証拠画像を…
読み込んだファイルの中身は

G01G41X0.F2.5H1E106=1M90

これです。数字とアルファベット以外は無視します。

Re:ファイルの読み込み

Posted: 2008年11月06日(木) 11:29
by 初心者
申し訳ない。私のミスだったようで無事実行できました
上記のも試してみます。ありがとうございました

Re:ファイルの読み込み

Posted: 2008年11月06日(木) 11:42
by 初心者
私のは
LIST1
0.
01
1061
2.5
41
90

LIST2
E
F
G
G
H
M
X
と並べ替えされています。ソースは上記のと同じです。
並べ替えせずに表示したいのですがどうしたらいいでしょう
実行したテキストファイルは
G01G41X0.F2.5H1E

Re:ファイルの読み込み

Posted: 2008年11月06日(木) 11:51
by 初心者
{
	// リストボックスのポインタを取得する
	CListBox* listbox1 = (CListBox*)GetDlgItem(IDC_LIST1);
	CListBox* listbox2 = (CListBox*)GetDlgItem(IDC_LIST2);

// リストボックスのアイテムを全て消去する 
listbox1->ResetContent(); 
listbox2->ResetContent(); 


// ファイルを読み込んでリストボックスへ割り当てる
	CFileDialog dlg(TRUE);
	if (dlg.DoModal() == IDOK)
	{
		CHAR buf = '\0';
		BOOL isnum = FALSE;
		CString data = "";
		CFile file(dlg.GetPathName(), CFile::modeRead);

		while (file.Read(&buf, 1) != FALSE)
		{
			// 0~9かドット(小数点?)の場合は数字として扱い、それ以外はアルファベットとする
			if (isdigit((int)buf) != 0 || buf == '.')
			{
				if (data.GetLength() == 0)
				{
					data += buf;
					isnum = TRUE;
				}
				else if (isnum == FALSE)
				{
					listbox2->AddString(data);
					data = buf;
					isnum = TRUE;
				}
				else
				{
					data += buf;
				}
			}

			if (isalpha((int)buf) != 0)
			{
				if (data.GetLength() == 0)
				{
					data += buf;
					isnum = FALSE;
				}
				else if (isnum == TRUE)
				{
					listbox1->AddString(data);
					data = buf;
					isnum = FALSE;
				}
				else
				{
					data += buf;
				}
			}
		}

		// 最後に読み込んだ文字列をリストボックスへ追加する
		if (data.GetLength() != 0)
		{
			if (isnum == TRUE)
			{
				listbox1->AddString(data);
			}
			else
			{
				listbox2->AddString(data);
			}
		}

		// ファイルを閉じる
		file.Close();
	}
}
がソースです

Re:ファイルの読み込み

Posted: 2008年11月06日(木) 12:13
by バグ
ソート(並び替え)機能が有効になっているようですね。
ダイアログエディタのリストボックス上で、右クリックして「プロパティ」、「スタイル」と選択し、ソートと書かれたチェックボックスのチェックを外してください。
プログラム内で無効にする方法もあるにはあるのですが、非常に面倒です。

Re:ファイルの読み込み

Posted: 2008年11月06日(木) 13:00
by 初心者
きちんとできました。長期にわたりありがとうございました。

Re:ファイルの読み込み

Posted: 2008年11月06日(木) 18:27
by 初心者
上記のプログラムは一文字ずつ呼んで仕分けしていくプログラムだとは思うのですが
一行読み込んで仕分けして表示 というようなのはできないでしょうか?
何度も申し訳ない

Re:ファイルの読み込み

Posted: 2008年11月06日(木) 18:35
by バグ
できますよ。

CStdioFileクラスのReadString関数を使用すれば一行ずつ読み込めます。

ただ、結局は読み込んだ文字列を分解して、今のプログラムと全く同じように処理していかなければいけないので同じことだと思いますけど…

Re:ファイルの読み込み

Posted: 2008年11月06日(木) 18:40
by バグ
MFCを使用したサンプルです。
選択したファイルの一行目を読み込んで、CString型のdataに読み込んだ内容を格納して、MessageBoxで表示するだけです。
CFileDialog dlg(TRUE);
if (dlg.DoModal() == IDOK)
{
	CString data = "";
	CStdioFile file(dlg.GetPathName(), CFile::modeRead);
	file.ReadString(data);
	MessageBox(data);
}

Re:ファイルの読み込み

Posted: 2008年11月06日(木) 19:39
by 初心者
ありがとうございました。試してみます

Re:ファイルの読み込み

Posted: 2008年11月07日(金) 10:29
by 初心者
一行ずつ表示はできたのですが一区切りごとにMessageboxが出てきます。

G01G41X0.F2.5H1E

ならば
G
01
G
41
X
0.
F
2.5
H
1
Eの11個のメッセージボックスが出ます。100行ぐらいあるのでこれだとどうしても・・

書き方が悪かったので申し訳ないのですが・・
一行読み込んで、分解して表示するのは全部の行を一気に表示したいのですが不可能でしょうか?

私が行ったプログラムのソースは
CFileDialog dlg(TRUE);
if (dlg.DoModal() == IDOK)
{
	CString data = "";
	CStdioFile file(dlg.GetPathName(), CFile::modeRead);
	file.ReadString(data);
	MessageBox(data);
}

while (file.Read(&buf, 1) != FALSE)
		{
			// 0~9かドット(小数点?)の場合は数字として扱い、それ以外はアルファベットとする
			if (isdigit((int)buf) != 0 || buf == '.')
			{
				if (data.GetLength() == 0)
				{
					data += buf;
					isnum = TRUE;
				}
				else if (isnum == FALSE)
				{
					Messagebox(data);
					data = buf;
					isnum = TRUE;
				}
				else
				{
					data += buf;
				}
			}

			if (isalpha((int)buf) != 0)
			{
				if (data.GetLength() == 0)
				{
					data += buf;
					isnum = FALSE;
				}
				else if (isnum == TRUE)
				{
					MessageBox(data);
					data = buf;
					isnum = FALSE;
				}
				else
				{
					data += buf;
				}
			}
		}

		// 最後に読み込んだ文字列をリストボックスへ追加する
		if (data.GetLength() != 0)
		{
			if (isnum == TRUE)
			{
				MessageBox(data);
			}
			else
			{
				MessageBox(data);
			}
		}

		// ファイルを閉じる
		file.Close();
	}
}
すごい不自然な気もしますが・・教えてください。

Re:ファイルの読み込み

Posted: 2008年11月07日(金) 11:17
by バグ
質問の意味がよく分からないですが…
1行ごとに分解した結果を表示したいという事でしょうか?
例えば…

aw12erfg4567uiop
oi876t3vbuw651wg

みたいなファイルだったら、

[awerfguiop] [124567]
[oitvbuwwg] [8763651]

(左がアルファベット表示用リストボックスで、右が数字表示用リストボックスです)
みたいな感じですか?

Re:ファイルの読み込み

Posted: 2008年11月07日(金) 11:33
by 初心者
そんな感じで大丈夫だと思います。
一文字ずつ読み込んでいたらきついといわれたので一行ずつ読み込むプログラムに切り替えたいです

Re:ファイルの読み込み

Posted: 2008年11月07日(金) 11:59
by 初心者
G00X49.82Y27.133ような行があったときに
LST1には
0の次に数字0がくるので
00とし

4の次に9がきて次に.がきて次に8がきて次に2がきて
49.82となり

2の次に7がきて.がきて1がきて3がきて3がきて
27.133となり次が英文字でその手前までを取り出す


00
49.82
27.133と書き込まれるのだと思いますが

単体ごとを組み合わせるのではなく[00][49.82][27.133]そのものを取り出すやり方じゃないと
CADの図形が取り込めないのでダメだといわれました

while (file.Read(&buf, 1) != FALSE)は変えないといけないなともいわれました
ポインタを使えばいいと言われたんですがポインタの仕組みがいまいち理解できなくてわかりません。

Re:ファイルの読み込み

Posted: 2008年11月07日(金) 12:11
by バグ
書き込みごとに言っている事がコロコロと変わっているんですけど…
結局、どうしたいのかをもう少し具体的に書き込んでください。

G00X49.82Y27.133

さっき確認した内容だと

[GXY][0049.8227.133]

こうなりますが、これでは駄目だという事ですか?

[G][00]
[X][49.82]
[Y][27.133]

こういう風に改行させるという事ですか?

Re:ファイルの読み込み

Posted: 2008年11月07日(金) 13:06
by 初心者
後者です
先ほどのは仕分けの仕方についていいました。

Re:ファイルの読み込み

Posted: 2008年11月07日(金) 18:24
by バグ
自分で考える気がないように感じるんだけど…
まぁ、乗りかかった舟だし…

どうやら、コピペできた方がいいっぽいので、出力先をリストボックスからエディットボックスへ変更しました。

それから、エディットボックスへ文字列を追加する部分が行数がかさんで仕方ないので、関数化しました。
そちらのダイアログクラスにメンバ関数を追加してください。

これで駄目なら、もっと詳細の仕様を書きこむなり、決めるなりしてください。
出ている情報では、私にはこれ以上は無理です。
void FileRead()
{
	// エディットボックスのポインタを取得する
	CEdit* edit1 = (CEdit*)GetDlgItem(IDC_EDIT1);
	CEdit* edit2 = (CEdit*)GetDlgItem(IDC_EDIT2);

	// エディットボックスのアイテムを全て消去する
	edit1->SetWindowText("");
	edit2->SetWindowText("");

	// ファイルを読み込んでエディットボックスへ割り当てる
	CFileDialog dlg(TRUE);
	if (dlg.DoModal() == IDOK)
	{
		INT count = 0;
		CString buf;
		CStdioFile file(dlg.GetPathName(), CFile::modeRead);

		// ファイルの読み込みが成功している間ループする
		while (file.ReadString(buf) != FALSE)
		{
			BOOL isnum = FALSE;
			CString check;

			// ファイルから読み込んだ文字列を1文字ずつチェックする
			for (INT i = 0; i < buf.GetLength(); ++i)
			{
				// 数字、ドットのチェック
				if (isdigit((int)buf.GetAt(i)) != 0 || buf.GetAt(i) == '.')
				{
					if (i == 0)
					{
						isnum = TRUE;
						check += buf.GetAt(i);
					}
					else if (isnum == FALSE)
					{
						isnum = TRUE;
						AddString(edit1, check);
						check = buf.GetAt(i);
					}
					else
					{
						check += buf.GetAt(i);
					}
				}

				// アルファベット(大文字のみ)のチェック
				if (isalpha((int)buf.GetAt(i)) != 0 && isupper((int)buf.GetAt(i)) != 0)
				{
					if (i == 0)
					{
						isnum = FALSE;
						check += buf.GetAt(i);
					}
					else if (isnum == TRUE)
					{
						isnum = FALSE;
						AddString(edit2, check);
						check = buf.GetAt(i);
					}
					else
					{
						check += buf.GetAt(i);
					}
				}
			}

			// 文字列が空でなければ、リストボックスへ追加する
			if (check.IsEmpty() == FALSE)
			{
				if (isnum == TRUE)
				{
					AddString(edit2, check);
				}
				else
				{
					AddString(edit1, check);
				}
			}
		}

		// ファイルを閉じる
		file.Close();
	}
}

// エディットボックスへ文字列を追加する
void AddString(CEdit* edit, CString& str)
{
	CString buf;
	edit->GetWindowText(buf);
	buf += (str + "\r\n");
	edit->SetWindowText(buf);
	str.Empty();
}