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

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

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

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

エスケープ処理

エスケープ処理とは、一連の文字や一文字に対して、一定の規則に従って別の意味を適用する処理過程です。

Q&A

解決済

3回答

895閲覧

<C言語>エスケープ・シーケンスの表記は、続けて書かなくてもありなのでしょうか?

cadet_study

総合スコア13

C

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

エスケープ処理

エスケープ処理とは、一連の文字や一文字に対して、一定の規則に従って別の意味を適用する処理過程です。

0グッド

0クリップ

投稿2018/09/02 11:12

前提・実現したいこと

こんばんは。今回はエスケープ・シーケンス ( / と ESC ... など ) の使用方法(コンソールに出力する際の使用方法)について質問させていただきます。

発生している問題

エスケープ・シーケンスを printf 関数などで使用する際,改行を実行したいときには
printf("test\n"); のように \n を利用して改行を行うことを学びました。また、その他にも \a や \r を利用することで警告や復帰を行うということも知りました。
このようなこともあり、エスケープ・シーケンスに該当する文字は、「続けて」 \ や ESC[ などの後に表記するものだと思っていました。
しかし、私が使用しているテキスト(新明解シリーズ)に以下のコードがあり、エスケープ・シーケンスの表記が3つの printf 関数にまたがってされており、なぜそのような表記ができるのかが分かりませんでした。

該当のソースコード

このコードは、コンソール画面の文字の色・背景色を指定するエスケープ・シーケンスである
ESC[-;-;...m を使用して、色の変更を行うコードです。(~は省略したものです。)

C

1void color(int fg, int bg) { 2 3 int col[] = { ~ }; 4 5 printf("ESC[0;"); 6 7 if (~) { 8 9 printf("1;"); 10 11 } 12 13 printf("%d;%dm", ~); 14 15}

このように、ESC[-;-;...m のエスケープ・シーケンスが複数の printf 関数に分かれて表記されていました。
上記のコードのように、エスケープ・シーケンスの表記はその後に続けて書かなくても1つのエスケープ・シーケンスの表現としてみなされるのでしょうか?それとも、それぞれのエスケープ・シーケンスで別々の箇所で表記することが可能なものや、できないものなどが決まっているのでしょうか?

ご教授して下さると幸いです。宜しくお願いします。

試したこと

私が visual studio しか持っておらず、この動作を実際に確かめようと思ったのですが、ESC などのエスケープ・シーケンスがサポートされていないため、実行することができませんでした。

エスケープ文字(\aや\n)の実行は行うことができましたが、やはりその printf 内での引数中に書かない場合はエスケープ・シーケンスとして機能せず、存在しないエスケープ・シーケンス表記を利用したとして未定義動作?となり、実行がおかしくなってしまいました。(引数の末尾に \ のみを指定した場合は "定数が 2 行目に続いています" と,エラーになりました。)

また、上記のようなコードが他にあるのかどうかや、別々に書いてもいいのかについて探してみたのですが見つかりませんでした。

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

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

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

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

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

guest

回答3

0

文字列表記時のエスケープ表記と、エスケープシーケンスは別のものです。
一緒くたにしても意味ないですw

投稿2018/09/02 11:27

y_waiwai

総合スコア87719

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

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

cadet_study

2018/09/02 12:32

回答ありがとうございます。エスケープ表記とエスケープ・シーケンスがどのように違うのか具体的に教えてください。
y_waiwai

2018/09/02 12:46

エスケープ表記は、文字列を書くときに、文字で表せないコントロールコードを表現するために使われる便宜上の書き方です。改行コードは\n バックスペースは \b タブは\t と決められてますんで、これを分割してしまうと意味が通らなくなります。 エスケープシーケンスは、ターミナルに表示するときに、そのターミナルに特別のことをさせたいときに送る命令列のことをいいます。 文字の色を変える、とか、画面を消去、カーソル位置を移動させる、とかとか。 まーこいつは、ターミナルが、その命令列をその順番に受信できればいいだけなので、分割しようがなにしようがOKですねー
Zuishin

2018/09/02 12:50

私の回答のコメントにも書きましたが、バックスラッシュから始まるのもエスケープシーケンスです。
y_waiwai

2018/09/02 12:58

まあ、同じ呼び方もするってのもあって、まぎらわしいですわな。
Zuishin

2018/09/02 13:04

エスケープ文字を使った文字列がエスケープシーケンスです。特に紛らわしくはないと思います。 逆に「エスケープ表記」「エスケープシーケンス」と自作の方言で使い分ける方が紛らわしいと思います。 言葉の綾かと思いましたが、回答の核の部分が間違っていると判断できるため低評価します。
cadet_study

2018/09/02 13:35

お返事ありがとうございます! \ からはじまるエスケープシーケンス(エスケープ表記)は、\ とそれに続く文字が該当するコードで連続することで1つの制御コードを表すことができるため、分割することができず、コンソール制御のエスケープシーケンス(ANSI系)は、コンソールへの出力で順番に受けることができればいいため,上記のようなコードが許されるということなのでしょうか?
y_waiwai

2018/09/02 13:57

そゆことですね イマドキの人はコンソールと言ってもコマンドプロンプトとか黒いウィンドウを思い浮かべるだろうけど、その昔、コンピュータがデータセンタにしかなかった頃は、電話回線やら専用線でつながったようなコンソール装置、ターミナル装置というキカイでして、その表示を色々弄るためにエスケープシーケンスを駆使していろいろやったもんで、それでエロゲをつくったやつとかもいたとかいないとかw
cadet_study

2018/09/02 15:36

そうなのですか…  コンソールといえばコマンドプロンプトとばかり思っていましたけど、そのようなことがあったのですね… 色々と詳しい解説をして下さり本当に助かりました。 本当にありがとうございました。
guest

0

ちょっと気になったのですが、

printf("ESC[0;");

これもエスケープシーケンスの一部ですか?
もし、そうだとすると、コンソールに "ESC[0;" の文字が出力されるだけですが、それが期待する結果でしょうか?
昨今のコンソールは、エスケープシーケンスをサポートするものも少ないようですが、サポートする端末に出力しても同様です。
ESC は制御コードとして出力する必要があるので、 "\x1B[0;" とすべきでしょう。 "\x1B" ("\033"でも良いが) は、エスケープコードです。

投稿2018/09/02 12:58

pepperleaf

総合スコア6383

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

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

cadet_study

2018/09/02 13:47

お返事ありがとうございます! 実はテキストの方では \x1b としっかり表記されていまして、私が勝手に ESC でも問題ないと思ってしまっていたため、変えたものを出してしまいました。本当にご指摘ありがとうございます。 エスケープシーケンスは \ からはじまるもの,ということが原則なのですね。
pepperleaf

2018/09/02 22:31

> エスケープシーケンスは \ からはじまるもの, 違います。 他の方も書かれていますが、コンソール制御のためのエスケープは、コード '\x1B'(10進で 27)から始まるものです。 \ 記号は、文字列のエスケープコード(ただし、言語に依存)、微妙ですが、違うものです。
cadet_study

2018/09/03 05:29

つまり、エスケープシーケンスの制御命令は、それぞれの対応するエスケープコードで、一続きに表記することで命令を始める必要があり、コンソールを制御命令をするならコードとして \x1b を表記することで始め、制御文字を表記する命令をしたいなら \~ と指定する必要があるという意味でしょうか?  (それぞれの制御指令にはその該当するエスケープコードが割り当てられていて、そのコードを連続して表記することでその制御処理がスタートする,という意味なのかと…)
cadet_study

2018/09/03 06:38

もし仮に \xhh (16進文字) の hh を指定しないような,正しくエスケープコードを使用しない場合は、構文エラーになるのでしょうか,それとも未定義動作となるのでしょうか?
pepperleaf

2018/09/03 13:11

既に、他の方のコメントで解決されたかもしれませんが、、 \xhh の形式、、 文字列で、\x で始まると次は16進数字(0..F)が来ると期待されます。実際に、Visual Studio2017(*.c)で試したところ、 数字無し ... エラー 3桁以上 ... エラーでした。(実際の数値として解釈し、256を越えた場合) 古い組込み系コンパイラでは、別の動作だったので、最近の仕様なのか、コンパイラ依存なのかは分かりませんが、参考までに。 なお、\nnn (x 無しは、8進数として解釈されます。ご注意を)
cadet_study

2018/09/03 14:20

なるほど… 詳しいご説明ありがとうございました。
guest

0

ベストアンサー

例えば "abc" とコンソールに出力し、続けて改行を入れずに "def" と出力すると、コンソールには "abcdef" と出力されます。
ソースコード中では分離していても、実際の出力は連続しているということです。

"ESC[0;" はコンソールに対してのエスケープシーケンスなので、コンソールから見て連続していればいいということです。

投稿2018/09/02 11:40

Zuishin

総合スコア28656

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

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

cadet_study

2018/09/02 12:35

そうなんですか!ありがとうございます!
Zuishin

2018/09/02 12:46

ちなみに \ から始まるのは C 言語のエスケープシーケンスなので、これはソースコード中で連続していなければいけません。 それと「エスケープ表記」と「エスケープシーケンス」はおおよその文脈で同じものです。もっと正確に言うなら「エスケープシーケンスを使用した表記」が「エスケープ表記」です。 y_waiwai さんの言は、C 言語のエスケープシーケンスとコンソールのエスケープシーケンスを混同してはならないという意味で、単なる言葉の綾だと思います。
cadet_study

2018/09/02 13:23

\n や \a などの \ からはじまるエスケープシーケンスは、c言語が定義しているもので、c言語提供類のものは、そのコード内の部分で連続しなければならない決まりなのですね… コンソール制御の方は ANSI が定義したエスケープシーケンスで、ANSI 提供類のものはコンソールへの出力時に連続していれば問題ないということですか? (知識不足ながら、コンソールを制御するエスケープシーケンスについて調べたところ、ANSI 提供の エスケープシーケンスのものだと知ったので…)
Zuishin

2018/09/02 13:29

その認識で合っています。 私も見落としていたのですが、ANSI エスケープシーケンスのエスケープ文字は pepperleaf のおっしゃる通り ESC の三文字でなく \x1b ですので注意してください。
cadet_study

2018/09/02 13:42

そうなのですか… 実はテキストでは \x1b と表記されていて、私がESC でも問題ないと思っていまして勝手に変えてしまいました。ありがとうございます。エスケープシーケンスは \ から指定するのですね! 少し質問内容と逸れてしまい大変申し訳ないのですが、存在しないエスケープシーケンスを指定した場合は未定義であることは分かったのですが、仮に \ の後に何も指定しない場合も未定義の分類になるのでしょうか?(書き忘れなどが起きてしまった場合とかです…)
Zuishin

2018/09/02 13:57

「\"」は「"」を表すエスケープシーケンスです。文字列にダブルクォーテーションマークを入れたい時に使います。 例えば puts("a\"b") は a"b を出力します。 なにも指定しないというのは puts("a\") のような呼び出しのことでしょうか? だとしたらクォーテーションが閉じていないとみなされてコンパイルエラーになります。
cadet_study

2018/09/02 15:30

そうです。 puts("a\") などのような状態のとき,どのようになるのかと思いこの質問をさせていただきました。 何から何まで詳しく説明して下さり本当に助かりました。 本当にありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問