プロが教える店舗&オフィスのセキュリティ対策術

3つほど前に質問させてもらってますが質問の仕方をかえ
もう一度質問したいと思います。putcharとgetcharを使って

aaa,bbbb,ccc CRLF
zzz,yyy,xxxという入力は

aaa,bbb,ccc CRLF
zzz,yyy,xxx CRLF と出力する

とあるのですがCRLFを実際に打ち込んで出力してますよね?
CRLFについてはなんとなくわかったのですがこの辺が
よくわかりません。

A 回答 (11件中1~10件)

まず「改行コードとは何か」から説明せねばならないようですね。



これは、文字通り「行が改(あらた)まる事を示すコード」です。

「行が改(あらた)まる」とは「行はここで終わり。このコードの次にある文字は、次の行の先頭文字である」と言う事です。

簡単に言えば「これで1行が終わる」って事を意味するコードな訳です。

C言語の世界では、この改行コードを「制御コードの10(10進数)の文字1個」と決めました。16進数では「0A」です。

どうしてこのコードになったかと言うと、世界最初のC言語が作られたのがUNIXと言うOSで、このOSでは「テキストファイルの改行コードは、制御コードの10が1個」と決まっていたからです。

で、C言語で、文字列の中に制御コードを含める時は「\ + コード番号を8進数で3桁」か「\x + コード番号を16進数で2桁」と書く事になっています。

例えば「Hello World + 改行」を printf で出力したいなら
printf("Hello World\012");
とか
printf("Hello World\x0a");
とか書かないとなりませんでした。

これでは「お~い、改行コードって、8進数で幾つだっけ?」なんて事が良くあったので、そういう不便さを無くす為に

「\012や\x0aの代わりに\nって書いても良い事にしよう」

って事にしました。なので

printf("Hello World\n");

と書けば、最後に改行してくれるのです。

入力の場合も同じで、行の最後に\nに相当するキーを叩けば、そこで「1行の終わり」として処理され、キーボードから入力した文字列がプログラムに引き渡しされます。

その「行の最後に相当する、\nに相当するキー」とは、キーボードにある一番大きなキーである

Enter
←┘

と書かれたキーです。

ここまでは「C言語と、その開発の舞台となったUNIX系OSのお話」です。ここからは世界がガラリと変わります。

質問者さんは、Windows が搭載されたPCを使っていますか?

質問者さんがお使いの「Windows」と言うOSの元祖は「MS-DOS」と言うOSで、Windowsの中には「コマンドプロンプト」や「DOSモードで起動」と言う形で残されています。

この「MS-DOS」では、改行を行うコードは「カーソルを行頭に戻す制御コード」と「カーソル位置は変えずに1行送る制御コード」の2文字一組と決まっていました。

この「2文字一組」になった理由は、当時のコンピュータの出力装置は、ディスプレイではなく「紙送り式の1行づつ印字するプリンタ」だったからです。ブラウン管式モニター(しかも白黒)は非常に高価だった時代です。

「カーソルを行頭に戻す制御コード」は、プリンタに送ると「印字ヘッドが左端の1カラム目に戻る」と言う動作をしました。

「カーソル位置は変えずに1行送る制御コード」は、プリンタに送ると「印字ヘッドの位置はそのままで、用紙を1行分、送り出す」と言う動作をしました。

なので「次の行の先頭から印字し始める」には「カーソルを行頭に戻す制御コード」と「カーソル位置は変えずに1行送る制御コード」を、2文字一組でプリンタに送る必要があったのです。

ペアになったコードの1文字目の「カーソルを行頭に戻す制御コード」を「CRコード(Carriage Return)」と呼びます。

プリンタの印字ヘッドの事を、英語で「キャリッジ」と言います。印字ヘッド(キャリッジ)が左端1文字目に戻る(リターン)するのですから「キャリッジ・リターン」と言う訳です。

