• ベストアンサー

c言語のfeof関数はどういう関数?

feof関数について調べると、 ・ストリームがファイルの終端かどうか調べる。 ・終端指定子がセットされているかどうか調べる。 と、サイトによって説明のしかたが2つに分かれていました。 不思議に思ってstdio.hを調べてみると、  #define _IOEOF 0x0010  #define feof(_stream) ((_stream)->_flag & _IOEOF) こんな感じになっていました。 上だとエラー指示子と0x0010(10進数で16)の論理積を出しているようですが、0x0010が何を意味するのかがわからないのでなにがなんだかです。 feofはどういう関数なのでしょうか? 回答よろしくお願いします。

noname#113783
noname#113783

質問者が選んだベストアンサー

  • ベストアンサー
回答No.2

<stdio.h>の実装については#1さんの通りです。 feofはthe end-of-file indicatorがセットされているかどうかを調べる関数です。 # 規格 (ISO/IEC 9899:1999) 7.19.10.2 The feof function まず,規格7.19.3 Filesの11段落に, > The byte input functions read characters from the stream as if by successive calls to the fgetc function. とありますので,<wchar.h>で定義されるワイド入出力関数を除くと,ファイルの読み込みはすべてfgetcを使った読み込みを経由していると見なせます。 次に規格7.19.7.1 The fgetc functionの第3段落には > If the end-of-file indicator for the stream is set, or if the stream is at end-of-file, the end-of-file indicator for the stream is set and the fgetc function returns EOF. とあります。つまり, ・ストリームが終端に達した後,さらに読み込もうとするとthe end-of-file indicatorがセットされる ということになります。 なので, > ・ストリームがファイルの終端かどうか調べる。 ではなく, > ・終端指定子がセットされているかどうか調べる。 が正しいことになります。 前者は曖昧と言えば曖昧ですが,終端に達した後「さらに読み込もうとした」ことが必要なので。

noname#113783
質問者

お礼

わかりました! 回答ありがとうございました。

その他の回答 (2)

  • jacta
  • ベストアンサー率26% (845/3158)
回答No.3

feof関数は、「ファイル終了表示子」がセットされているかどうかを判定します。 fgetcやfread等のストリーム入力関数によって値を読み込んだ結果、ファイルの終端に達しても、その時点ではファイル終了表示子はセットされません。その状態でさらに読み込もうとした時点でファイル終了表示がセットされます。 また、いったんファイル終了表示子がセットされたとしても、clearerrの呼び出し等によって、ファイル位置表示子がファイルの終端にあるままの状態でファイル終端表示子はクリアされ、feofが0を返すようになります。

noname#113783
質問者

お礼

回答ありがとうございました!

  • php504
  • ベストアンサー率42% (926/2160)
回答No.1

FILE構造体の仕様がコンパイラによってまったく違うので_IOEOFの意味を考えても意味がないです 調べられたコンパイラではFILE構造体のメンバ変数であるflagの下から5ビット目が終端指定子なのでしょう ファイルの終端にきたら終端指定子がセットされるので feofはストリームがファイルの終端かどうかを(終端指定子がセットされているかどうかで)調べる関数になります。

noname#113783
質問者

お礼

回答ありがとうございました!

