επιστημηさん、サンプルありがとうございます。
そのまま使わせて貰ってます。
//cout << i++ << [ << token << ] ;←ここでエラー
}
str.ReleaseBuffer(-1);
//fin.Close();
cout << endl;
}
エラーとりをしていて返信遅くなりました。
正直、cout <<こういう物を見た事がなくてエラーが出た時あせりました。
Printf?みたいな物なんですかね・・・
すいません。また、新たに質問したい事が出来ました。
1000|01-01-01|aaaaaとかで|や-等は飛ばせる様になったのですが
現在テキストの中に<<aaa/aaa>>こういった/が含まれています。
現在プログラムでは、+-|だけ飛ばす様にしているのですが
なぜか、/も飛ばされています。
すいませんが、教えて貰えないでしょうか。
お願いします。
ソースです。
for ( const char* token = strtok(str.GetBuffer(str.GetLength()),+-|);
token != NULL;
token = strtok(0,+-|) ) {
//token = str.Mid(14);
m_HndTree[0] = m_tree.InsertItem(token,TVI_ROOT);
InsertItemする直前のtokenがどうなってるくらいは確認したんでしょうね?
> どの関数が例外を投げる/投げないを調べたうえで使えばこれは問題にならないでしょう。
> 「例外を投げない」という強い保証がある関数にはそもそも例外可能性なんてものはないですか
ら。
参照先MSDNを見ても、「例外を投げない強い保証」がないようです。
(私の理解では、「例外を投げない強い保証」とは、「投げない」または「throw()」の明記です)
>> ReadStringやデストラクタでも例外返しませんか?
> 投げませんよ。
> http://msdn.microsoft.com/ja-jp/library/x5t0zfyf(VS.80).aspx
上記で「投げない」と書いてない以上、投げる可能性があると考えるべきでしょう。
# VC6バンドルのMSDNに明記があるかは未確認です。
実際、手元のVC7.1(質問者環境のVC6は今手元にないので)のソースでも、
CStdioFile::ReadString(CString&)には、明確にAfxThrowFileExceptionを呼ぶパスがありま
す。
# AfxThrowFileExceptionはCStdioFile::ReadString(LPTSTR,UNIT)の方にもあります。
また、内部で呼んでいるCString::GetBufferでもMemoryExceptionを投げる可能性があるはず。
> また、「デストラクタでは例外を投げてはいけない」という原則があります。
これは、明記がなくても信じてもいい/信じたいところです。
正しく実装していれば実際の投入可能性がないかもしれませんが、
CStdioFile::ReadString(LPTSTR,UNIT)の方には、
AfxThrowInvalidArgException()の呼び出しもありますね。
CStdioFile::ReadString(LPTSTR,UNIT)のソースを読む限り、
> lpszResult == NULL && !feof(m_pStream)
という条件判断で例外を投げてますので、
実装上の挙動としては、こんな感じ(↓)でしょうか。
> データを読み込まずにファイルの終わりに達した場合は NULL または
> FALSE (ブール型の場合) を返します。
「ファイルの終わりに達せずにデータが読み込めなかった場合は
CFileException例外を投げます」
そして、おそらく、公式の仕様見解はこう?(↓)
「ファイルの終わりに達せずにデータが読み込めなかった場合の動作は未規定です」
# 散発的にすみません。
本題に立ち返ると、下記の前提認識にずれがあり、MSDNをこの理解で読むのは
誤りという点がまずあって、
> このトピックで使われてる CStdioFile のメンバ関数で例外を投げるのは
> コンストラクタと Seek くらいですしね。
その上で、「各関数に例外投入可能性がある」という認識にたってみれば、
個別に「極めて局所的にtry/catch」は著しく読みにくくありませんか、という話です。
MFC側で例外を投げてくる可能性があるものを使う以上、
PCの性能云々は関係なく、どこかでcatchはせざるを得ないはずです。
(「そこで例外がでたら落ちる仕様」という割り切りがない限りは)
> 「最近のPCは早いから~」で作っていたらたちまちボトルネックになってしまうでしょう。
むしろ、MFCなどMSの設計思想がそもそもこれに近いように思います。
別スレ立てますか?(例外関係)
> 別スレ立てますか?(例外関係)
雑談ラウンジに別スレ立てました。
宜しく
返信遅れました。申し訳ないです。
> InsertItemする直前のtokenがどうなってるくらいは確認したんでしょうね?
for ( const char* token = strtok(str.GetBuffer(str.GetLength()),+-|0123456789 );
token != NULL;
token = strtok(0,+-|0123456789 ) ) {
AfxMessageBox(token);//確認
m_HndTree[0] = m_tree.InsertItem(token,TVI_ROOT);
省略
}
こんな方法しか、思かびませんでした。
これでは、確認になっていませんか?
せっかくVC++6.0を使っているんですから
デバッガを使ったほうが早くないですか?
デバッガならステップ毎に状況の確認も出来ますし。
あと、VC++の入門書よりもC++言語の方を先に読んだ方が良く無いかなぁと
感じました。cout <<を見た時に分からない様子でしたので。
VC++の使い方を勉強するのも必要だとは思うんですが、
コンソールアプリでC++言語の勉強をしてからMFCの使い方を勉強した方が
すんなり理解出来る所が多いのではないかなと思いました。
PATIOさん、アドバイスありがとうございます。
基本的な事なら、すいません。
C++の参考書でも、VC++の勉強になるのですか?
ふと今思ったのですが、[cout <<]←ってC++,VC++で使えるのですか?
> なぜか、/も飛ばされています。
上記は間違いですね。分解されて表示されていました。
ブレイクを張ってtokenの中を見たのですが
●for(const char* token =
strtok(str.GetBuffer(str.GetLength()),+-|0123456789 );①(aaa/aaa)
token != NULL;
● token = strtok(0,+-|0123456789 ) ) {②(aaa),(/aaa)
①ではaaa/aaaでそのまま読み込まれているのですが、
②ではaaaと/aaaに分解されていました。
なぜ分解して表示されるのか、解りません。
よろしくお願い致します。
...再現できないのでわかりません。
#include <iostream>
#include <cstring>
using namespace std;
int main() {
char data[] = ab/cd|ef/gh/ij|kl/mn/op;
for ( const char* token = strtok(data,+-|0123456789);
token != NULL; token = strtok(0,+-|0123456789) ) {
cout << '[' << token << ]\n;
}
}
> C++の参考書でも、VC++の勉強になるのですか?
「ランニングをして、野球の練習になるのですか?」
基礎体力を付けるのには、野球の練習よりもランニングでしょう。
> 基礎体力を付けるのには、野球の練習よりもランニングでしょう。
ごもっともですね。
επιστημηさんのサンプルでは、/で分解されず
[ab/cd|ef/gh/ij|kl/mn/op]とちゃんと表示されました。
ソース乗せます。
//--------------------------------------------------------------------
CFile file;
CString str;//1行文読込用
CStdioFile fin;
if ( !fin.Open(部材.txt, CFile::modeRead, NULL ) ) {return -1;}
while ( fin.ReadString(str) != NULL ) {
int i = 0;
for (const char* token=strtok(str.GetBuffer(str.GetLength()),+-|0123456789 );
token != NULL;
token = strtok(0,+-|0123456789 ) ) {
m_HndTree[0] = m_tree.InsertItem(token,TVI_ROOT);
m_HndTree[1] = m_tree.InsertItem(token,m_HndTree[0]);
m_HndTree[2] = m_tree.InsertItem(token,m_HndTree[1]);
m_HndTree[3] = m_tree.InsertItem(token,m_HndTree[1]);
m_HndTree[4] = m_tree.InsertItem(token,m_HndTree[0]);
m_HndTree[5] = m_tree.InsertItem(token,m_HndTree[4]);
m_HndTree[6] = m_tree.InsertItem(token,m_HndTree[4]);
m_HndTree[7] = m_tree.InsertItem(token,m_HndTree[4]);
m_HndTree[8] = m_tree.InsertItem(token,m_HndTree[0]);
m_HndTree[9] = m_tree.InsertItem(token,m_HndTree[8]);
m_HndTree[10] = m_tree.InsertItem(token,m_HndTree[8]);
m_HndTree[11] = m_tree.InsertItem(token,m_HndTree[0]);
m_HndTree[12] = m_tree.InsertItem(token,m_HndTree[11]);
m_HndTree[13] = m_tree.InsertItem(token,m_HndTree[11]);
m_HndTree[14] = m_tree.InsertItem(token,m_HndTree[11]);
//cout << i++ << [ << token << ] ;
}
str.ReleaseBuffer(-1);
//fin.Close();
cout << endl;
}
テキストの中
----+--------+------------------------------------
2000|02-00-00|《aaaaaa》
2000|02-01-00| aaa/bbb
2000|02-01-01| ccc
2000|02-01-02| ddddd
2000|02-01-03| ee
//------------------------------------------------
実行結果
//------------------------------------------------
<<aaaaaa>>
aaa
/aaa
ccc
ddddd
ee
//------------------------------------------------
になります。お願いします。