ペアになったコードの2文字目の「カーソル位置は変えずに1行送る制御コード」を「LFコード(Line Feed)」と呼びます。

プリンタの用紙を行(Line)送り(Feed)するのですから「ライン・フィード」と言う訳です。

プリンタに送るコードが上記のようになっていたので、MS-DOSでは文字のコード番号をプリンタに合わせ「CRコード」を「10進数で13、16進数で0Dの制御コード」に「LFコード」を「10進数で10、16進数で0Aの制御コード」に決めました。

そして、キーボードから「Enterキー」を押した時は「内部で、仮想的にCRキーとLFキーが押された事にして、CRのコードとLFのコードをペアにして入力させる」と言う細工をしました。

このように、MS-DOSやWindowsの世界では「Enterキーを押したら入力されるコード」は「CRとLFのペア」であり、テキストファイルの中に保存されている「改行を示すコード」も「CRとLFのペア」になっています。

なので「MS-DOS系の人」は「改行コード」の事を「CR+LF」とか「CRLF」とか表記します。

この「CRLF」の表記が、今回、質問者さんが目にした「改行を意味するらしい、謎の表記」な訳です。

では、話をC言語に戻します。

「C言語では、改行コードは\rと書く」と説明しました。

しかも「\r」の「1文字のみ」です。MS-DOSやWindowsのように「2文字で一組」にする必要はありません。

でも、C言語で

printf("Hello World\n");

と書いたプログラムを書いてMS-DOSやWindowsで動かせば「Hello Worldと改行」が出力されます。

実は、MS-DOSやWindows用のC言語用ライブラリには「\nの1文字をCRコード+LFコードの2文字のペアに変換して出力したり、CRコード+LFコードの2文字のペアを\nの1文字に変換して入力するモード」と言うのが仕様追加されているのです。

それが、俗に言う「ファイルを開く時の、テキストモードとバイナリモードの指定」なのです。

テキストモードで開くと、MS-DOSやWindows用のC言語用ライブラリは「\n⇔CRコード+LFコード」の変換をします。

バイナリモードで開くと、この変換は行われません。

なお「初期にMS-DOSに移植されたCコンパイラ」は、このテキストモードとバイナリモードの切り替えが無かったので「Hello Worldと改行」を書くには

printf("Hello World\r\n");
printf("My name is TARO\r\n");
printf("Goodby\r\n");

と書かねばなりませんでした。さもないと、画面表示が
Hello World
       My name is TARO
                   Goodby.
などのようになって「改行でカーソルが左端に戻らない」なんて事が起きました。

昔は「動作させる環境により改行コードが違ったので、違うOSに乗せ換える時に、改行コードを書き換えてた」のです。

これでは不便なので「改行コードを書き換えなくても、テキストかバイナリか指定するオープンモードの指定部分さえ追加すれば、そのまま書き換えずに使える」ようにしたのです。

これで「CRLFとは何者であるか」が理解出来れば良いのですが…。
    • good
    • 0

「A=B、B=Cである、だからA=Cである。


A=B、B≠Dである。だからA≠Dである。」
という数学の考え方を当てはめてみて下さい。


・CRは文字コード0x0dである
・LFは文字コード0x0aである

・UNIXの改行コードはLFである
・DOSの改行コードはCRLF である
・Macの改行コードはCRである

・\nは改行コードを示す。


\nは文字コードで表すと何になりますか?
-> UNIXでは・・・ \n=改行コード、改行コード=LFだから\n=0x0a
-> DOSでは・・・ \n=改行コード、改行コード=CRLFだから\n=0x0d 0x0a
-> Macでは・・・ \n=改行コード、改行コード=CRだから\n=0x0d


改行コードとはCR、CRLF、LFのどれですか?
-> CR、CRLF、LFのいずれかである
「改行コード」という「呼び方」が同じというだけで、どれになるかはOSによって異なる。


LFはDOSにとっての改行コードですか?
-> いいえ。
DOSにとっての改行コードはCRLFですので、LFは「DOSにとっての改行コードではない」。


