【C言語】エスケープシーケンスで特殊文字を扱う

エスケープシーケンスの解説ページアイキャッチ

このページでは、C言語における「エスケープシーケンス」について解説していきます。

今回はC言語にフォーカスを当てて解説を行いますが、エスケープシーケンスの考え方や使い方は様々な場面(他のプログラミング言語やコマンドラインからのコマンド実行など)で活用できますので、是非エスケープシーケンスについて理解していってください!

MEMO

以降ではバックスラッシュ \ の記号を利用して解説していきますが、Windows 環境の場合は \ が円マーク ¥ として扱われる場合があります

その場合は、お手数をおかけしますが、以降の解説は \¥ に置き換えて読んでいっていただければと思います

エスケープシーケンスとは

エスケープシーケンスとは、簡単に言えば「特殊な文字を扱うための文字の組み合わせ」のことです。

分かりやすい例が、皆さんもよく使用している \n です。\n は「\」と「n」 の2つの文字を組み合わせたものであり、この2つの文字を組みわせることで「改行」という特殊な意味を持った文字として扱われます。

エスケープシーケンスの例

この \n のように、特殊な文字を扱うための文字の組み合わせのことを「エスケープシーケンス」と呼びます。この「文字の組み合わせ」において、1つ目に指定する文字は、ほとんどの場合 \ となります。

エスケープシーケンスで制御を表す特殊文字を扱う

先程も挙げた \n の例のように、エスケープシーケンスを利用することで、制御を表す特殊な文字を扱うことができるようになります。

MEMO

ここからは、MacOSX 上で主にターミナルアプリを使って私が動作確認した結果に基づいて解説を行なっていきます

環境によって動作が異なる可能性があるので注意してください

制御を表す特殊な文字を扱うエスケープシーケンスには、下記のようなものがあります。

スポンサーリンク

\n:改行を行う

\n に関しては皆さんもうご存知ですよね?\n は改行を表す文字として扱われ、\n を出力することで改行を行うことができます。

改行を行う様子

例えば下記では1文字出力する度に \n を出力するようにしているため、

\nの使用例

printf("H\ne\nl\nl\no\n");

下記のように、1文字出力した後に改行が行われて出力されるようになります。

H
e
l
l
o

\r:行頭に戻る

\r は「行頭に戻る」を表す特殊文字として扱われるエスケープシーケンスになります。

「行頭に戻る」を行う様子

例えば下記では、Hello を出力した後に \r が出力されるため、次の文字の出力位置が行頭の H の位置に戻ります。そして、その H の位置から Wo\n が出力されることになります。

\rの使用例

printf("Hello\rWo\n");

そのため、上記を実行した出力結果は次のようになります。

Wollo

例えばですが、下記のようなソースコードを実行することで、

同じ位置の文字を更新する

#include <stdio.h>
#include <unistd.h>

#define N 20

int main(void) {

	for (int i = 0; i < N; i++) {
		printf("%d / %d\r", i + 1, N);
		fflush(stdout);
		sleep(1);
	}

	return 0;
}

下のアニメのように数値を同じ位置でカウントアップしていくような動作も実現することができます。

行頭に戻る様子を表すアニメ

先程紹介したソースコードでは unistd.h をインクルードしていますが、確か Windows には存在しなかったと思います。

うろ覚えですが、unistd.h の代わりに windows.h をインクルードし、sleep(1) の代わりに Sleep(1000) を実行するようにすれば、Windows 上でも同様の動作ができるのではないかと思います。

また、先程紹介したソースコードで使用している fflush 関数に関しては下記ページで解説していますので、詳しく知りたい方は下記ページをご参照いただければと思います。

fflushの解説ページのアイキャッチC言語の「fflush関数」を解説!知っておくとデバッグにも役立つよ!

\b:1文字戻る

\b は「1文字戻る」を表す特殊文字として扱われるエスケープシーケンスになります。

「1文字戻る」を行う様子

例えば下記では、Hello を出力した後に \b が3回出力されるため、次の文字の出力位置が1つ目の l の位置に戻ります。そして、その l の位置から World\n が出力されることになります。

\bの使用例

printf("Hello\b\b\bWorld\n");

そのため、上記を実行した出力結果は次のようになります。

HeWorld

スポンサーリンク

\t:水平タブを挿入する

\t は「水平タブを挿入する」を表す特殊文字として扱われるエスケープシーケンスになります。

