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

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

ただいまの
回答率

88.78%

C言語でファイルの内容を別のファイルに順序を逆にしてコピーしたのですが少し気になる点があります

解決済

回答 5

投稿

  • 評価
  • クリップ 1
  • VIEW 2,282

tada_tadaa

score 94

C言語でファイルの内容を順序を逆にして、別のファイルにコピーするプログラム文があるのですが、
実際に実行してみると、確かに逆にはなるのですが、なぜか改行が一つ増えてコピーされてしまって
いるようです。以下がプログラム文です。

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
    long loc;
    FILE *in, *out;
    char ch;

    /* コマンドライン引数の値が正しいか調べる */
    if(argc!=3) {
        printf("使用法:<プログラム名> <コピー元> <コピー先>\n");
        exit(1);
    }

    if((in = fopen(argv[1], "rb"))==NULL) {
        printf("入力ファイルを開くことができません\n");
        exit(1);
    }

    if((out = fopen(argv[2], "wb"))==NULL) {
        printf("出力ファイルを開くことができません\n");
        exit(1);
    }

    /* コピー元ファイルの終端に達する */
    fseek(in, 0L, SEEK_END);
    loc = ftell(in);

    /* ファイルを逆順にコピーする */
    loc = loc-1; /* ファイル終端マークから後退する */
    while(loc >= 0L) {
        fseek(in, loc, SEEK_SET);
        ch = fgetc(in);
        fputc(ch, out);
        loc--;
    }
    fclose(in);
    fclose(out);

    return 0;
}


コピー元ファイルは aaa.txt
コピー先ファイルは bbb.txt

aaa.txtの内容は
abcdefghijklmnopqrstuv
wxyz0123456789

bbb.txtの内容は
9876543210zyxw

vutsrqponmlkjihgfedcba

です。僕の予想ではbbb.txtの内容は
9876543210zyxw
vutsrqponmlkjihgfedcba

だったのですが、実際はなぜか改行が1つ余計に増えてるように見えます。
この実行結果は正しいのでしょうか?
なぜ改行が1つ増えているのでしょうか?
お分かりの方がいれば教えていただければと思います。

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 5

checkベストアンサー

+2

こんにちは。

Windowsで処理されてますか?
Windowsの場合、改行は"\r\n"です。それが逆順になって"\n\r"となり、あり得ない筈のコードが来たため、表示ソフトが混乱して2回改行してしまっているのではないでしょうか?

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2016/02/04 18:44 編集

    回答ありがとうございます。

    >Windowsで処理されてますか?

    Windowsで処理しています。Chironianさんがおっしゃられているとおり、秀丸エディタのバイナリ・
    モードで確認したところ、コピー先のファイルの改行が 0A,0D,となっており、あり得ない改行コード
    のようです。
    試しにLinuxで実行してみたところ
    (空白行)
    9876543210zyxw
    vutsrqponmlkjihgfedcba
    で、wとvの間の改行は一つになりました。ただ、なぜか先頭に空白行があるので、先頭で改行
    しているものと思われます。なぜかは分りません。
    とりあえず、疑問が解けたので良かったです。
    ありがとうございました。

    キャンセル

  • 2016/02/04 19:06

    > ただ、なぜか先頭に空白行があるので、先頭で改行しているものと思われます。なぜかは分りません。

    単純にaaa.txt最後の"\n"がbbb.txtの頭に来ただけと思います。
    そして、bbb.txtは最後の行が改行されてないのではないでしょうか?

    キャンセル

  • 2016/02/04 19:31

    Linuxでaaa.txtファイルの末尾には改行があるようには見えないです。もしかしたらあるのかも
    しれません。
    aaa.txtの中身
    abcdefghijklmnopqrstuv
    wxyz0123456789
    で、カーソルは9のところで点滅している状態でそれ以上カーソルを後ろにやることはできない状態
    で保存しています。

    >そして、bbb.txtは最後の行が改行されてないのではないでしょうか?

    bbb.txtの最後の行は改行されているようには見えないです。わかりませんが。
    bbb.txtの中身
    (空白行)
    9876543210zyxw
    vutsrqponmlkjihgfedcba
    で、カーソルはaのところで点滅していて、それ以上後ろに動かせない状態です。

    キャンセル

  • 2016/02/04 21:06 編集

    Linuxでファイルの末尾が改行コードかどうか調べる方法がありましたので調べてみました。

    https://teratail.com/questions/5315

    $ tail -c 1 aaa.txt | xxd -p
    を実行してみたら
    0aで改行コードがあるということがわかりました。
    loc = loc-1; /* ファイル終端マークから後退する */を
    loc = loc-2; /* ファイル終端マークから後退する */にしたら先頭の空白行はなくなりました。

    キャンセル