> aaa,bbbb,ccc CRLF
> zzz,yyy,xxxという入力は
推測ですが。

キーボードからの入力とすると、入力を終了させるために、xxxの後にエンターキーを押していると思いますので、
こういう入力になると思います。(DOSで実行している場合)

aaa,bbbb,ccc CRLF
zzz,yyy,xxx CRLF


これを順番にgetcharで取り込み、putcharで出力すると

> aaa,bbb,ccc CRLF
> zzz,yyy,xxx CRLF と出力する
この状態になると思います。


# C言語はCGIカウンターくらいにしか使わないので突っ込んだ質問はご容赦下さい。
    • good
    • 0

#9 で、UNIX を範とした OS-9 は、Enter は、<CR> で、CTRL + J でした。


こっちは、UNIX は範としたけれども、端末が <CR> が多かったせいかな。
    • good
    • 0

#8 chie65535 さんへ


(minaraiH さんは見ないでね、余計にこんがらがりそうだから)

復帰と改行が逆になってませんか?

もともと、C言語は、UNIX から来ているので、
改行文字は '\n' new line だったはず。
'\r' は、return 何とか
つまり最初は、
'\n' は、<LF>
'\r' が、<CR>
UNIX で使っていた端末が、たまたま Enter キーに、<LF> が割り当てられていたんじゃないかと思いますが・・・

MS-DOS のCも昔は、'\n' は、13 だったと思います。
いまだに名残で、キーボードからは13番目の文字 CTRL + M で改行します。
多分、UNIX 系のものは、MAC 以外は、13 でないでしょうか?

1980年代くらいからしか知りませんが、端末装置の Enter キーは CTRL + 'J' の 復帰 が多く割り当てられていたので、
かなり異端だと思ってはいましたが・・・まあ、当時ですから、改行文字のコードなんて、そんなものでしょう。
    • good
    • 0

CRLF は、「目に見えない」制御文字の呼称(略記?)の1つです。



 http://e-words.jp/p/r-ascii.html

本などに記述する場合、CRLF と「目に見えるように」せざるを得ません。
地図には、赤道が描かれていますが、実際はどうなんだろう(未確認、残念)。

>(スペース)CRLFとあるがこれはこのとおり4文字ではなく

 スペースは「目に見えない」から、"(スペース)"と記述したのと同じです。

 CR : Carriage Return 行頭復帰 \r 0x0D
 LF : Line Feed    改行   \n 0x0A

 ・末尾は、16進のコードです(1バイト)。
 ・その前が、エスケープシーケンスで、★ソース中に記述するのはこれです。

 コンパイラは、出力フォーマット中の、\r や \n は理解できますが、CRLF はただの文字列とします。

☆なお、「改行」は、OSにより異なります。

  http://hp.vector.co.jp/authors/VA016670/escape_c …

 MS-windows(MS-DOS) では \n が改行で、出力されるコードは、0x0D 0x0A(\r\n) の2バイトとなります。
 \n 5ケ出力したファイルは、サイズが10バイトとなります。
++++++++++++++++++++++++++++++++++++++++
前回の

>後出力画面に\\ と \"に出力する方法がわかりません。

 これについて、 \\ \" 「と」出力したいとすると、

 printf( "\\\\ \\\"" ); とするのが普通ですが

 printf( "%c%c %c%c", 0x5C, 0x5C, 0x5C, 0x22 ); や
 printf( "\\\\ \\%c", 0x22 ); とも記述出来ます。

  http://e-words.jp/p/r-ascii.html

>printf("\\");としても\1個だけ

 エスケープシーケンスの約束事です。