関連するQ&A

  • C言語 配列の確保

    はじめまして。C言語の勉強を最近始めたのですが、 以下のプログラムで教えていただきたい点があります。 #include <stdio.h> #include <math.h> #define x 10000 #define y 200000 #define z 1.0E-12 #define k 1.38 #define kE 1.0E-23 #define h 6.63 #define hE 1.0E-34 #define c 3.00 #define cE 1.0E+08 void main(void){ int i; double A[x+1]; double B[x+1]; for(i=0;i<=x;i++) { A[i]=(i+y)*z; B[i] = exp(-(h*hE*c*cE)/(A[i]*k*kE*1000)); printf("%e %e\n",A[i],B[i]); }} このプログラムで、xを100000にするとプログラムが動かなくなってしまいます。OSはWindowsXP、ソフトはVisual C++ 6.0を使っています。 解決方法を教えていただけないでしょうか。

  • 落ちてしまいます

    無限ストリームなのですが、 (define (stream-car stream) (car stream)) (define (stream-cdr stream) (force (cdr stream))) (define (cons-stream a b) (cons a (delay b))) (define (integers-starting-from n) (cons-stream n (integers-starting-from (+ n 1)))) (define integers (integers-starting-from 1))      (define (stream-ref s n) (if (= n 0) (stream-car s) (stream-ref (stream-cdr s) (- n 1)))) (define (divisible? x y) (= (remainder x y) 0)) (define (sieve stream) (cons-stream (stream-car stream) (sieve (stream-filter (lambda (x) (not (divisible? x (stream-car stream)))) (stream-cdr stream))))) (define primes (sieve (integers-starting-from 2))) (stream-ref primes 10) integersを定義する段階で落ちてしまうようです。どうも遅延評価がうまくいってないようです。どうしたらよいでしょうか?どなたか助けてください。

  • scanf C言語

    現在取得したデータを多次元配列いれたいのですが、カンマまでの文字列を入れる方法がわかりません。例で言いますと jgasogasog,dklafh343,fdjalsjfd,kldjfas5 dfasfdas6ff ,fsadfa6sg,dgas6dsa,fsdafa もカンマまでの文字列array[0][0] = jgasogasog array[0][1] = dklafh34 といった形で入れていきたいです。 ご迷惑おかけしますが何卒よろしくお願いします。 途中まで作ったソースをのせます。 #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> #include<string.h> #define piyo 2 #define hoge 1400 int main(void) { FILE *fp; char test[10][500]; int n = 0; if ((fp = fopen("testfile.csv", "r")) == NULL) { printf("\aファイルをオープンできません\n"); return(0); } int i, j; int k = 0; //ファイルfpの終端指示子をチェックします。 while (!feof(fp) && k < 500) { //%cは一文字出力をしてくれる使用データ型はchar型 //fscanf関数は書式指定をしてファイルから値を読み込み、バッファに格納します。 for (i = 0; i < 10; i++) { for (j = 0; j < 500; j++) { fscanf(fp, "%[^,],%d", &test[i][j]); k++; } } } for (i = 0; i < 10; i++) { for (j = 0; j < 500; j++) { printf("test[%d][%d]=%d\n", i,j,test[i][j]); } } fclose(fp); return(0); } 似たような質問をしてすいません。

  • scanf関数のプログラムをgetchar関数で

    scanf関数を使って四則演算、論理輪、論理積をint、float、double型で表示するプログラムを作ったのですが これをscanf関数ではなく、getchar関数で組みなおし、関数化する課題が出ました。 そのままscanf関数のところだけを変えても型が違うというエラーが出てうまくいきません。 どうすればいいでしょうか? 一応scanf関数で組んだプログラムの一部を載せておきます。 #include <stdio.h> #include <math.h> main() { float a , b; float x[5]; printf("正の数字を2つ入力して下さい(小数点を含めて4ケタまで):\n"); for(;;) { printf("\na="); scanf("%f" , &a); if(a>=0 && a<=9999 && a) { break; } else { printf("****aに入力エラー****\n"); printf("数字は4ケタ以内の正数を入力:\n"); continue; } } for(;;) { printf("b="); scanf("%f" , &b); if(b>=0 && b<=9999 && b) { break; } else { printf("****bに入力エラー****\n"); printf("数字は4ケタ以内の正数を入力:\n"); continue; } } x[0] = a+b; x[1] = a-b; x[2] = a*b; x[3] = a/b; x[4] = a||b; x[5] = a&&b; printf("\n"); printf("int型 結果:\n足し算=%d\n" , (int)x[0]); printf("引き算=%d\n" , (int)x[1]); printf("掛け算=%d\n" , (int)x[2]); printf("割り算=%d\n" , (int)x[3]); printf("論理和=%d\n" , (int)x[4]); printf("論理積=%d\n" , (int)x[5]); printf("\n"); printf("float型 結果:\n足し算=%f\n" , x[0]); printf("引き算=%f\n" , x[1]); printf("掛け算=%f\n" , x[2]); printf("割り算=%f\n" , x[3]); printf("論理和=%f\n" , x[4]); printf("論理積=%f\n" , x[5]); ・ ・ ・ getchar(); }

  • 解説をお願いします。

    #define ast_test_flag(p,flag) ({ \ typeof ((p)->flags) __p = (p)->flags; \ typeof (__unsigned_int_flags_dummy) __x = 0; \ (void) (&__p == &__x); \ ((p)->flags & (flag)); \ }) あるソースコードを読んでいると上のような記述に当たりました。 何をしているのか解説していただけませんか。 __xとか¥記号とか宣言していないものも多く、皆目見当がつきません。

  • Cプログラミングについて

    私はBorlandのコンパイラを使ってCプログラミングをやっているのですが、以下のプログラムが実行できません。 どのようにすればコンパイラできるのか教えてください。 非線型方程式f(x)=x^3-x+1の根をニュートン法により求めよ。 /* *-------------------------- *   ニュートン法 * *-------------------------- */ #include <stdio.h> #include <math.h> #define f(x) ((x)*(x)*(x)-(x)+1) #define g(x) (3*(x)*(x)-1) #define EPS 1e-8 #define LIMIT 50 int main(void) { double x=-2.0,dx;   int k; for (k=1;k<=LIMIT;k++){ dx=x; x=x-f(x)/g(x); if(fabs(x-dx)<fabs(dx)*EPS){ printf("iteration=%d\n",k); printf("x=%f\n",x); break; } } if (k>LIMIT) printf("収束しない\n"); } コンパイルしようとすると以下のようなエラーが出ます。 エラー E2206 sample.c 18: 不正な文字 ' ' (0x8140)(関数 main ) エラー E2206 sample.c 18: 不正な文字 ' ' (0x8140)(関数 main ) 警告 W8070 sample.c 32: 関数は値を返すべき(関数 main ) *** 2 errors in Compile *** お答えよろしくお願いします。

  • 関数のプロトタイプ宣言

    #include <stdio.h> #define N 3 #define M 4 int sum(int [][M]); (関数のプロトタイプ宣言) int main(){   ・   ・   ・ return(0); } int sum(int x[][M]){    ・    ・ } 以上のプログラムより、関数のプロトタイプ宣言や、関数内の 行列の定義でint sum(int [][M]);や int sum(x[][M]){}となっていますが なぜ、列にMだけを代入することだけでよいのでしょうか? また、教科書に関数のプロトタイプ宣言ではint sum(int [][]);だけでもよいと書かれていたのですが 実際、コンパイルしてみたところ 'int[]' 型のサイズは未知あるいはゼロとエラーがでました。 これは、コンパイラによってできるものとできないものがあるのでしょうか?? よろしくお願いします。

  • C言語のプログラムです。

    次のようなプログラムを作成しようと考えています。 1.文字列を入力し、入力した文字列にアルファベット以外の文字が含まれていたら再入力。 2."end"もしくは"END"が入力されたらプログラム終了。 3.main関数とは別の関数で入力した文字列に現れる文字を全て入力順に大文字で表示する。(小文字と大文字は同じ文字として扱い、出現個数も合わせて表示する) ※2.では文字列を比較するstrcmpを使用。 表示結果例)  入力:DxbhzAeFSXY  出力:D=1,X=2,B=1,H=1,Z=1,A=1,E=1,F=1,S=1,Y=1 (応用)3.では入力順に表示させていたが、アルファベット順に結果を表示する。 上記の2.までのプログラムは作成できたのですが、3.及び応用が分からず大変困っています。 どなたかご教授ください。 #include <stdio.h> #include <string.h> int sub(int ss[i],int n){ int x; for(x=1; x<=n; x++){ //小文字を大文字に変換 if(ss[i]>=97){ ss[i]=ss[i]-32; } } } int main(void){ char ss[80]; char sa[2][4]={{\"end\"},{\"END\"}}; int a, i, n; int flag= 0; //アルファベット以外の入力があった際の判別 do{ printf(\"文字列を入力してください\\n\"); gets(ss); n= strlen(ss); //文字列ssの長さを求める if(n=3 && ((strncmp(ss,sa[0],3)==0)) || ((strncmp(ss,sa[1],3)==0))){ //endまたはENDの判定 return 0; } for(i=0; i<n; i++){ if((ss[i]>=65 && ss[i]<=90) || (ss[i]>=97 && ss[i]<=122)){ } else{ flag=1; break; } } }while(flag=1); }

  • 入力を待たずにstdinの監視をしたい(C言語)

    こんにちは.タイトルのままなのですが,c言語でstdinに何かが入力されるまで待つことなく,stdinの監視がしたいです.例えば, whileループを回してる最中に,qがstdinに入力されたらbreakするけど,あとは普通に回る,みたいな感じにしたいです.fgetc(stdin)とすると,毎回入力を待つことになるので,待たないで回る方法が知りたいです. 具体的には,以下はgnuplotにsinカーブを表示するプログラムですが,コメントアウトしてある /* if((buf = fgetc(stdin)) == 'q'){ break; } */ の部分のようにすると毎回とまってしまいます.これを,毎回入力を待たずに,qを打ったら止まるようにするにはどうするのが普通なのでしょうか. 返信おまちしております. #include <stdio.h> #include <math.h> #include <unistd.h> FILE *gp; #define omega (M_PI/2) #define A 1 #define N 10 int i; int j; double x, t; int main(void) { gp = popen(gnuplot, "w"); fprintf(gp, "set xrange [0:11]\n"); fprintf(gp, "set yrange [-3.5:3.5]\n"); fprintf(gp, "set xlabel \"x\"\n"); fprintf(gp, "set ylabel \"y\"\n"); char buf; for (j = 0; j < N*160; ++j) { usleep(5000); /* if((buf = fgetc(stdin)) == 'q'){ break; } */ fprintf(gp, "plot '-' with lines linetype 1\n"); for (i = 0; i < j+1; ++i) { t = 0.1*i; x = A*sin(omega*t); fprintf(gp, "%f\t%f\n", t/10, x); } fprintf(gp, "e\n"); } fprintf(gp, "exit\n"); fflush(gp); pclose(gp); return 0; }

  • C言語のプログラムに関することで質問です。

    C言語のライブラリを利用したプログラムのことで質問なのですが、座標xとyの成分から、ベクトルの角度(t)と大きさ(r)を求めるプログラムを作りました。しかし、このままのプログラムだと、ある場合のときに限り、正しい値が返されなくなるらしいのですが、それはどのような場合で正しい値が返されなくなってしまうのかを教えてください。また、正しい値がでるようにするにはどこをどう直したらよいのでしょうか? 自分でも考えてみたのですが、分からず困っています。分かる方どうかよろしくお願いいたします。 #include <stdio.h> #include <stdlib.h> #include <math.h> #define square(x) ((x) * (x)) //ベクトルの角度θを返す関数 double theta(double x, double y) { return atan(y / x); } //ベクトルの大きさを返す関数 double radius(double x, double y) { return sqrt(square(x) + square(y)); } int main(int argc, char **argv) { double x, y; //x, yは座標 double t, r; //t, rは極座標 if(argc == 3 && (x = atof(argv[1])) && (y = atof(argv[2]))) { t = theta(x, y);  //極座標tを計算 r = radius(x, y); //極座標rを計算   //ベクトルの角度と大きさを表示 printf("t = %f, r = %f\n", t, r); } return 0; }

専門家に質問してみよう