
コンピュータプログラミングにおいて、文字列は伝統的に文字のシーケンスであり、リテラル定数または何らかの変数として扱われます。後者の場合、要素を変更したり長さを変更したりできる場合もあれば、作成後に固定される場合もあります。文字列は多くの場合、バイト(またはワード)の配列データ構造として実装され、文字エンコーディングを使用して、通常は文字である要素のシーケンスを格納します。より一般的には、文字列は文字以外のデータのシーケンス(またはリスト)を表す場合もあります。
使用するプログラミング言語と具体的なデータ型によっては、文字列として宣言された変数は、あらかじめ定められた最大長でメモリに静的に割り当てられる場合もあれば、可変個の要素を保持できるように動的に割り当てられる場合もある。
ソースコードに文字列がそのまま出現する場合、それは文字列リテラルまたは匿名文字列と呼ばれます。[ 1 ]
数理論理学や理論計算機科学で使用される形式言語では、文字列とは、アルファベットと呼ばれる集合から選択された記号の有限列のことである。
文字列の主な目的は、単語や文などの人間が読めるテキストを格納することです。文字列は、コンピュータプログラムからプログラムのユーザーに情報を伝えるために使用されます。[ 2 ]プログラムは、ユーザーから文字列入力を受け取ることもできます。さらに、文字列は、文字として表現されているものの、人間が読むことを意図していないデータを格納することもできます。
文字列の例とその用途:
file upload completeに表示する文字列です。プログラムのソースコードでは、このメッセージは文字列リテラルとして表示されるでしょう。I got a new job todayサービスのステータス更新としての「 」など。文字列リテラルの代わりに、ソフトウェアはこの文字列をデータベースに保存する可能性が高い。AGATGCCGTの核酸配列を表す「 」のようなアルファベットデータ。[ 3 ]?action=editURLクエリ文字列の " など。これらは、人間が多少読みやすいように意図されていることが多いが、主な目的はコンピュータとの通信である。「文字列」という用語は、文字以外のデータやコンピュータ記録のシーケンス( 「ビット列」など)を指す場合もありますが、特に指定がない場合は文字の列を指します。[ 4 ]
「string」という言葉を、一列、連続、または連続して並べられたあらゆる項目を意味する言葉として使うのは、何世紀も前から行われてきました。[ 5 ] [ 6 ] 19世紀の植字では、植字工は「string」という用語を紙に印刷された活字の長さを表すために使用し、植字工の給料を決定するためにその長さが測定されました。[ 7 ] [ 4 ] [ 8 ]
「文字列」という言葉を「一定の順序で並んだ記号や言語要素の列」という意味で使用するようになったのは、記号の意味を脇に置いて記号体系の形式的な振る舞いについて語るために、数学、記号論理学、言語理論から生まれたものです。 [ 4 ]
例えば、論理学者のC.I.ルイスは1918年に次のように書いています。[ 9 ]
数学的体系とは、認識可能な記号の列の集合であり、その列の一部は最初に取得され、残りの列は記号に割り当てられた意味とは無関係な規則に従って実行される操作によって導出されるものである。体系が音や匂いではなく「記号」で構成されていることは重要ではない。
Jean E. Sammetによると、コンピュータ向けの「最初の現実的な文字列処理およびパターンマッチング言語」は1950 年代のCOMITであり、続いて1960 年代初頭のSNOBOL言語が登場した。 [ 10 ]
文字列データ型は、形式的な文字列の概念に基づいてモデル化されたデータ型です。文字列は非常に重要で便利なデータ型であるため、ほぼすべてのプログラミング言語で実装されています。一部の言語ではプリミティブ型として、他の言語では複合型として利用できます。ほとんどの高級プログラミング言語の構文では、文字列(通常は何らかの方法で引用符で囲まれている)が文字列データ型のインスタンスを表すことができます。このようなメタ文字列は、リテラルまたは文字列リテラルと呼ばれます。
形式的な文字列は任意の有限長を持つことができますが、実際のプログラミング言語では、文字列の長さは人為的な最大値に制限されることがよくあります。一般に、文字列データ型には 2 種類あります。固定長文字列は、コンパイル時に決定される固定の最大長を持ち、この最大長が必要かどうかに関わらず同じ量のメモリを使用します。可変長文字列は、長さが任意に固定されておらず、実行時の実際の要件に応じて可変量のメモリを使用できます (メモリ管理を参照)。現代のプログラミング言語のほとんどの文字列は可変長文字列です。もちろん、可変長文字列であっても、使用可能なメモリ量によって長さが制限されます。文字列の長さは、別の整数として格納することも (これにより、長さに人為的な制限が加わる可能性があります)、C 言語のようにすべてのビットがゼロの文字値である終端文字によって暗黙的に格納することもできます。下記の「ヌル終端」も参照してください。
文字列データ型は従来、文字ごとに1バイトを割り当てており、文字セットは地域によって異なっていたものの、文字エンコーディングは十分に似通っていたため、プログラマーはしばしばこれを無視することができました。これは、プログラムが特別に扱う文字(ピリオド、スペース、コンマなど)が、プログラムが遭遇するすべてのエンコーディングで同じ位置にあったためです。これらの文字セットは通常、ASCIIまたはEBCDICに基づいていました。あるエンコーディングのテキストを別のエンコーディングを使用するシステムで表示すると、テキストはしばしば文字化けしましたが、多くの場合、ある程度は読み取ることができたため、一部のコンピューターユーザーは文字化けしたテキストを読むことを覚えました。
中国語、日本語、韓国語(総称してCJKと呼ばれる)などの表意文字言語では、適切な表現のために256文字(1文字あたり8ビットバイトのエンコーディングの限界)をはるかに超える文字数が必要です。従来の解決策は、ASCIIには1バイト表現、CJKの表意文字には2バイト表現を使用することでした。これらを既存のコードで使用すると、文字列のマッチングや切り取りに問題が発生し、その深刻度は文字エンコーディングの設計方法によって異なりました。EUCファミリーなどの一部のエンコーディングでは、ASCII範囲内のバイト値がそのASCII文字のみを表すことが保証されているため、これらの文字をフィールド区切り文字として使用するシステムではエンコーディングが安全です。ISO -2022やShift-JISなどの他のエンコーディングでは、このような保証がないため、バイトコードによるマッチングが安全ではありません。これらのエンコーディングは「自己同期」もしていなかったため、文字境界を見つけるには文字列の先頭に戻る必要があり、2つの文字列を貼り付けると2番目の文字列が破損する可能性がありました。
Unicode は状況をいくらか単純化しました。現在、ほとんどのプログラミング言語には Unicode 文字列用のデータ型があります。Unicode が推奨するバイトストリーム形式であるUTF-8は、古いマルチバイトエンコーディングで上記のような問題が発生しないように設計されています。UTF-8、UTF-16、UTF-32 では、プログラマーは固定サイズのコード単位が「文字」とは異なることを認識する必要があります。現在の主な問題は、この違いを隠蔽しようとする API の設計が不適切であることです (UTF-32 ではコードポイントが固定サイズになりますが、これらはコードを構成するため「文字」ではありません)。
C++、Perl、Ruby などの一部の言語では、通常、文字列が作成された後でもその内容を変更することができます。これらは可変文字列と呼ばれます。Java 、JavaScript、Lua、Python、Goなどの他の言語では、値は固定されており、変更を加える場合は新しい文字列を作成する必要があります。これらは不変文字列と呼ばれます。不変文字列を持つこれらの言語の中には、Java や.NETの、スレッドセーフな Java 、Cocoaのように、可変の別の型も提供しているものがあります。不変性には利点と欠点があります。不変文字列では、非効率的に多くのコピーを作成する必要があるかもしれませんが、よりシンプルで完全にスレッドセーフです。StringBuilderStringBufferNSMutableString
文字列は通常、バイト配列、文字配列、またはコード単位配列として実装され、個々の単位や部分文字列(固定長の文字を含む)に高速にアクセスできるようになっています。Haskellなどの一部の言語では、代わりに連結リストとして実装されています。
JavaScriptやPHPなど、多くの高水準言語は文字列を基本データ型として提供していますが、 JavaやC#のように、文字列を複合データ型として提供し、リテラルを記述するための特別な言語サポートを備えている言語もあります。
C、Prolog、Erlangなどの一部のプログラミング言語では、専用の文字列データ型を実装せず、代わりに文字列を文字コードのリストとして表現するという慣習を採用しています。専用の文字列型を持つプログラミング言語であっても、文字列は通常、整数やその他の値のリストと同様に、文字コードのシーケンスとして反復処理できます。
文字列の表現方法は、使用する文字セットと文字エンコーディング方式に大きく依存します。古い文字列実装は、ASCIIで定義された文字セットとエンコーディング、あるいはISO 8859シリーズのようなより新しい拡張規格に対応するように設計されていました。現代の実装では、Unicodeで定義された豊富な文字セットに加え、UTF-8やUTF-16といった多様な複雑なエンコーディング方式がよく用いられています。
バイト列という用語は通常、文字のみの文字列やビット列などではなく、汎用的なバイト列を指します。バイト列は、バイトが任意の値を取ることができ、あらゆるデータをそのまま格納できることを暗示しており、終端値として解釈される値は存在しないことを意味します。
ほとんどの文字列実装は、対応する文字の文字コードを格納するエントリを持つ可変長配列と非常によく似ています。主な違いは、特定のエンコーディングでは、1つの論理文字が配列内の複数のエントリを占める場合があることです。たとえば、UTF-8では、単一のコード(UCSコードポイント)が1バイトから4バイトまでを占め、1つの文字が任意の数のコードを占めることができます。このような場合、文字列の論理長(文字数)は、配列の物理的な長さ(使用バイト数)とは異なります。UTF -32は、この問題の前半部分を回避します。
文字列の長さは、実際の文字を格納するストレージとは別のドープベクトルに格納できます。IBM PL/I (F) コンパイラは、可変長文字列と文字列パラメータの受け渡しに文字列ドープベクトル[ 11 ] (SDV) を使用しました。SDV には現在の長さと最大長が格納され、文字列本体とは隣接していません。PL/I (F) 以降、IBM は長さプレフィックス付き文字列を採用し、SDV の使用を廃止しました。
文字列の長さは、特別な終端文字を使用することで暗黙的に格納できます。多くの場合、これはすべてのビットがゼロであるヌル文字(NUL) であり、これは人気の高いC プログラミング言語で使用され、維持されている慣習です。[ 12 ]したがって、この表現は一般的にC 文字列と呼ばれます。n 文字の文字列のこの表現はn + 1 のスペース (終端文字のために 1)を占有するため、暗黙的なデータ構造となります。
終端文字列では、終端コードは文字列内で使用可能な文字ではありません。長さフィールドを持つ文字列にはこの制限がなく、任意のバイナリデータを格納できます。
10バイトのバッファに格納されたヌル終端文字列の例と、そのASCII(またはより現代的なUTF-8)表現(8ビット16進数)を以下に示します。
上記の例の文字列「FRANK」の長さは5文字ですが、6バイトを占めます。終端文字の後の文字は表現の一部ではなく、他のデータの一部であるか、単なるゴミデータである可能性があります。(この形式の文字列は、宣言に使用された元のアセンブリ言語ディレクティブにちなんで、ASCIZ文字列と呼ばれることもあります。)
文字列の終端にヌル以外の特殊バイトを使用する方法は、歴史的にハードウェア[ a ]とソフトウェアの両方で見られてきましたが、その値が印刷文字でもある場合もありました。$は多くのアセンブラシステムで使用され、はCDC:システムで使用され(この文字の値はゼロでした)、ZX80はBASIC言語の文字列区切り文字であったため[ 15 ]を使用しました。"
やや似た例として、 IBM 1401のような「データ処理」マシンでは、文字列の左側を区切るために特別なワードマークビットが使用され、右側から処理が開始されました。このビットは、文字列の他の部分ではすべてクリアされている必要がありました。つまり、IBM 1401は7ビットのワードを持っていましたが、この機能を利用して7番目のビットの割り当てを上書きし、(例えば)ASCIIコードを処理しようと考えた人はほとんどいませんでした。
初期のマイクロコンピュータソフトウェアは、ASCIIコードが最上位ビットを使用しないという事実に依存しており、文字列の終わりを示すためにそれを設定していました。出力前に0にリセットする必要があります。[ 16 ]
文字列の長さは、例えば文字列の先頭に長さをバイト値として付加するなどして、明示的に格納することもできます。この慣習は多くのPascal方言で使用されており、そのため、このような文字列をPascal文字列またはP文字列と呼ぶ人もいます。文字列の長さをバイトとして格納すると、文字列の最大長は255に制限されます。このような制限を回避するために、改良されたP文字列の実装では、文字列の長さを格納するために16ビット、32ビット、または64ビットのワードを使用します。長さフィールドがアドレス空間をカバーする場合、文字列は使用可能なメモリによってのみ制限されます。
長さが制限されている場合、通常はマシンワードという一定スペースでエンコードできるため、暗黙のデータ構造が実現し、n + k のスペースを占有します。ここで、kはワード内の文字数です (64 ビット マシン上の 8 ビット ASCII の場合は 8、32 ビット マシン上の 32 ビット UTF-32/UCS-4 の場合は 1 など)。長さが制限されていない場合、長さ n をエンコードするにはlog ( n ) のスペースが必要になります (固定長コードを参照)。そのため、長さ接頭辞付き文字列は簡潔なデータ構造であり、長さnの文字列をlog( n ) + n のスペースでエンコードします。
後者の場合、長さプレフィックスフィールド自体には固定長がないため、文字列が長くなり長さフィールドを増やす必要が生じた場合は、実際の文字列データを移動する必要があります。
以下は、10バイトのバッファに格納されたPascal文字列と、そのASCII/UTF-8表現です。
オブジェクト指向言語を含む多くの言語では、文字列を次のような内部構造を持つレコードとして実装しています。
public final class String { private unsigned long length ; // 文字列の長さprivate UniquePointer < char [] > text ; // 明示的な所有権// 公開メソッド... }ただし、実装は通常隠蔽されているため、文字列へのアクセスと変更はメンバ関数を介して行う必要があります。textは動的に割り当てられたメモリ領域へのポインタであり、必要に応じて拡張される場合があります。文字列 (C++)も参照してください。
文字終端コードと長さコードはどちらも文字列を制限します。たとえば、ヌル文字(NUL)を含むC文字配列は、C文字列ライブラリ関数で直接処理することはできません。長さコードを使用する文字列は、長さコードの最大値に制限されます。
これらの制約はどちらも、巧妙なプログラミングによって克服できる。
文字終端に伴う問題がなく、原理的には長さコードの制約を克服できるデータ構造と、それらを操作する関数を作成することが可能です。また、ランレングス符号化(繰り返し文字を文字値と長さで置き換える)やハミング符号化の手法を用いて、表現される文字列を最適化することも可能です。
これらの表現方法は一般的ですが、他にも可能です。ロープを使用することで、挿入、削除、連結などの特定の文字列操作をより効率的に行うことができます。
テキストエディタの中核となるデータ構造は、編集中のファイルの現在の状態を表す文字列(文字のシーケンス)を管理するものです。その状態は単一の長い連続した文字配列に格納することもできますが、一般的なテキストエディタでは、代わりにギャップバッファ、行のリンクリスト、ピーステーブル、ロープなどの別の表現をシーケンスデータ構造として使用し、挿入、削除、以前の編集の取り消しなどの特定の文字列操作をより効率的にしています。[ 17 ]
文字列のメモリレイアウトとストレージ要件の違いは、文字列データにアクセスするプログラムのセキュリティに影響を与える可能性があります。終端文字を必要とする文字列表現は、コーディングエラーや攻撃者による意図的なデータ改ざんによって終端文字が存在しない場合、バッファオーバーフローの問題に陥りやすい傾向があります。長さフィールドを別個に持つ文字列表現も、長さが操作可能な場合は同様に脆弱性があります。このような場合、文字列データにアクセスするプログラムコードは、文字列メモリの制限範囲外のデータに誤ってアクセスしたり変更したりしないように、境界チェックを行う必要があります。
文字列データは、プログラムへのユーザー入力から取得されることが多い。そのため、プログラムは文字列が期待される形式であることを確認するために、文字列の検証を行う責任がある。ユーザー入力の検証を不十分または全く行わないと、プログラムはコードインジェクション攻撃に対して脆弱になる可能性がある。
文字列を、人間が読みやすく、かつ機械が処理することを目的としたテキストファイル内に埋め込む必要がある場合があります。これは、例えばプログラミング言語のソースコードや設定ファイルなどで必要となります。このような場合、NULL文字は通常は表示されず(印刷不可)、キーボードから入力するのが難しいため、終端文字としては適していません。また、文字列の長さを手動で計算して追跡するのは面倒でエラーが発生しやすいため、文字列の長さを保存することも不便です。
よく用いられる表現方法は以下の2つです。
"str"または ASCII 0x27 一重引用符)で囲まれた文字列で'str'、ほとんどのプログラミング言語で使用されています。引用符自体、改行文字、印刷不可文字などの特殊文字を含めるために、通常はバックスラッシュ文字(ASCII 0x5C)を接頭辞とするエスケープシーケンスが用意されています。文字列は文字列としてよく使われますが、コンピュータサイエンスにおける文字列は、同種のデータ列全般を指す場合もあります。例えば、ビット列やバイト列は、通信媒体から取得した非テキスト形式のバイナリデータを表すのに使用できます。このデータは、アプリケーションのニーズ、プログラマの希望、使用するプログラミング言語の機能に応じて、文字列固有のデータ型で表現される場合とされない場合があります。プログラミング言語の文字列実装が8ビットクリーンでない場合、データ破損が発生する可能性があります。
C言語プログラマーは、「文字列」(定義上常にヌル終端される「文字の文字列」)と「文字の配列」(同じ配列に格納される場合もあるが、多くの場合ヌル終端されない)を明確に区別します。このような文字の配列に対してC言語の文字列処理関数を使用すると、多くの場合うまく機能するように見えますが、後々セキュリティ上の問題につながります。[ 18 ] [ 19 ] [ 20 ]
文字列を処理するためのアルゴリズムは数多く存在し、それぞれにさまざまなトレードオフがあります。競合するアルゴリズムは、実行時間、ストレージ要件などに関して分析できます。文字列処理に使用されるアルゴリズムとデータ構造の理論に対して、 1984 年にコンピュータ科学者のZvi Galilが文字列学という名前を造語しました。 [ 21 ] [ 22 ] [ 23 ]
アルゴリズムのカテゴリには以下のようなものがあります。
高度な文字列アルゴリズムは、接尾辞木や有限状態機械など、複雑なメカニズムやデータ構造を採用することが多い。
文字列は非常に便利なデータ型であるため、文字列処理アプリケーションを簡単に記述できるように設計された言語がいくつかあります。例として、以下の言語が挙げられます。
多くのUnixユーティリティは単純な文字列操作を実行でき、強力な文字列処理アルゴリズムを容易にプログラミングするために利用できます。ファイルや有限ストリームは文字列として扱うことができます。
マルチメディア制御インターフェース、組み込みSQL、printfなどの一部のAPIは、解釈されるコマンドを保持するために文字列を使用します。
Perl、Python、Ruby、Tclなどの多くのスクリプト言語は、テキスト操作を容易にするために正規表現を使用します。Perlは特に正規表現の使用で知られており、[ 24 ]他の多くの言語やアプリケーションはPerl互換の正規表現を実装しています。
PerlやRubyなどの一部の言語は文字列補間をサポートしており、任意の式を評価して文字列リテラルに含めることができます。
文字列関数は、文字列を作成したり、可変文字列の内容を変更したりするために使用されます。また、文字列に関する情報を照会するためにも使用されます。関数の種類と名前は、使用するプログラミング言語によって異なります。
文字列関数の最も基本的な例は、文字列の長さを返す関数です。これは、文字列の長さ(終端文字や文字列の内部構造情報は含まない)を返す関数で、文字列を変更しません。この関数は、多くの場合length、、、lenまたはという名前が付けられますsize。たとえば、length("hello world")は 11 を返します。もう 1 つの一般的な関数は連結で、2 つの文字列を連結して新しい文字列を作成します。これは多くの場合、加算演算子 + を使用します。
一部のマイクロプロセッサの命令セットアーキテクチャには、ブロックコピーなどの文字列操作を直接サポートする機能が含まれています(例:Intel x86mREPNZ MOVSB)。[ 25 ]
させては、アルファベットと呼ばれる、明確に区別できる有限個の記号(文字とも呼ばれる)の集合である。文字列(または単語[ 26 ]または式[ 27 ])は、は、[ 28 ]例えば、、 それからは文字列です。
紐の長さは、(数列の長さ)は任意の非負整数であり、しばしば次のように表記されます。.空文字列は、長さ、そして、と表記されるまたは[ 28 ] [ 29 ]
すべての文字列の集合長さと表記される例えば、、 それから。 我々は持っていますすべてのアルファベットについて。
すべての文字列の集合任意の長さのクリーネ閉包はそして、と表記される。 に関しては、
例えば、、 それからセットはそれ自体は可算無限であり、各要素はは有限長の文字列です。
弦のセット(つまり、)は、例えば、偶数個のゼロを含む文字列の集合、は、。
連結は重要な二項演算です任意の2つの文字列についてそしてでそれらの連結は、記号のシーケンスとして定義されます。続いて文字のシーケンス、そして、と表記される例えば、(つまり、英語の小文字アルファベット)、 そして、 それからそして。
文字列連結は結合法則を満たすが、非可換な演算である。空文字列は任意の文字列に対して、識別要素として機能します。、したがって、集合はそして連結演算はモノイドを形成し、自由モノイドはによって生成される。さらに、長さ関数はモノイド準同型を定義します。非負整数(つまり関数)、したがって)
紐は部分文字列または因子であると言われている(空の場合もある)文字列が存在する場合そしてそのため関係「は部分文字列である」は、上の部分順序を定義します。最小の要素は空文字列である。
紐は、文字列が存在する場合そのため。 もし空でない、は適切な接頭辞であると言われている対称的に、弦は接尾辞であると言われている文字列が存在する場合そのため。 もし空でない、は、接尾辞と接頭辞は、「~の接頭辞である」と「~の接尾辞である」という関係はどちらも接頭辞の順序です。
文字列の逆順とは、同じ記号を逆順に並べた文字列のことです。例えば、(どこ、、 そしてはアルファベットの記号です)、その逆はは. 自身を反転させた文字列 (例:)は回文と呼ばれ、空文字列と長さ のすべての文字列も含まれます。。
紐回転であると言われているもし例えば、弦回転、 どこそして別の例として、文字列3つの異なる回転があります。それ自体(、)(と)、 そして(と)
文字列の集合に順序を定義することはしばしば有用です。アルファベットが全順序(アルファベット順参照)があり、全順序を定義できます。辞書順と呼ばれる。アルファベット順が完全であれば辞書順は完全だが、アルファベット順が完全であっても、非自明なアルファベットに対しては完全ではない。例えば、そしてすると、辞書順は関係性を含むこの順序付けに関して、例えば無限集合最小要素を持たない。
See Shortlex for an alternative string ordering that preserves well-foundedness. For the example alphabet, the shortlex order is
A number of additional operations on strings commonly occur in the formal theory. These are given in the article on string operations.