「水平タブを挿入する」を行う様子

例えば下記では、HelloHellooo を出力した後に \t が出力されるため、水平タブを挿入した後ろ側から World\n が出力されることになります。

\tの使用例

printf("Hello\tWorld\n");
printf("Hellooo\tWorld\n");

そのため、上記を実行した出力結果は次のようになります(World の前側にあるのはスペースではなく水平タブであり、各行で World の位置が自動的に揃えられているところがポイントになります)。

Hello	World
Hellooo	World

\v:垂直タブを挿入する

\v は「垂直タブを挿入する」を表す特殊文字として扱われるエスケープシーケンスになります。

「垂直タブを挿入する」を行う様子

例えば下記では、Hello を出力した後に \v が出力されるため、垂直タブを挿入した後ろ側から World\n が出力されることになります。

\vの使用例

printf("Hello\vWorld\n");

そのため、上記を実行した出力結果は次のようになります(Hello の次の文字の位置の一行下側に移動した位置から World が出力されているところがポイントになります)。

Hello
     World

\a:音を鳴らす

\a は「音を鳴らす」を表す特殊文字として扱われるエスケープシーケンスになります。単に音ではなく警告音と言った方が正確かもしれないです。

私は MacOSX を利用していますが、ターミナルアプリで下記を実行すると「コッ」という音が3回鳴ります(実行する場合は音量に注意してください)。

\aの使用例

printf("\a\a\a\n");

おそらく音が鳴るかどうかや、鳴る音に関しては実行する環境によって異なると思います。ちなみに私が VSCode 上で実行した際には、音は鳴りませんでした。

スポンサーリンク

\0:文字列の終端を表す

\0 は「文字列の終端」を表す特殊文字として扱われるエスケープシーケンスになります。C言語で文字列を扱ったことのある方であればお馴染みだと思います。

例えば下記では、Hello の後に \0 があるため、Hello までが1つの文字列として扱われることになります。

\”の使用例

char *str = "Hello\0World";
printf("%s\n", str);

そのため、上記の printf では Hello までのみが出力されることになります。

Hello

エスケープシーケンスで特別な意味を持つ特殊文字を扱う

ここまでエスケープシーケンスを利用することで何かしらの制御を行うための特殊文字を扱ってきましたが、エスケープシーケンスは、特別な意味を持つ特殊文字を「単なる文字として扱う」目的で利用することもできます。

単なる文字として扱う目的で利用するエスケープシーケンスには、下記のようなものがあります。

\":単なる " として扱う

分かりやすい例が \" のエスケープシーケンスだと思います。

C言語では、" は「文字列の始まりと終わり」を表す特別な意味を持つ文字になります。

そのため、例えば文字列の中で " を扱いたいと思って "AB"CD" と記述した場合、"AB" までのみが文字列としてみなされ、さらにその後に意味不明な CD" が記述されていることになるのでコンパイルエラーになってしまいます。

" の持つ特別な意味を打ち消し、単なる " という文字として扱いたい場合に利用するのが \" のエスケープシーケンスになります。例えば "AB\"CD" と記述した場合、もはや \" には「文字列の始まりと終わり」を表すという特別な意味はなく、単なる " という文字として扱われます。

そのため、printf("AB\"CD") などで "AB\"CD" を出力した場合、 "AB\"CD" までが文字列として扱われ、さらに \"" という単なる文字に置き換えられた状態で出力されます。

例えば下記を実行したのであれば、

\”の使用例

printf("There is a \"pen\"\n");

下記のような出力結果を得ることができます。

There is a "pen"

この " のように、特別な意味を持っているために、そのままだと文字列や文字の中で扱えないものが存在します。

エスケープシーケンスとして記述することで、その特別な意味を打ち消すことができ、単なる文字として扱うことができるようになります。そしてそれにより、文字列や文字の中で扱えるようにすることができます。

ここからは、この「特別な意味を打ち消すため」の \" 以外のエスケープシーケンスを紹介していきます。

スポンサーリンク

\':単なる ' として扱う

C言語では、' は「文字の始まりと終わり」を表す特別な意味を持つ文字になります。

ですので、' という文字を扱いたいからといって、''' と記述するとコンパイルエラーになります。

' を単なる文字として扱いたい場合は、\' と記述します。

\’の使用例

char moji[5] = {
    '\'', 'A', 'B', 'C', '\''
};

