質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

3回答

2312閲覧

ftell()を自分で作る。

strike1217

総合スコア651

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

0クリップ

投稿2017/05/28 11:29

編集2017/05/28 13:36

ファイルの中身は適当に・・・

odsauodna gs g s gjsdnaofuhsodahfonsda za ds fs dg b dn gsdjbofhouhsdugf da g fdksjoufyhsodhbgd fg ds g df g gdfskjgouy

C

1 fseek(fp, 0, SEEK_END); //なくても良い 2 count = ftell(fp); 3 printf("%d Bytes\n",count);

ファイルの中の文字数をカウントします。
これを自分で作ろうとしました。
最初にやったのは・・・

C

1while((ch = fgetc(fp)) != EOF) 2 count++;

出来ませんでした。
念のため確認しました。

while((ch = fgetc(fp)) != EOF) printf("%c", ch); putchar(ch);

何も表示されません。

なぜでしょうか??

別のアプローチ

while(fscanf(fp, "%s", buf) != EOF){ sprintf(str, "%s\n", buf); } strlen(str);

最初の11文字の文字数しか取得できません。
strlen()は\0が出現するまでの文字数でしたよね??

このファイルは改行がたくさんありまが、改行=\0ではないので、strlen()でも取得出来そうですが、なぜかできません・・・

ファイルの最後にEOFがあるのは分かるのですが、このファイルをバッファの中に入れた場合、\0はどこに存在するでしょうか??

環境を書いておきます。
Linux 64bit Debianです。

[追記]
再度プログラムを最初から作り直しました。

C

1#include<stdio.h> 2#include<string.h> 3 4void copy(FILE *fp, FILE *fr){ 5 char buf[1024]; 6 char str[1024]; 7 int ch, count = 0; 8 9 /*while(fscanf(fp, "%s", buf) != EOF){ 10 sprintf(str, "%s\n", buf); 11 fputs(str, fr); 12 }*/ 13 14 while((ch = fgetc(fp)) != EOF){ 15 fputc(ch, fr); 16 printf("%c", ch); 17 count++; 18 } 19 printf("\n"); 20 printf("%d Bytes\n", count); 21} 22 23int main(int argc, char **argv){ 24 FILE *fp, *fr; 25 26 if(argc > 0) 27 fp = fopen(argv[1], "r"); 28 fr = fopen(argv[2], "w"); 29 if(!fp) 30 printf("couldn't open file\n"); 31 else{ 32 copy(fp, fr); 33 fclose(fp); 34 fclose(fr); 35 } 36 return 0; 37}

なぜかちゃんと問題なく動いています。
????

1回目のプログラムは

void copy(FILE *fp, FILE *fr){ char buf[1024]; char str[1024]; int ch, count = 0; while(fscanf(fp, "%s", buf) != EOF){ sprintf(str, "%s\n", buf); fputs(str, fr); } [ここに質問の文字数をカウントするプログラムを書いた] }

・・・正直、何がダメだったのかさっぱり・・・

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

otn

2017/05/28 13:06

プログラムの他のところに原因があるのでしょう。
strike1217

2017/05/28 13:14

他の箇所でございますか! 確認してみますね
yukkeorg

2017/05/28 13:19

プログラムの全体像がわからないので問題点がわかりずらいかと思います。ソースを開示していただけると答えやすいかと思います。
guest

回答3

0

追記ありがとうございます。

[ここに質問の文字数をカウントするプログラムを書いた]の場所では fp のファイルの位置を指し示している位置がEOFを指しているため、再度fgetc()関数を実行をしてもEOFが帰って来てしまいます。

その場所でファイルの文字(バイト)数をカウントする場合は、fseek()関数かrewind()関数を使って fp が現在指し示しているファイルの位置をファイルの先頭へセット(リセット)してあげる必要があります。

追記(22:50)
あ、cateyeさんがコメントで指摘されてましたね…

投稿2017/05/28 13:48

編集2017/05/28 13:52
yukkeorg

総合スコア985

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

strike1217

2017/05/28 13:50

「一度、fscanf()などを実行したらファイルポインタが最後を指している」ということでしょうか?
strike1217

2017/05/28 13:51

cateyeさんのコメントを元にfseek()で先頭に戻したら確かにできました!!
yukkeorg

2017/05/28 14:00 編集

FILEポインタは、fgetcやfscanfなどの関数を通すと、FILEポインタが指し示すファイルから読み込んだ分だけ位置を進めますので、その位置をコントロ―ルしたい場合はfseek関数やrewind関数などのファイル操作関数を利用します。
guest

0

気が付いたところだけですが・・・
fgetc()はintを返します。chがcharならば(処理系依存ですが:調べてみてください)EOFとの比較が出来ません。あと、

c

1while((ch = fgetc(fp)) != EOF) 2 printf("%c", ch); 3 putchar(ch); 45while((ch = fgetc(fp)) != EOF) 6{ 7 printf("%c", ch); 8 putchar(ch); 9}

にしないと、putchar(ch);はループを抜けた後になります。
たとえ1行でも"{}"で囲む癖をつけましょう。

投稿2017/05/28 13:23

cateye

総合スコア6851

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

strike1217

2017/05/28 13:25

あ、すいません。 {}つけ忘れていました。 chはint型ですね。
guest

0

ベストアンサー

fseek(fp, 0, SEEK_END);

ではなく、

fseek(fp, 0, SEEK_SET);

ではないですか?
間違っていたらすみません

投稿2017/05/28 11:41

chankane

総合スコア139

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

cateye

2017/05/28 13:32

バージョン1を見るとファイルの最後に移動して、サイズを求めていますね。で、クローズする前に先頭に戻しています。なので、SEEK_SETでないと先頭からの読み込みはできません。
strike1217

2017/05/28 13:39

あ、SEEK_SETを入れていなかったから、カウント出来なかったのかな・・・・? ちょっと確認してみます。
strike1217

2017/05/28 13:44

fseek(fp, 0, SEEK_SET); を入れたら、カウントできました!! SEEK_SETして先頭に移動しないといけないのですね!!
chankane

2017/05/28 14:20

ファイルの中身を読み込みつつカウントしたい場合には、先頭から1文字ずつ読み込む方法(今回うまくいった方法)がどちらかといえば良く、ただただ、ファイルサイズが知りたい場合には、上記のサイト様の方法がスマートです。strike1217様のコードでは、自作 ftell() 関数の実装が前者の方法に該当し、main()関数の実装が後者の方法に該当します。だからうまくいかなかったのです。 まとめると、 1. fseek(fp, 0, SEEK_SET)し(省略可)、while文で最初から1文字ずつ読み込みつつカウントする(今回はこちらで解決) 2. main()関数で fseek(fp, 0, SEEK_END) し、ftell(fp) で現在位置を出す このどちらの方法でもうまくいきますよ(*^^)v 頑張ってくださいませ
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問