- 締切済み
ファイル処理について
大学の課題なのですが、何度取り組んでもエラーになるため、間違いのご指摘、または正答を教えていただけないでしょうか。 問題は以下のものです。 【問題】 ファイルから整数を読み込み,その値によってfpの読み込み位置をかえ,何度目の読み込みで0を読み込んだかを表示するプログラムを作成せよ. ファイルの内容の例 2,4,0, fpの読み込み位置を変えるにはfseekという関数を利用する. fseekの使い方: 現在の読み取り位置xだけずらすには, fseek(ファイルポインタ, x, SEEK_CUR); と記述する. STEP 1 データを一区切りで読み取る("2,"や"-4,"などの整数とコンマの組) 2 読み取ったデータに応じてfpを移動させる("2,"なら2移動,"-4,"なら-4移動) 3 0を読むまで繰り返す +++++*+++++fseek-exercise.c+++++*+++++ #include <stdio.h> int main(void){ FILE *fp; int c; int i; int count=0; char filename[60]; printf("ファイル名 :"); scanf("%s",filename); //ファイルを開く // (* ここに解答を書き加える *) while(1){ printf("読み込み前 : %ld\n",ftell(fp)); //fpから値を読む // (* ここに解答を書き加える *) printf("読み込んだ値は%dです\n",c); printf("読み込み後 : %ld\n\n",ftell(fp)); //読み込み位置をずらす // (* ここに解答を書き加える *) } printf("%d回目です.",count); fclose(fp); return(0); } // 以上になります。 自分で作ったプログラムは以下のようになりました。 #include <stdio.h> int main(void){ FILE *fp; int c; int i; int count=0; char filename[60]; printf("ファイル名 :"); scanf("%s",filename); //ファイルを開く // fp = fopen(filename,"r"); if(fp == NULL){ printf("cannot open\n"); exit(1); } while(1){ printf("読み込み前 : %ld\n",ftell(fp)); //fpから値を読む // c = fgetc(fp); printf("読み込んだ値は%dです\n",c); printf("読み込み後 : %ld\n\n",ftell(fp)); //読み込み位置をずらす // if(c > '0' || c< '9'){ i = atoi(&c); count++; if(i == 0){ break; } fseek(fp,i,SEEK_CUR); } } printf("%d回目です.",count); fclose(fp); return(0); } // どこを訂正していいのかわかりません。 どうぞ、よろしくお願いいたします。
- みんなの回答 (4)
- 専門家の回答
みんなの回答
- yama5140
- ベストアンサー率54% (136/250)
>STEP >1 データを一区切りで読み取る("2,"や"-4,"などの整数とコンマの組) >2 読み取ったデータに応じてfpを移動させる("2,"なら2移動,"-4,"なら-4移動) >3 0を読むまで繰り返す 「『整数とコンマの組』単位の移動」と曲解して作ってみました(BorlandC++5.5.1)。 というか、「文字単位での移動」だと、移動の途中に、2桁の整数・負数などがあると、難しくて・・。 ・データによっては、無限ループとなります。 2( 2, )進んで2( -2, )戻る場合など・・。 ・データによっては、「 0を読むまで繰り返す」ことができません。 ・という訳で、参考にもならんかも・・。 サンプルデータ:12,31,32,33,34,35,36,37,38,39,10,11,-2,-3,-4,-5,-6,-7,-8,-9,-0,1, (プロセス) :12,--,--,--,--,--,--,--,--,--,10,--,-2,--,--,--,--,--,--,--,-0,-, #include <stdio.h> int main( void ) { FILE *fp; int iIdou, count = 0, iCmmCnt, c; fp = fopen( "Z:\\Test.txt", "rb" ); // バイナリストリームモード // (略) while( 1 ){ printf( "\t読み込み前 : %ld\n", ftell( fp ) ); if( 1 != fscanf( fp, "%d,", &iIdou ) ) break; printf( "[%d]\t読み込んだ値は %d です\n", ++count, iIdou ); printf( "\t読み込み後 : %ld\n\n", ftell( fp ) ); if( ! iIdou ) break; // 0発見 iCmmCnt = 0; if( 0 > iIdou ){ // ←負:左へ while( iCmmCnt > ( iIdou - 2 ) ){ if( fseek( fp, -1, SEEK_CUR ) ) break; c = fgetc( fp ); fseek( fp, -1, SEEK_CUR ); if( ',' == (char)c ){ iCmmCnt--; if( iCmmCnt == ( iIdou - 2 ) ) fseek( fp, 1, SEEK_CUR ); } } } if( 0 < iIdou ){ // →右へ while( iCmmCnt < ( iIdou - 1 ) ){ c = fgetc( fp ); if( ',' == (char)c ) iCmmCnt++; } } } printf( "%d 回目です.", count ); fclose( fp ); return( 0 ); } 注:インデントに全角空白を用いています。コピペ後、タブに一括変換して下さい。
- php504
- ベストアンサー率42% (926/2160)
1 データを一区切りで読み取る("2,"や"-4,"などの整数とコンマの組) は fscanf(fp, "%d,", &num); という意図かなと思いました。
- D-Matsu
- ベストアンサー率45% (1080/2394)
ひとつ訂正。 > if(c > '0' || c< '9'){ この条件式ではif(1)と同じ(必ず真)です。
- D-Matsu
- ベストアンサー率45% (1080/2394)
まず質問する上での基本中の基本ですが「どううまくいかない」のか詳細を書きましょう。 エラーが出るなら何をやったらどんなエラーが出るのか。 ざっくり見た上では以下の箇所に問題あります。 > c = fgetc(fp); > printf("読み込んだ値は%dです\n",c); > printf("読み込み後 : %ld\n\n",ftell(fp)); charの'0'~'9'は数値の0~9ではないので期待する値は表示されません。 > if(c > '0' || c< '9'){ この条件式では'0'と'9'を含みません。 > i = atoi(&c); atoi()に渡すのは文字列('\0'で終端されたchar配列)でなければなりません。単品のcharのアドレスを渡した場合、次のアドレスの中身が不定のため実行結果は不定(最悪Segmentation fault)になります。