for (int i = 0; i < 5; i++) {
    putc(moji[i], stdout);
}

\\:単なる \ として扱う

ここまで解説してきたように、\ はエスケープシーケンスの1文字目として扱われることが多く、エスケープシーケンスの始まりを表す特別な意味を持つ文字になります。

例えば、\abc\ という文字列を扱いたいからといって "\abc\" と記述してしまうと、 \" が単なる " という文字として扱われるため、文字列の終わりを表す " が足りないことになります。そのため、コンパイルエラーになってしまいます(1文字目も音を鳴らすエスケープシーケンス \a になってしまっている)。

この \ を単なる文字として扱う際には \\ と記述します。

例えば、\abc\ という文字列を出力したい場合は、下記のように \\ を利用します。

\\の使用例

printf("\\abc\\");

%%:単なる % として扱う

C言語においては、% はフォーマット指定の始まりを示す特別な文字であり、文字列の中で % を指定すると、フォーマット指定子として扱われてしまいます。

例えば printf("%d", x) などのように記述して x を表示する形式を % から始まる構文で指定した経験があると思います。

% の特別な意味を打ち消し、単なる % という文字として扱いたい場合は %% を指定します。

\% ではないので注意してください。

例えば 100% と出力したい場合は、下記のように printf を実行する必要があります。

%%の使用例

printf("100%%");

スポンサーリンク

まとめ

このページでは、C言語における「エスケープシーケンス」について解説しました。

エスケープシーケンスを利用することで、「改行を行う」「1文字戻る」といった制御を行うための特殊文字を扱うことができます。

また、エスケープシーケンスを利用することで、"\ といった特別な意味を持つ文字を単なる文字として扱うこともできます。

といっても、エスケープシーケンスとして覚えておいた方が良いのは \n くらいだと思います。もちろん、\r\b も覚えておくことで出来ることの幅が広がることは間違い無いですが、そこまで使用する機会は多く無いのかなぁと思います。

また、「”特別な意味を持つ文字” は、そのままでは文字列や文字の中で扱えない」という点もしっかり覚えておくと良いと思います。特別な意味を持つために、文字列や文字の中で使用するとコンパイルエラーになったり、意図した出力が行えない等の現象が発生することがあります。

そんな際には、まず、その “特別な意味を持つ文字” の前に \ を記述してみましょう!大体それで、その特別な意味を打ち消して “単なる文字” として扱うことができるようになります。ただ、% に関しては特別で、%% と記述する必要があるので注意してください。

ちなみに、エスケープシーケンスを利用して printf で出力する文字の色や背景色を変更するようなこともできます。これに関しては下記ページで解説していますので、興味のある方は是非読んでみてください!

printfで文字色や背景色を変更する方法の解説ページアイキャッチ【C言語】printfで文字の色や背景色を変更する

オススメの参考書

C言語学習中だけど分からないことが多くて挫折しそう...という方には、下記の「スッキリわかるC言語入門」がオススメです!

まず学習を進める上で、参考書は2冊持っておくことをオススメします。この理由は下記の2つです。

  • 参考書によって、解説の仕方は異なる
  • 読み手によって、理解しやすい解説の仕方は異なる

ある人の説明聞いても理解できなかったけど、他の人からちょっと違った観点での説明を聞いて「あー、そういうことね!」って簡単に理解できた経験をお持ちの方も多いのではないでしょうか?

それと同じで、1冊の参考書を読んで理解できない事も、他の参考書とは異なる内容の解説を読むことで理解できる可能性があります。

なので、参考書は2冊持っておいた方が学習時に挫折しにくいというのが私の考えです。

特に上記の「スッキリわかるC言語入門」は、他の参考書とは違った切り口での解説が豊富で、他の参考書で理解できなかった内容に対して違った観点での解説を読むことができ、オススメです。題名の通り「なぜそうなるのか?」がスッキリ理解できるような解説内容にもなっており、C言語入門書としてもかなり分かりやすい参考書だと思います。

もちろんネット等でも色んな観点からの解説を読むことが出来ますので、分からない点は別の人・別の参考書の解説を読んで解決していきましょう!もちろん私のサイトも参考にしていただけると嬉しいです!

入門用のオススメ参考書は下記ページでも紹介していますので、こちらも是非参考にしていただければと思います。

https://daeudaeu.com/c_reference_book/

同じカテゴリのページ一覧を表示