>printf("\\\");とすればエラーがでます。

 " が対になっていないからです( \" の " は、フォーマット中の " とコンパイラが認識)
    • good
    • 0

いや, さすがに


CRLF とあったら普通は「復帰 (0x0d), 改行 (0x0a) の 2バイトシーケンス」である
ことはわかりますけど>#2~#4, それはやっぱり質問者から答えてほしかった....
ついでにいうと CRLF をして「改行コード」というのもどうかと思う. (テキストストリームにおける) 「改行コード」には典型的な物でも
・CR (0x0d)
・LF (0x0a)
・CR, LF (0x0d, 0x0a)
の 3通りがあります. そして
・テキストストリームとの入出力では処理系依存の変換がおこなわれることがある
ので, 処理系を決めるなり「どこから入力してどこに出力するのか」を決めるなりしないとプログラムを作ることは不可能です (後者は必須, テキストストリームである場合は前者も必要). 例えば, 「改行コードが CR であるような処理系」でテキストストリームに "xxx,yyy,zzz \n" と書くと, 実際には
xxx,yyy,zzz CR
と書きだされることになりますが, 厳密にいうとこれは質問者の意図とは異なる動作といえます. さらには, この場合「CRLF を追加する」ことは不可能です (CR を書きだしても LF を書きだしても, 実際に書かれるのは CR だから).
    • good
    • 0

No.2です。


ますます意味がわからなくなりました。
確実に肝心の部分を読み飛ばしているか理解してません。

私はNo.2で
-----------------
>putcharとgetcharを使って
>
>aaa,bbbb,ccc CRLF
>zzz,yyy,xxxという入力は
>
>aaa,bbb,ccc CRLF
>zzz,yyy,xxx CRLF と出力する
>とあるのですが
「あるのですが」とは、「どこにあった」ものでしょうか?
-----------------
と聞いています。
それは、質問文の

>この辺がよくわかりません。

にその上までの内容がつながらないからです。
その為、「どこにあった」とたずねています。
返答は期待していたものではありません。
「テキスト」と返答があれば「そのテキストの前に記載されている部分についても追記してください」と返答していました。

私の「推測」(あくまでも推測です)では、
(画面上に)
「aaa,bbb,ccc」(改行して)
「xxx,yyy,zzz」(を表示し、さらに改行しておくには)
(CRLFを付加して)
 printf( "aaa,bbb,ccc \n");
 printf( "xxx,yyy,zzz \n");
(とCRLF「\n」を記述する。)
のような内容ではないかと推測はしてますけど。
    • good
    • 0

キャラクタコード表。


http://hp.vector.co.jp/authors/VA008536/data/asc …
CRもLFも制御コードで1バイトのコードです。
C言語ではエスケープシーケンスで表現します。
http://ja.wikipedia.org/wiki/%E6%94%B9%E8%A1%8C% …
    • good
    • 0

CRはCarriage Returnの略、ASCIIコードでは10進数で13、16進数で0x0D


LFはLine Feedの略、ASCIIコードでは10進数で10、16進数で0x0A
Windowsでは改行に0x0D 0x0Aの2バイトを使うのでそれをあわせてCRLFと表記したのでしょう。
0x0Dと'\r'、0x0Aと'\n'は同じ値になります
    • good
    • 0

前の質問


http://okwave.jp/qa4998753.html
「CRLF」は「0x0D、0x0D」(CarrigeReturn- LineFeed)のことでしょう < No.1

正直、今回の質問の意図が読み取れません。
>putcharとgetcharを使って
>
>aaa,bbbb,ccc CRLF
>zzz,yyy,xxxという入力は
>
>aaa,bbb,ccc CRLF
>zzz,yyy,xxx CRLF と出力する
>とあるのですが
「あるのですが」とは、「どこにあった」ものでしょうか?
何らかのテキストの一部のようにも思えますが、上2行と下2行のつながりが見えてきません。
これが明確にならない限り、意図した回答は得られないと思います。

この回答への補足

(スペース)CRLFとあるがこれはこのとおり4文字ではなく
改行コードがくることを意味する。

とぐらいしか書いてないですね

補足日時:2009/05/29 12:57
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!