Ruby
 Computer >> コンピューター >  >> プログラミング >> Ruby

Rubyで学ぶ文字列エンコーディング入門:ASCIIとUnicodeの仕組みを徹底解説

コンピュータが理解できるのは「0」と「1」だけ。そんなデジタルの世界で、いったいどうやって文字列は存在しているのでしょうか?

答えはシンプルです。

ドメイン名をIPアドレスに対応付けられるように。

バーコードを特定の商品に対応付けられるように。

私たちは…

数字を文字に対応付けることができるのです!

例えば、97"a" に。

122"z" に。

まさにこの仕組みによって、数字だけの世界に文字が生まれます。

では、どの数字がどの文字に対応しているのでしょうか?

この問いに答えるために、人類はさまざまな文字マッピングシステム(文字エンコーディング)を考案してきました。

その始まりがASCIIです。

ASCIIとは何か

ASCIIは「American Standard Code for Information Interchange(米国情報交換標準コード)」の略称です。

ASCII対応表を参照してもよいですし、Rubyに文字からASCII値への変換を頼むこともできます。

こんな感じです:

"a".ord
# 97

複数の文字の場合:

"abc".bytes
# [97, 98, 99]

逆に、整数があればそれに対応する文字を取得することもできます。

こんな感じです:

97.chr
# "a"

ASCIIエンコーディングに含まれるもの:

  • 制御文字(改行、タブ、NULLなど)
  • 記号(括弧、イコール、疑問符など)
  • 数字(0〜9)
  • 英字(a-z、A-Z)

この記事の後半で説明しますが、この文字の範囲には大きな限りがあります。

なぜなら…

中国語や日本語など、他の言語の文字や記号が含まれていないからです。

現実世界でのASCIIの活用例

数字と文字の対応付けは、裏側で自動的に行われています。

しかし、実用的な使い道もあるのです!

例えば:

HTTPの仕様では、URLの中に特定の文字を使用することができません。

しかし、無効な文字をASCII形式でエンコードすれば、ほとんどの最新のWebサーバーは正しく解釈してくれます。

example.com/a+++ => example.com/a%2B%2B%2B

%2B とは何でしょうか?

これは文字 + をASCIIエンコードした形式です。

さらに、この知識を応用して文字を変換することもできます。

例えば:

ASCII表を見ると、小文字から32を引けば大文字に変換できることに気づきます。

("a".ord - 32).chr
# "A"

もちろん、逆方向でも同じことができます。

("A".ord + 32).chr
# "a"

そうです。

Rubyには upcasedowncase メソッドが用意されています。

しかし、面接の質問やコーディングチャレンジなどの場面では、この知識が思わぬところで役立つかもしれません。

Unicodeとは何か

ASCIIでエンコードできるのは最大127種類の文字(拡張ASCIIなら256種類)だけです。これでは表現できる文字が大きく制限されてしまいます。

その解決策は?

それはUnicodeです。

Unicodeとは、最大100万種類以上の文字を表現できる文字列エンコーディングシステムです。

ASCIIよりもはるかに広い容量があります!

おかげで、あらゆる言語の文字、新しい記号、さらには絵文字まで扱えるようになりました。

Unicodeの一例:

ɑΩϕβΣπ

これらはギリシャ文字で、ASCIIでは表示することができません。

RubyでUnicodeを使う方法

RubyはUnicodeをサポートしており、Ruby 1.9以降はデフォルトで有効になっています。

だからこんなこともできます:

π = 3.141592

あるいはこう:

def ★★★
  puts "You get 3 stars, great job!"
end

★★★
# "You get 3 stars, great job!"

なかなか楽しいですね!

ただし、これらの記号はキーボードに存在しないため、メソッド名や変数名に使うのは実用的とは言えません。

実は、有効でありながら目に見えないUnicode文字も存在します。

例:

def ​
  puts "Invisible method"
end
​

一見すると、名前のないメソッドのように見えます。通常であれば許可されません。

しかし、見えないUnicode文字のおかげで正しく動作するのです!

文字列エンコーディング関連のメソッド

Rubyには、さまざまなエンコーディングを扱うためのメソッドが用意されています。

例えば:

"abc".encoding.name
# "UTF-8"

特殊なケースですが、現在設定されているエンコーディングencoding.name)と、文字列の実際のエンコーディングが一致しないことがあります。

これは、Webサイト、ファイル、データベースなどの外部ソースからデータを読み込む際に発生しがちです。

その結果、InvalidByteSequenceError というエラーが発生します。

その場合はエンコーディングを変換する必要があります

どうやって?

encode メソッドを使います:

"abcΣΣΣ".encode("ASCII", "UTF-8", undef: :replace)

# "abc???"

ここでは UTF-8(Unicode)からASCIIへ変換を行っています。Σ という文字はASCIIに存在しないため、Rubyに対して置換を指示しています。

デフォルトでは、未定義の文字は疑問符に置き換えられます。

しかし、この挙動は変更可能です。

こんな感じに:

"abcΣΣΣ".encode("ASCII", "UTF-8", invalid: :replace, undef: :replace, replace: "")

# "abc"

あるいは「fallback」オプションを使う方法もあります:

"abcΣΣΣ".encode("ASCII", "UTF-8", fallback: {"Σ" => "E"})

# "abcEEE"

これは次のような意味です:

「UTF-8(Unicode)からASCIIへすべての文字を変換する際、ASCIIに存在しない文字はfallbackハッシュを使って置き換える」。

もうひとつのメソッドである force_encoding は、この変換処理を行わずにエンコーディング情報だけを変更します。

例:

"abc½½½".force_encoding("iso-8859-1")

利用可能なエンコーディングの一覧は、Encoding.aliases メソッドで確認できます。

まとめ

この記事では、コンピュータがエンコーディングテーブルを使って数字から文字を作り出す仕組みを学びました。さらに、RubyにおけるASCIIとUnicodeの扱い方、そして encode メソッドによるエンコーディング変換の方法まで理解できましたね。

さあ、エディタを開いて、実際にコードを書きながら練習してみましょう 😃

最後までお読みいただきありがとうございました。

  1. Rubyで学ぶ挿入ソート:仕組みから計算量まで徹底解説

    ※本記事は、Rubyでさまざまなソートアルゴリズムを実装するシリーズの第4回です。第1回ではバブルソート、第2回では選択ソート、第3回ではマージソートを取り上げました。データのソート手法をさまざまな角度から探っていくシリーズもいよいよ折り返し地点。今回は挿入ソート(Insertion Sort)に焦点を当てます。挿入ソートには魅力的な特徴がたくさんあります。まず、挿入ソートは安定(stable)なアルゴリズムです。つまり、同じキーを持つ要素同士の相対的な順序が入れ替わることがありません。また、インプレース(in-place)アルゴリズムでもあるため、ソート結果を保存するための新しい配列を作成す

  2. Rubyの文字列フォーマット入門:%演算子と書式指定子の使い方

    この記事では、Rubyで文字列をフォーマットする方法について詳しく解説します。 なぜ文字列のフォーマットが必要なのでしょうか?例えば、10未満の数値にも先頭にゼロを付けて表示したい場合(01、02、03など)、あるいはコンソール出力を見やすいように桁を揃えて整形したい場合などが挙げられます。 他の言語ではprintf関数を使って文字列をフォーマットできます。C言語を使ったことがある人なら馴染み深いでしょう。printfでは、書式指定子(フォーマット指定子)のリストと、変数や値のリストを定義して使用します。 Rubyでの文字列フォーマットの基本 Rubyでもsprintfメソッドが利用可能ですが