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

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

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

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

ファイル

ファイルとは、文字列に基づいた名前又はパスからアクセスすることができる、任意の情報のブロック又は情報を格納するためのリソースです。

Q&A

解決済

5回答

4315閲覧

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

tada_tadaa

総合スコア111

C

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

ファイル

ファイルとは、文字列に基づいた名前又はパスからアクセスすることができる、任意の情報のブロック又は情報を格納するためのリソースです。

0グッド

1クリップ

投稿2016/02/04 08:13

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

c

1#include <stdio.h> 2#include <stdlib.h> 3 4int main(int argc, char *argv[]) 5{ 6 long loc; 7 FILE *in, *out; 8 char ch; 9 10 /* コマンドライン引数の値が正しいか調べる */ 11 if(argc!=3) { 12 printf("使用法:<プログラム名> <コピー元> <コピー先>\n"); 13 exit(1); 14 } 15 16 if((in = fopen(argv[1], "rb"))==NULL) { 17 printf("入力ファイルを開くことができません\n"); 18 exit(1); 19 } 20 21 if((out = fopen(argv[2], "wb"))==NULL) { 22 printf("出力ファイルを開くことができません\n"); 23 exit(1); 24 } 25 26 /* コピー元ファイルの終端に達する */ 27 fseek(in, 0L, SEEK_END); 28 loc = ftell(in); 29 30 /* ファイルを逆順にコピーする */ 31 loc = loc-1; /* ファイル終端マークから後退する */ 32 while(loc >= 0L) { 33 fseek(in, loc, SEEK_SET); 34 ch = fgetc(in); 35 fputc(ch, out); 36 loc--; 37 } 38 fclose(in); 39 fclose(out); 40 41 return 0; 42}

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

aaa.txtの内容は
abcdefghijklmnopqrstuv
wxyz0123456789

bbb.txtの内容は
9876543210zyxw

vutsrqponmlkjihgfedcba

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

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

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

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

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

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

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

guest

回答5

0

ベストアンサー

こんにちは。

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

投稿2016/02/04 08:25

Chironian

総合スコア23272

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

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

tada_tadaa

2016/02/04 09:51 編集

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

2016/02/04 10:06

> ただ、なぜか先頭に空白行があるので、先頭で改行しているものと思われます。なぜかは分りません。 単純にaaa.txt最後の"\n"がbbb.txtの頭に来ただけと思います。 そして、bbb.txtは最後の行が改行されてないのではないでしょうか?
tada_tadaa

2016/02/04 10:31

Linuxでaaa.txtファイルの末尾には改行があるようには見えないです。もしかしたらあるのかも しれません。 aaa.txtの中身 abcdefghijklmnopqrstuv wxyz0123456789 で、カーソルは9のところで点滅している状態でそれ以上カーソルを後ろにやることはできない状態 で保存しています。 >そして、bbb.txtは最後の行が改行されてないのではないでしょうか? bbb.txtの最後の行は改行されているようには見えないです。わかりませんが。 bbb.txtの中身 (空白行) 9876543210zyxw vutsrqponmlkjihgfedcba で、カーソルはaのところで点滅していて、それ以上後ろに動かせない状態です。
tada_tadaa

2016/02/04 12:08 編集

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

0

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

投稿2016/02/04 09:50

catsforepaw

総合スコア5938

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

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

tada_tadaa

2016/02/04 10:00

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

0

とりあえず

C

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

やってみるかな

投稿2016/02/04 09:05

WoodenHamlet

総合スコア306

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

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

tada_tadaa

2016/02/04 10: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" となってて一つの改行だけのように見えます。 とりあえず疑問が解決して良かったです。
guest

0

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

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

投稿2016/02/04 08:29

sekitaka_1214

総合スコア509

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

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

tada_tadaa

2016/02/04 09:35

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

0

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

投稿2016/02/04 09:06

otn

総合スコア84489

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

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

tada_tadaa

2016/02/04 11: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にして保存して 実行するのが一番確かな気がします。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.49%

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

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

質問する

関連した質問