+1

予想ですが、\r\nが逆順にコピーされて\n\rになって、テキストエディタによって、改行2つに解釈されているのではないでしょうか。

一度各ファイルの内容を16進文字列で確認してみてはどうでしょう?

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2016/02/04 18:35

    回答ありがとうございます。

    秀丸エディタのバイナリ・モードで文字列を確認したところ、コピー元のファイルでは改行文字が
    0D,0A, となっておりました。コピー先では 0A,0D,となっており、windowsでは改行コードは
    CR+LFでASCII文字コードでは0D,0A,に該当してましたので、コピー先の0A,0D,という改行コード
    は、存在しないっぽいので、おっしゃられるように、テキストエディタによって、改行2つに解釈され
    ているものと思われます。

    キャンセル

+1

とりあえず

while(loc >= 0L) {
    fseek(in, loc, SEEK_SET);
    ch = fgetc(in);
    printf("\"%c\"", ch); /* 一体何が起きているというんだ… */
    fputc(ch, out);
    loc--;
}


やってみるかな

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2016/02/04 19:18

    回答ありがとうございます。

    コマンドプロンプトには
    "9""8""7""6""5""4""3""2""1""0""z""y""x""w""
    ""v""u""t""s""r""q""p""o""n""m""l""k""j""i""h""g""f""e""d""c""b""a"
    と表示されました。
    秀丸エディタで、コピー元のファイルの改行コードをWindowsのCR+LFからLFにして保存して
    実行したところ、改行は1つになりました。他の方がおっしゃてるようにLF+CRでコピー先のファ
    イルに保存されてました。それでありえない改行コードLF+CRをエディタが2個の改行に変換した
    ようです。しかし、少し不思議なのは printf("\"%c\"", ch);を入れて実行したところコマンドプロン
    プトには
    "w""
    ""v"
    となってて一つの改行だけのように見えます。
    とりあえず疑問が解決して良かったです。

    キャンセル

+1

おそらく、そのプログラムはLinuxなどのUNIX系OSで動かすことを前提に作られたのではないでしょうか。テキストを扱うときはWindowsかUNIX系かでだいぶ異なります。
秀丸エディタをお使いであれば、改行コードを「LF」で保存したものを使えば期待通りに動きます。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2016/02/04 19:00

    回答ありがとうございます。

    おっしゃられる通り、コピー元のファイルの改行コードを「LF」で保存して、プログラムを実行したとこ
    ろ、きちんと改行は一つになりました。
    コピー先ファイルの内容
    9876543210zyxw
    vutsrqponmlkjihgfedcba

    キャンセル

0

原因は他の方の回答の通り。
オープン時のモード指定で、"r""w"とバイナリの b を外せばいいです。
テキスト処理の時に、b を指定してはいけません。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2016/02/04 20:34

    回答ありがとうございます。

    >オープン時のモード指定で、"r"、"w"とバイナリの b を外せばいいです。

    if((in = fopen(argv[1], "r"))==NULL) {
    if((out = fopen(argv[2], "w"))==NULL) {
    で試してみましたが、改行は2個でした。
    9876543210zyxw

    vutsrqponmlkjihgfedcba
    やはり、コピー元のファイルを保存するときに改行コードをWindowsのCR+LFからLFにして保存して
    実行するのが一番確かな気がします。

    キャンセル

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

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

関連した質問

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

  • トップ
  • Cに関する質問
  • C言語でファイルの内容を別のファイルに順序を逆にしてコピーしたのですが少し気になる点があります