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

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

ただいまの
回答率

90.01%

プログラムbcopyはコンパイルできるのですが

解決済

回答 2

投稿 編集

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

sanchu52

score 169

プログラムbcopyでコンパイルできるのですがうまくコピーできません。ファイルLACKNUM2.DAT(44バイト)をファイルLACKNUM3.DATにコピーしてもファイルLACKNUM3.DAT(0バイト)となっています。教科書どおりに打ち込んでいるんですが。どこが悪いのでしょうか。

/* bcopy … ファイルのコピー */
#include <stdio.h>
#include <strings.h>


#define    BSIZE        128            // この大きさ(128byte)に分割してコピー 

int main(int argc, char *argv[])
{
    int      n;
    FILE  *src, *dst;           // *srcと *dstはファイルポインタ 
    unsigned char  buf[BSIZE];

    if (argc != 3) {
        fprintf(stderr, "パラメータが不正です。\n");
        fprintf(stderr, "bcopy コピー元ファイル名 コピー先ファイル名\n");
    } else {
        if ((src = fopen(*++argv, "rb")) == NULL) {        
                        // *++argv=const char *filenameも ,"rb"=const char *modeもポインタ
                        // *argvはコピー元ファイル名
            fprintf(stderr, "ファイル%sがオープンできません。\n", *argv);
            return (1);
        } else if ((dst = fopen(*++argv, "wb")) == NULL) {
                        // *argvはコピー先ファイル名
            fprintf(stderr, "ファイル%sがオープンできません。\n", *argv);
            fclose(src);
            return (1);
        } else {
            while ((n = fread(buf, BSIZE, 1, src)) > 0) {
                   //コピー元ファイル名(src)からbufに読み込む
                   // ファイルポインタsrcから BSIZE バイトのデータを 
                   // 1 個読み込み、読み込みデータ格納先のポインタbufに格納する */

                fwrite(buf, n, 1, dst);        //bufからコピー先ファイル名(dst)に読み込む
            }
            fclose(src);
            fclose(dst);
        }
    }
    return (0)
}

実行結果
...@naka ~
$ gcc -o bcopy bcopy.c -Wall

...@naka ~
$ bcopy LACKNUM2.DAT LACKNUM3.DAT

...@naka ~
$
  • 気になる質問をクリップする

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 2

+1

これ、よく初心者がハマるところです。

freadのリファレンス(MSDNより)をよーーーく見てみましょう。

以下抜粋

size_t fread( 
   void *buffer,
   size_t size,
   size_t count,
   FILE *stream 
);

パラメーター
buffer
    データの格納場所。
size
    項目のバイト単位のサイズ。
count
    読み取る項目の最大数。
stream
    FILE 構造体へのポインター。

戻り値
    fread で エラーが発生したり、ファイルの末尾に到達する countの前に発生した実際に読み込まれる count 未満である、完全な項目数を返します。

戻り値の「項目数」って……。

つまりこういうことです。

n = fread(buf, BSIZE, 1, src)
fwrite(buf, n, 1, dst);

fread関数でBSIZEバイトのデータを「1個」読み込み、成功したので「1個読んだよ」という意味で「1」が返されます。そして結果的fwrite関数に「1バイトのデータを1個書け」というふうに引数が渡されるので、期待通りに動かないというわけです。

fread、fwriteには、第2引数に1を、サイズは第3引数に指定するというのが定石です。これだと、1バイトのデータをBSIZE個読み込む、あるいは書き込む、という意味になり、期待通りに動くようになります。


追記
すみません。ちょっと見落としていましたコピー先「LACKNUM3.DAT」が0バイトですね。

#define    BSIZE  128

前述のfreadで128バイトのデータを1個読むように指定していますが、srcのファイルが128バイトに満たず、結果的に「読めなかった」ので「0」が返されますね。

対処方法は前述の通りです。バイト単位で処理できるようにすることで、そのような問題も回避できます。

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2016/01/24 19:12

    ありがとうございます。おっちょこちょいで申し訳ありません。
    freadを何回も読み直していたんですが、気が付きませんでした。
    この前のプログラムでfprintfのformatで分からないところがあり、
    疲れていました。

    キャンセル

checkベストアンサー

0

最後のreturn;が無いので、コンパイルエラーになるはずです。

また、下記のようにfreadfwriteの引数を変更して下さい。

while ((n = fread(buf, 1, BSIZE, src)) > 0) {
と
fwrite(buf, 1, n, dst);

あと、returnの値に無用な括弧を付けないようにしましょう。

これが教科書通りなのであれば、良くない教科書ですね。

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2016/01/24 18:51

    勘違いがあったので訂正しました。

    キャンセル

  • 2016/01/24 19:05

    ありがとうございます。これからもちょくちょくお世話になると思います。
    よろしくおねがいします。

    キャンセル

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

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