- 締切済み
fread()エラー
お世話になります。 今、バイナリファイルを操作しているのですが、 fread()でエラーになってしまいます。 char buf1[256]; FILE *fp; vector<string> f1; int num; fp = fopen("hoge.txt","r"); while( fgets( buf1, sizeof(buf1),fp ){ f1.push_back( buf1 ); num ++; } fclose(fp); FILE *cfp; unsigned char data[1024]; for(int i=0; i<num; i++ ){ cfp = fopen(f1[i].c_str(), "rb"); fread( data, sizeof(char), 1024, cfp ); } hoge.txtには、コンテンツ場所(パス)が複数記載されており、 その1つずつをfread()で読み込み解析したいのですが、 fread()でセグメンテーション違反になります。 f1の中味をprintf("%s",f1[0].c_str()); で見てみると正常にコンテンツの場所が格納されています。 また、 string pp = "/home/hoge/hoge.txt"; cfp = fopen(pp.c_str(), "rb"); fread(bb,sizeof(char),1024,cfp); とすると正常に動作します。 どうぞよろしくお願い致します。
- みんなの回答 (8)
- 専門家の回答
みんなの回答
- aris-wiz
- ベストアンサー率38% (96/252)
回答されてる人のコードでは皆さんきちんと修正してるので 一応、本題とはちょっと離れるけどつっこみを。 以下のコードループの中でfopenを使用しcfpを上書きしてますが、 きちんとfcloseしましょう。 >FILE *cfp; >unsigned char data[1024]; >for(int i=0; i<num; i++ ){ >cfp = fopen(f1[i].c_str(), "rb"); >fread( data, sizeof(char), 1024, cfp ); >} >f1の中味をprintf("%s",f1[0].c_str()); このような場合は、使っている可能性のあるものすべてを 調べる必要があります。f1[0]がOKだったからといってそれ以降 f1[1]が大丈夫という保障はありません。 きちんと、ある程度の可能性まで考慮して調査してみると 良いと思います。
- mikaemi
- ベストアンサー率50% (33/65)
あっ、あと、size_t i など符号なし型を使う場合は、引き算や 0 との比較に注意してください。i が 0 なのに、--i や i - 1 などを気軽に使ってしまうと、巨大な数字に化けてしまいます(たぶん^^)。
- mikaemi
- ベストアンサー率50% (33/65)
ご参考: ==== C++ っぽく凝って書くと^^ #include <cstdio> #include <vector> #include <string> #include <fstream> #include <algorithm> #include <iterator> int main() { using namespace std; vector<string> f1; { ifstream ifs("hoge.txt"); istream_iterator<string> isi(ifs), ise; copy(isi, ise, back_inserter(f1)); } for(int i=0; i<f1.size(); i++ ){ FILE *cfp; if ((cfp = fopen(f1[i].c_str(), "rb")) == NULL) continue; unsigned char data[1024]; while (size_t sz = fread( data, sizeof data[0], sizeof data / sizeof data[0], cfp )) { // ... } fclose(cfp); } } === ファイルのパス名の中に空白がある場合、C++ っぽく普通に書くと^^ #include <cstdio> #include <vector> #include <string> #include <fstream> #include <cctype> std::string trim(const std::string &str) { std::string::size_type s = 0; while (s < str.size() && std::isspace(str[s])) ++s; std::string::size_type e = str.size(); while (s < e && std::isspace(str[e - 1])) --e; return str.substr(s, e - s); } int main() { using namespace std; vector<string> f1; { ifstream ifs("hoge.txt"); string ln; while (getline(ifs, ln)) f1.push_back(trim(ln)); } for(int i=0; i<f1.size(); i++ ){ FILE *cfp; if ((cfp = fopen(f1[i].c_str(), "rb")) == NULL) continue; unsigned char data[1024]; while (size_t sz = fread( data, sizeof data[0], sizeof data / sizeof data[0], cfp )) { // ... } fclose(cfp); } }
- Oh-Orange
- ベストアンサー率63% (854/1345)
★アドバイス ・fopen() 関数でファイルパスに改行コードが含まれるとエラーになります。 あと num は 0 で初期化してから num++ しましょう。 サンプル: vector<string> path; char buff[ 256 ]; char *find; FILE *fp; int num = 0; ←初期化 // hoge.txt の読み込み if ( (fp = fopen("hoge.txt","r")) != NULL ){ while ( fgets(buff,sizeof(buff),fp) != NULL ){ if ( (find = strchr(buff,'\n')) != NULL ){ *find = '\0'; } path.push_back( buff ); num++; } fclose( fp ); } // 各ファイルを読み込む unsigned char data[ 1024 ]; for ( int no = 0 ; no < num ; no++ ){ if ( (fp = fopen(path[no].c_str(),"rb")) != NULL ){ size_t size = fread( data, sizeof(char), sizeof(data), fp ); // バイナリー検索 for ( int i = 0 ; i < (size - 1) ; i++ ){ if ( (data[i] == 0xFF) && (data[i + 1] == 0xE0) ){ printf( "find:%d\n", (data[i] << 8|data[i + 1]) ); } } fclose( fp ); } } その他: ・fread() で読み取れたバイト数をバイナリー検索して下さい。 あと data[1024] なので i カウンタは 0~1023 ですが 16 ビットのデータを 検索する場合は i カウンタを 0~1022 までの検索にします。注意。 ・以上。
- mikaemi
- ベストアンサー率50% (33/65)
> それと、テキストファイルは "r" がいいです。 あっ、失礼。"r" になってますね^^; すみません。
- mikaemi
- ベストアンサー率50% (33/65)
あぁ、そうそう。gets と fgets の違いに注意してください。てか、C++で使わない、のがいい^^
- mikaemi
- ベストアンサー率50% (33/65)
fopen() が失敗してるんだと思いますよ。 ファイル名の後に、改行が入ってしまっているんじゃないですか? それと、テキストファイルは "r" がいいです。 それに、num を初期化しましょう。 そして、きちんと、関数の戻り値をみて、エラー処理をしましょう。エラーが起こってからでもできる、というならそれでもいいですけどねぇ。。。 ・NULL を使う場合は省略せずにきちんと NULL と比較したほうがいい ・fopen() の戻り値は必ずチェックする ・fread() の返してくるサイズはきちんと受ける ・C++なら、変数の宣言は使う必要があるところで宣言する あと、せっかく C++ なんだし、バイナリのファイルじゃない場合は、fstream とか使えばいいのに^^
- RAPTsong
- ベストアンサー率42% (74/175)
> int num; num が初期化されていないからでは? それで、配列の添え字が範囲外アクセスしているのでしょう。
お礼
ありがとうございました。無事に解決できました。