Strings admit the following interpretation as nodes on a graph, where is the number of symbols in :
The natural topology on the set of fixed-length strings or variable-length strings is the discrete topology, but the natural topology on the set of infinite strings is the limit topology, viewing the set of infinite strings as the inverse limit of the sets of finite strings. This is the construction used for the p-adic numbers and some constructions of the Cantor set, and yields the same topology.
Isomorphisms between string representations of topologies can be found by normalizing according to the lexicographically minimal string rotation.
String literals (or constants) are called 'anonymous strings'
可変長データには、文字列を記述する「ドープ ベクトル」と呼ばれる関連制御領域があります。ドープ ベクトルには、文字列の最大長と現在の長さのレコードと、文字列の先頭へのポインタが含まれています。ドープ ベクトルは、記述するデータに隣接している必要はありませんが、通常は同じストレージ クラスのストレージを占有します。
彼は「ストリングロジー」という用語を考案しました。これは文字列アルゴリズムのサブフィールドです。
文字列学という用語は、文字列アルゴリズムだけでなくテキストアルゴリズムにも広く使われている愛称である。
{{cite book}}: CS1メンテナンス: 場所の発行元が見つかりません (リンク)の最も有名な強みは、正規表現による文字列操作です。
Σをアルファベットとする。Σ
上の空でない語とは、定義域が
I
n
(ある
n
∈ ℕに対して)で、終域がΣ
である有限列のことである。
ある言語の記号の有限列は、
その言語の
表現と呼ばれる。