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

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

ただいまの
回答率

89.50%

ftell()を自分で作る。

解決済

回答 3

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 1,071

strike1217

score 581

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

odsauodna
gs
g
s
gjsdnaofuhsodahfonsda
za
ds
fs
dg
b
dn
gsdjbofhouhsdugf
da



g
fdksjoufyhsodhbgd
fg
ds
g
df
g

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


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

while((ch = fgetc(fp)) != EOF)
          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です。

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

#include<stdio.h>
#include<string.h>

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);
    }*/

    while((ch = fgetc(fp)) != EOF){
                fputc(ch, fr);
        printf("%c", ch);
        count++;
        }
    printf("\n");
    printf("%d Bytes\n", count);
}

int main(int argc, char **argv){
    FILE *fp, *fr;

    if(argc > 0)
        fp = fopen(argv[1], "r");
        fr = fopen(argv[2], "w");
    if(!fp)
        printf("couldn't open file\n");
    else{
        copy(fp, fr);
        fclose(fp);
        fclose(fr);
    }
    return 0;
}

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

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);
    }
    [ここに質問の文字数をカウントするプログラムを書いた]
}


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

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • otn

    2017/05/28 22:06

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

    キャンセル

  • strike1217

    2017/05/28 22:14

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

    キャンセル

  • yukkeorg

    2017/05/28 22:19

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

    キャンセル

回答 3

+1

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

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


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

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/05/28 22:25

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

    キャンセル

+1

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

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

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

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

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/05/28 22:50

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

    キャンセル

  • 2017/05/28 22:51

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

    キャンセル

  • 2017/05/28 22:59 編集

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

    キャンセル

checkベストアンサー

0

fseek(fp, 0, SEEK_END);


ではなく、

fseek(fp, 0, SEEK_SET);


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

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/05/28 22:39

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

    キャンセル

  • 2017/05/28 22:44

    fseek(fp, 0, SEEK_SET);
    を入れたら、カウントできました!!

    SEEK_SETして先頭に移動しないといけないのですね!!

    キャンセル

  • 2017/05/28 23:20

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

    キャンセル

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

  • ただいまの回答率 89.50%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る