MATLAB char型:基礎から学ぶ文字列操作

MATLAB char型:基礎から学ぶ文字列操作

MATLABは数値計算に特化した強力なツールですが、データ解析、ファイル入出力、ユーザーインターフェース作成など、様々なタスクにおいて文字列の操作は不可欠です。MATLABでは、文字列を扱うための主要なデータ型として、歴史的に「char型配列(文字配列)」が使われてきました。MATLAB R2016b以降では、より直感的で柔軟な「string型(文字列スカラー)」も導入されましたが、char型は依然として多くの既存コードや一部の関数で利用されており、その理解はMATLABを使いこなす上で非常に重要です。

この記事では、MATLABのchar型に焦点を当て、その基礎から応用的な操作、そしてstring型との比較までを詳細に解説します。豊富なコード例を通じて、char型の扱い方をマスターしましょう。

1. はじめに:MATLABにおける文字列とchar型

MATLABは数値データを中心に扱いますが、プログラミングやデータ処理の多くの場面で文字列が必要になります。例えば、

  • ファイル名の指定
  • グラフのタイトルやラベル
  • ユーザーへのメッセージ表示
  • コマンドの組み立てと実行
  • テキストデータの読み込みと解析
  • 変数名や構造体のフィールド名

などです。これらの文字列をMATLABで扱うための基本的なデータ型がchar型です。

1.1 char型とは?

char型は、文字(character)の配列(array)です。MATLABでは、ほとんどのデータを配列(ベクトル、行列、多次元配列)として扱いますが、char型も例外ではありません。つまり、文字列は1文字ずつのデータが並んだ「文字の配列」として表現されます。

最も一般的なchar型は、1行の文字が並んだ「行ベクトル」としての文字列です。例えば、'hello'という文字列は、'h', 'e', 'l', 'l', 'o' という5つの文字が横一列に並んだ1×5の文字配列と見なされます。

1.2 char型とstring型の違い

MATLAB R2016b以降で導入されたstring型は、より現代的な文字列の扱いを提供します。string型は「文字列スカラー」または「文字列配列」として扱われ、各要素が独立した文字列を持ちます。一方、char型はあくまで「文字の配列」です。

主な違い:

  • 表現: char型はシングルクォート ('')、string型はダブルクォート ("") で囲んで作成します(R2017a以降)。
  • データ構造: char型は文字の配列。複数行を扱う場合は、各行が同じ長さである必要がある(パディングが必要)。string型は文字列の配列。各要素(文字列)は独立した長さを持ちうる。
  • 操作: string型はオブジェクト指向的なアプローチで、ドット (.) 演算子によるメソッド呼び出し(例: "hello".upper())や、文字列の連結にプラス (+) 演算子が使えます。char型は主に専用の関数 (upper('hello'), strcat('hello', 'world')) を使用します。
  • 互換性: 多くの古いMATLAB関数はchar型を前提としています。新しい関数はstring型もサポートしていることが多いですが、char型への変換が必要な場面もあります。

どちらの型を使うべきかは状況によりますが、新しいコードを書く場合や、可変長の文字列を多数扱う場合はstring型が推奨される傾向にあります。しかし、既存コードの理解や、特定の関数を使う際にはchar型の知識が不可欠です。この記事ではchar型に焦点を当てて解説します。

2. char型の基礎

2.1 char型の作成

char型は、シングルクォート ('') で囲むことによって作成します。

“`matlab
% 文字列の作成
myString = ‘Hello, MATLAB!’;

% 作成した変数のクラスを確認
class(myString)
“`

matlab
% 出力例
% ans =
% char

myString変数はchar型として認識されます。

空の文字列:
シングルクォートを2つ連続させることで、空の文字配列を作成できます。

matlab
emptyString = '';
class(emptyString)
size(emptyString)

matlab
% 出力例
% ans =
% char
% ans =
% 1 0

空のchar型は、1行0列の文字配列として扱われます。

特殊文字:
文字列中にシングルクォートを含めたい場合は、シングルクォートを2つ続けて記述します。

matlab
quoteString = 'He said, ''Hello!''';
disp(quoteString);

matlab
% 出力例
% He said, 'Hello!'

バックスラッシュ (\) に続く特殊文字シーケンスも使用できます。一般的なものには、改行 (\n)、タブ (\t) などがあります。

matlab
newLineString = 'Line 1\nLine 2';
fprintf(newLineString); % fprintf関数は特殊文字シーケンスを解釈して表示します

matlab
% 出力例
% Line 1
% Line 2

2.2 char型の表示

char型の変数を表示するには、変数名をコマンドウィンドウにそのまま入力するか、disp関数やfprintf関数を使用します。

“`matlab
myString = ‘Hello, MATLAB!’;

% 変数名をそのまま入力
myString

% disp関数を使用
disp(myString);

% fprintf関数を使用 (書式指定可能、特殊文字シーケンスを解釈)
fprintf(‘%s\n’, myString); % %sは文字列を表示するための書式指定子、\nは改行
“`

これらの方法は、単一の文字列を表示する場合には似ていますが、配列や特殊文字の扱いに違いがあります。

2.3 char型のサイズと形状

char型は文字の配列です。そのサイズや形状は、size関数やlength関数で確認できます。

“`matlab
myString = ‘Hello, MATLAB!’;

% サイズ (行数 x 列数)
size(myString)

% 長さ (要素数、char型ベクトルの場合は列数)
length(myString)
“`

matlab
% 出力例
% ans =
% 1 14
% ans =
% 14

'Hello, MATLAB!'は14文字なので、サイズは1×14、長さは14となります。これは「1行14列の文字配列」つまり「14個の文字からなる行ベクトル」であることを示しています。

複数行のchar配列を作成することも可能ですが、各行の長さは同じである必要があります。長さが異なる場合は、短い行に空白をパディングする必要があります。

“`matlab
% 同じ長さの文字列を縦に結合 (有効なchar配列)
charArray = [‘Row 1’; ‘Row 2’];
size(charArray)
disp(charArray);

% 長さが異なる文字列を縦に結合しようとするとエラー
% invalidArray = [‘Row 1’; ‘Row 22’]; % Error: Dimensions of arrays being concatenated are not consistent.
“`

matlab
% 出力例
% ans =
% 2 5
% Row 1
% Row 2

複数行のchar配列は、各行が同じ長さであるという制約があるため、柔軟性に欠けます。この制約を克服するために、MATLABではセル配列(cell array)やstring型配列がよく使用されます。後述しますが、char関数を使って自動的にパディングして複数行のchar配列を作成する方法もあります。

2.4 char型の要素へのアクセス

char型配列の個々の文字や部分文字列には、インデックス指定 (()) を使ってアクセスできます。MATLABのインデックスは1から始まります。

“`matlab
myString = ‘Hello, MATLAB!’;

% 最初の文字にアクセス
firstChar = myString(1);

% 5番目の文字にアクセス
fifthChar = myString(5);

% 6番目から10番目までの部分文字列にアクセス (スライス)
subString = myString(6:10);

% 最後の文字にアクセス
lastChar = myString(end);

% 結果の表示
disp(firstChar);
disp(fifthChar);
disp(subString);
disp(lastChar);
“`

matlab
% 出力例
% H
% o
% MATLA
% !

複数行のchar配列の場合は、行と列のインデックスを指定します。

“`matlab
charArray = [‘Apple’; ‘Banana’; ‘Cherry’]; % 各行は同じ長さ(6文字)

% 1行目の全体にアクセス
row1 = charArray(1, :);

% 全行の最初の文字にアクセス
firstChars = charArray(:, 1);

% 2行目の3番目の文字にアクセス
char2_3 = charArray(2, 3);

disp(row1);
disp(firstChars);
disp(char2_3);
“`

matlab
% 出力例
% Apple
% ABC
% n

2.5 char型の結合と連結

複数のchar型文字列を結合するには、主に角括弧 ([]) を使用します。横方向の結合(文字列の連結)と、縦方向の結合(複数行の文字配列の作成)が可能です。

横方向の結合(文字列の連結):
複数のchar型文字列を角括弧で並べると、それらは横方向に連結されます。

“`matlab
str1 = ‘Hello’;
str2 = ‘ ‘; % スペースも文字として扱う
str3 = ‘World!’;

% 角括弧で連結
combinedString = [str1 str2 str3];
disp(combinedString);

% 関数 strcat を使用することもできるが、角括弧が一般的
% combinedString_func = strcat(str1, str2, str3);
% disp(combinedString_func);
“`

matlab
% 出力例
% Hello World!

strcat関数も文字列連結に使用できますが、MATLABのドキュメントでは通常、角括弧による連結が推奨されています。

縦方向の結合(複数行の文字配列の作成):
複数のchar型文字列を縦方向に結合して複数行のchar配列を作成する場合、前述のように各行の長さが同じである必要があります。長さが異なる場合はエラーになります。

“`matlab
% 長さが同じ文字列の縦結合
names = [‘Alice’; ‘Bob ‘; ‘Charlie’]; % 全て7文字 (Bobはスペースでパディング)
disp(names);
size(names)

% char関数を使った自動パディング
% char関数は、入力された文字列の中で最も長いものに合わせて、短い文字列の末尾をスペースでパディングします。
names_padded = char(‘Alice’, ‘Bob’, ‘Charlie’);
disp(names_padded);
size(names_padded)
“`

matlab
% 出力例
% Alice
% Bob
% Charlie
% ans =
% 3 7
% Alice
% Bob
% Charlie
% ans =
% 3 7

char関数は、特に異なる長さのchar型文字列を複数行のchar配列にまとめたい場合に便利です。ただし、この形式のchar配列は各行が同じ長さである必要があり、末尾に不要な空白が含まれる可能性があることに注意が必要です。

2.6 char型と数値の変換

char型は文字の配列ですが、コンピュータ内部では各文字は数値(ASCIIコードなど)として表現されています。この数値との変換は、char型を低レベルで理解したり、数値データを文字列として表示したり、逆に文字列中の数値を抽出したりする際に役立ちます。

char型から数値への変換 (ASCIIコード):
double関数を使うと、char型配列の各文字を対応するASCIIコード(double型)に変換できます。

matlab
myString = 'Hello';
asciiCodes = double(myString);
disp(asciiCodes); % ASCIIコードの行ベクトルが表示される

matlab
% 出力例
% 72 101 108 108 111

数値からchar型への変換 (ASCIIコード):
char関数を数値配列に適用すると、対応するASCIIコードを持つ文字のchar型配列を作成できます。

matlab
asciiCodes = [72 101 108 108 111];
myString = char(asciiCodes);
disp(myString);

matlab
% 出力例
% Hello

数値から文字列への変換:
数値(スカラー、ベクトル、行列)を、その数値表現を含むchar型文字列に変換するには、num2str関数を使用します。

“`matlab
myNumber = 123.456;
numberString = num2str(myNumber);
disp(numberString);
class(numberString)

myVector = [10 20 30];
vectorString = num2str(myVector); % デフォルトではスペース区切り
disp(vectorString);
“`

matlab
% 出力例
% 123.456
% ans =
% char
% 10 20 30

num2strは、数値データをグラフのラベルやファイル名の一部として使いたい場合などに非常に便利です。

文字列から数値への変換:
char型文字列に数値が表現されている場合、それを数値型のデータに変換するには、str2num関数やstr2double関数を使用します。

“`matlab
numberString = ‘123.45’;
myNumber = str2num(numberString);
disp(myNumber);
class(myNumber)

% str2doubleは単一の数値文字列変換に特化しており、より堅牢
anotherNumberString = ‘456.78’;
anotherNumber = str2double(anotherNumberString);
disp(anotherNumber);
class(anotherNumber);

% 複数の数値をスペースやカンマで区切った文字列の場合、str2numは数値ベクトルを返すが、str2doubleはNaNを返す
vectorString = ’10 20 30′;
vectorNum_str2num = str2num(vectorString);
disp(vectorNum_str2num); % [10 20 30] が得られる
vectorNum_str2double = str2double(vectorString);
disp(vectorNum_str2double); % NaN が得られる

% カンマ区切りの文字列の場合、str2numはそのままではベクトルにできない
% complexString = ‘1.2, 3.4, 5.6’;
% vectorNum_str2num = str2num(complexString); % エラーまたはNaN
% disp(vectorNum_str2num);

% より複雑な文字列解析には sscanf や textscan が適している
“`

matlab
% 出力例
% 123.4500
% ans =
% double
% 456.7800
% ans =
% double
% 10 20 30
% NaN

str2numは複数の数値がスペース区切りで含まれる文字列を数値ベクトルに変換できますが、複雑な書式には対応できません。str2doubleは単一の数値を変換する場合に推奨されます。より複雑なテキスト形式から数値を抽出するには、後述するsscanftextscan関数がより強力です。

3. char型の操作関数

MATLABには、char型文字列を操作するための多数の組み込み関数が用意されています。ここでは、特によく使用される関数を中心に解説します。

3.1 検索・比較

文字列を検索したり、他の文字列と比較したりするための関数です。

文字列全体の比較:
* strcmp(str1, str2): str1str2完全に一致する場合に真(1)、それ以外の場合に偽(0)を返します。大文字/小文字を区別します。
* strcmpi(str1, str2): str1str2大文字/小文字を区別せずに完全に一致する場合に真(1)、それ以外の場合に偽(0)を返します。

“`matlab
strA = ‘MATLAB’;
strB = ‘MATLAB’;
strC = ‘matlab’;
strD = ‘MATLAB ‘; % 末尾にスペースあり

% strcmpによる比較
strcmp(strA, strB) % 完全に一致 -> 1 (true)
strcmp(strA, strC) % 大文字/小文字が異なる -> 0 (false)
strcmp(strA, strD) % 末尾にスペースがある -> 0 (false)

% strcmpiによる比較 (大文字/小文字無視)
strcmpi(strA, strB) % 一致 -> 1 (true)
strcmpi(strA, strC) % 大文字/小文字無視で一致 -> 1 (true)
strcmpi(strA, strD) % 末尾にスペースがある -> 0 (false)
“`

  • strncmp(str1, str2, n): str1str2最初のn文字が一致する場合に真(1)、それ以外の場合に偽(0)を返します。大文字/小文字を区別します。
  • strncmp(str1, str2, n): str1str2最初のn文字大文字/小文字を区別せずに一致する場合に真(1)、それ以外の場合に偽(0)を返します。

“`matlab
strE = ‘Apples’;
strF = ‘Application’;

% 最初の3文字を比較 (大文字/小文字区別)
strncmp(strE, strF, 3) % ‘App’ vs ‘App’ -> 1 (true)

strG = ‘Orange’;
strH = ‘orange juice’;

% 最初の6文字を比較 (大文字/小文字無視)
strncmpi(strG, strH, 6) % ‘Orange’ vs ‘orange’ -> 1 (true)
“`

部分文字列の検索:
ある文字列が別の文字列に含まれているか、あるいはどの位置にあるかを検索する関数です。

  • contains(str, pattern): strpatternという部分文字列を含んでいる場合に真(1)、それ以外の場合に偽(0)を返します。(R2016b以降推奨の機能ですが、char型にも使えます)
  • startsWith(str, pattern): strpatternで始まっている場合に真(1)。
  • endsWith(str, pattern): strpatternで終わっている場合に真(1)。

“`matlab
text = ‘This is a sample sentence.’;

contains(text, ‘sample’) % ‘sample’を含むか -> 1 (true)
contains(text, ‘example’) % ‘example’を含まないか -> 0 (false)
contains(text, ‘Sample’) % 大文字/小文字を区別するので 0 (false)

startsWith(text, ‘This’) % ‘This’で始まるか -> 1 (true)
endsWith(text, ‘.’) % ‘.’で終わるか -> 1 (true)
endsWith(text, ‘sentence’) % ‘sentence.’で終わるので 0 (false)
“`

これらの関数は、特に大文字/小文字を無視するオプション('IgnoreCase', true)も指定でき、柔軟な検索が可能です。

  • strfind(text, pattern): textの中にpatternという部分文字列が出現する開始インデックスをすべて返します。
  • findstr(text, pattern): strfindと同様ですが、引数の順番を気にせず使用できます(MATLABのドキュメントではstrfindの使用が推奨されています)。

“`matlab
text = ‘This is a test test.’;
pattern = ‘test’;

% 部分文字列 ‘test’ の出現位置を検索
indices = strfind(text, pattern);
disp(indices);
“`

matlab
% 出力例
% 11 16

strfindは、複数の出現位置を一度に知りたい場合に便利です。

正規表現による検索:
より複雑なパターンマッチングには、正規表現を使用する関数群があります。
* regexp(str, expression): 正規表現 expression に一致する部分を検索します。
* regexpi(str, expression): 大文字/小文字を区別しない正規表現検索を行います。

正規表現は強力ですが、学習コストがかかります。簡単な検索には上記の関数を使い、複雑なパターンマッチングが必要な場合にregexpの使用を検討しましょう。

3.2 置換

文字列中の特定の部分を別の文字列に置き換える関数です。

  • strrep(str, old, new): 文字列str中のすべてのoldという部分文字列をnewに置き換えた新しい文字列を返します。

“`matlab
text = ‘This is a test test.’;

% ‘test’ を ‘sample’ に置き換え
newText = strrep(text, ‘test’, ‘sample’);
disp(newText);

% ‘is’ を ‘XYZ’ に置き換え (複数回出現する場合)
anotherText = strrep(text, ‘is’, ‘XYZ’);
disp(anotherText);
“`

matlab
% 出力例
% This is a sample sample.
% ThXYZ XYZ a test test.

strrepは非常に頻繁に使用される関数です。

3.3 変換

文字列の形式を変更したり、不要な文字を取り除いたりする関数です。

  • upper(str): 文字列str中のすべての小文字を大文字に変換します。
  • lower(str): 文字列str中のすべての大文字を小文字に変換します。

matlab
myString = 'Hello World!';
upperString = upper(myString);
lowerString = lower(myString);
disp(upperString);
disp(lowerString);

matlab
% 出力例
% HELLO WORLD!
% hello world!

  • deblank(str): 文字列str末尾にある空白文字をすべて取り除きます。
  • strtrim(str): 文字列str先頭と末尾にある空白文字をすべて取り除きます。

“`matlab
paddedString = ‘ Hello World! ‘;

% 末尾の空白のみ削除
deblankedString = deblank(paddedString);
disp([‘[‘ deblankedString ‘]’]); % []で囲んで空白を確認

% 先頭と末尾の空白を削除
trimmedString = strtrim(paddedString);
disp([‘[‘ trimmedString ‘]’]);
“`

matlab
% 出力例
% [ Hello World!]
% [Hello World!]

deblankは複数行のchar配列を扱う際、char関数でパディングされた末尾の空白を取り除くのに特に便利です。

  • sprintf(format, ...): 書式指定文字列formatに従って、数値をchar型文字列に変換・整形します。これはC言語のprintfに似た機能で、非常に強力です。

“`matlab
% 数値を書式指定して文字列にする
x = 123.45678;
formattedString1 = sprintf(‘Value: %.2f’, x); % 小数点以下2桁
disp(formattedString1);

% 複数の値を整形
item = ‘Laptop’;
price = 999.99;
stock = 15;
formattedString2 = sprintf(‘Item: %s, Price: %.2f, Stock: %d’, item, price, stock);
disp(formattedString2);

% フィールド幅を指定して左/右寄せ
formattedString3 = sprintf(‘Aligned: %10s | %-10s’, ‘Left’, ‘Right’);
disp(formattedString3);
“`

matlab
% 出力例
% Value: 123.46
% Item: Laptop, Price: 999.99, Stock: 15
% Aligned: Left | Right

sprintfは、レポート生成、ファイル名作成、プロットラベル作成など、様々な場面で使われます。主な書式指定子には %s (文字列), %d (整数), %f (浮動小数点数), %.nf (小数点以下n桁の浮動小数点数), %e (指数表記), %% (リテラルな %) などがあります。

  • sscanf(str, format): 文字列strを、書式指定文字列formatに従って解析し、数値や文字列として読み取ります。sprintfの逆の操作にあたります。

“`matlab
dataString = ‘Name: Alice, ID: 101, Score: 85.5’;

% 書式を指定してデータを抽出
% ‘%*s’ は指定された文字列を読み飛ばす
% ‘%s’ は文字列を読み取る
% ‘%d’ は整数を読み取る
% ‘%f’ は浮動小数点数を読み取る
format = ‘Name: %s, ID: %d, Score: %f’;
extractedData = sscanf(dataString, format); % 複数の値を読み取ると列ベクトルになる

% 結果はASCIIコードと数値が混在する可能性があるため注意
disp(char(extractedData(1:5)’)); % ‘Alice’ のASCIIコード -> charに変換して表示
disp(extractedData(6)); % 101
disp(extractedData(7)); % 85.5
“`

sscanfは、固定フォーマットのテキストファイルからデータを読み込む際などに役立ちます。ただし、sscanfは空白などの区切り文字の扱いに癖があるため、より複雑なテキスト解析にはtextscan関数が推奨されることが多いです。

3.4 分割

文字列を特定の区切り文字(デリミタ)で分割する関数です。

  • strsplit(str, delimiter): 文字列strdelimiterで指定された区切り文字で分割し、結果をセル配列として返します。(R2016b以降推奨の機能ですが、char型にも使えます)

“`matlab
csvString = ‘Apple,Banana,Cherry’;
parts_comma = strsplit(csvString, ‘,’);
disp(parts_comma);
class(parts_comma); % 結果はセル配列

spaceString = ‘This is a sentence.’;
parts_space = strsplit(spaceString, ‘ ‘);
disp(parts_space);
“`

matlab
% 出力例
% {'Apple'} {'Banana'} {'Cherry'}
% ans =
% cell
% {'This'} {'is'} {'a'} {'sentence.'}

strsplitは、カンマ区切り(CSV)やタブ区切りなどのデータを処理する際に非常に便利です。結果がセル配列になる点に注意してください(各要素はchar型文字列です)。

4. char型配列(複数行のchar配列)の詳細

前述の通り、char型は文字の配列であり、複数行の文字配列を作成することも可能です。これは、各行が同じ長さの文字列のリストを表現するのに使われます。

4.1 作成方法の再確認

複数行のchar配列を作成する最も一般的な方法は、char関数を使用することです。これにより、入力された文字列の中で最も長いものに合わせて、短い文字列の末尾が自動的に空白でパディングされます。

matlab
cityList = char('Tokyo', 'New York', 'London');
disp(cityList);
size(cityList)

matlab
% 出力例
% Tokyo
% New York
% London
% ans =
% 3 8

この例では、最も長い文字列が'New York' (8文字) なので、'Tokyo''London'は末尾にスペースがパディングされ、3行8列のchar配列が作成されます。

4.2 アクセスと操作

複数行のchar配列は、通常の行列と同様に行と列のインデックス指定でアクセスできます。

“`matlab
cityList = char(‘Tokyo’, ‘New York’, ‘London’);

% 2行目の文字列全体にアクセス
secondCity = cityList(2, :);
disp([‘Second city: [‘ secondCity ‘]’]); % 末尾の空白を含む

% 全行の最初の文字にアクセス
firstLetters = cityList(:, 1);
disp([‘First letters: ‘ firstLetters’]);

% 3行目の2番目の文字にアクセス
char_3_2 = cityList(3, 2);
disp([‘Char at (3,2): ‘ char_3_2]);
“`

matlab
% 出力例
% Second city: [New York]
% First letters: T N L
% Char at (3,2): o

各行はchar型文字列として取り出されます。しかし、cityList(2, :)のように行全体を取り出すと、元の配列のパディングされた空白が含まれたままになります。これらの空白が邪魔な場合は、deblank関数やstrtrim関数を使用する必要があります。

matlab
secondCity_padded = cityList(2, :);
secondCity_trimmed = strtrim(secondCity_padded);
disp(['Trimmed second city: [' secondCity_trimmed ']']);

matlab
% 出力例
% Trimmed second city: [New York]

4.3 char型配列の制約と代替手段

複数行のchar配列は、各行が同じ長さでなければならないという厳しい制約があります。これは、可変長の文字列のリストを扱う場合に非常に不便です。この制約のため、MATLABではchar型配列よりも以下のデータ構造が推奨されることが多いです。

  • セル配列 (Cell Array): 各セルに異なる長さのchar型文字列を格納できます。
    matlab
    cityCell = {'Tokyo', 'New York', 'London'};
    disp(cityCell);
    size(cityCell); % 1x3 のセル配列
    cityCell{2} % 2番目のセルの中身 ('New York') にアクセス
  • string型配列: string型の登場により、可変長の文字列のリストをより直感的に扱えるようになりました。
    matlab
    cityStringArray = ["Tokyo", "New York", "London"];
    disp(cityStringArray);
    size(cityStringArray); % 1x3 の string 配列
    cityStringArray(2) % 2番目の要素 ("New York") にアクセス

したがって、複数の文字列をリストとして扱う場合は、多くの場合、char型配列ではなくセル配列やstring型配列を使用するのが適切です。char型配列が有効なのは、ファイルから読み込んだ固定長の文字列レコードのリストなど、各行の長さが自然に揃っている場合や、古いコードとの互換性が必要な場合などです。

5. char型とstring型の比較と使い分け

MATLABにおける文字列操作を完全に理解するには、char型とstring型の関係性を把握することが重要です。

5.1 主な違いの再確認

特徴 char型 (文字配列) string型 (文字列スカラー/配列)
作成 シングルクォート '...' ダブルクォート "..." (R2017a以降)
データ構造 文字の配列 (行ベクトル、複数行行列) 文字列のスカラー、または文字列のスカラーの配列
複数文字列 各行が同じ長さの行列、またはセル配列 各要素が異なる長さを持てるstring配列
連結 角括弧 []strcat関数 プラス + 演算子、strjoin関数
操作 専用の関数 (upper(), strrep(), など) ドット演算子によるメソッド (.upper(), .replace(), など) および関数
インデックス 文字レベル ('H') 文字列レベル ("Hello")
バージョン MATLABの初期から存在する R2016b以降に導入、R2017a以降でダブルクォートを使用

5.2 どちらを使うべきか?

  • char型を使うべき場面:

    • 既存のMATLABコードがchar型を前提としている場合。
    • 特定の組み込み関数(特に古いものや、sscanfのような低レベルなテキスト処理関数の一部)がchar型のみを受け付ける場合。
    • 文字単位の低レベルな操作が必要な場合(例: 文字列をASCIIコードとして扱う、個々の文字を処理する)。
    • 非常に短い文字列や固定長の文字列を扱う場合。
  • string型を使うべき場面:

    • 新しくMATLABコードを書く場合(特にR2016b以降)。
    • 可変長の文字列のリストを扱う場合(string配列が適しています)。
    • 直感的な文字列操作(プラス演算子による連結、ドット演算子によるメソッド呼び出し)を行いたい場合。
    • テキストデータの読み込み、処理、書き出しを行う場合(string型対応関数が豊富)。

5.3 char型とstring型の相互変換

char型とstring型は、必要に応じて相互に変換できます。

  • char型からstring型へ: string関数を使用します。
    “`matlab
    charString = ‘Hello char!’;
    stringFromChar = string(charString);
    disp(stringFromChar);
    class(stringFromChar);

    % 複数行のchar配列もstring配列に変換できる
    charArray = char(‘Row 1’, ‘Row 2’);
    stringArrayFromChar = string(charArray);
    disp(stringArrayFromChar);
    class(stringArrayFromChar); % string 配列になる
    “`

  • string型からchar型へ: char関数を使用します。
    “`matlab
    stringString = “Hello string!”;
    charFromString = char(stringString);
    disp(charFromString);
    class(charFromString);

    % string配列をchar型に変換すると、複数行のchar配列になる(パディングされる)
    stringArray = [“Apple”, “Banana”, “Cherry”];
    charFromArray = char(stringArray);
    disp(charFromArray);
    class(charFromArray); % char になる
    size(charFromArray); % 3×6
    “`

これらの変換関数を使用することで、char型とstring型が混在する環境でも作業を進めることができます。ただし、可能な限りどちらかの型に統一してコードを書くことが、コードの可読性や保守性を高める上で望ましいです。

6. char型を使った実践例

char型は、MATLABの様々な機能と組み合わせて使用されます。いくつか典型的な例を見てみましょう。

6.1 ファイルパスの操作

ファイル名の指定やパスの組み立てによくchar型が使われます。

“`matlab
% ファイル名と拡張子
fileName = ‘mydata’;
fileExtension = ‘.txt’;

% パスを組み立てる (OSに関わらずパス区切り文字を適切に扱う)
% fullfile 関数は、OSに応じた正しいパス区切り文字を使ってパスを連結します
folderName = ‘data_files’;
filePath = fullfile(folderName, [fileName fileExtension]); % ファイル名を連結してから fullfile に渡す
disp(filePath);

% ファイルの存在チェックなど (ファイルパスは char 型で渡すのが一般的)
if exist(filePath, ‘file’) == 2
disp(‘File exists.’);
else
disp(‘File does not exist.’);
end

% カレントディレクトリのリストを取得 (結果はchar配列またはstring配列)
dirInfo = dir;
% dirInfo は構造体の配列を返す。nameフィールドはファイル/ディレクトリ名 (char型またはstring型)
if ~isempty(dirInfo)
disp(‘Files in current directory:’);
for i = 1:length(dirInfo)
% dirInfo(i).name は char または string
% string() で string に統一してから disp などで表示するのが安全
disp(string(dirInfo(i).name));
end
end
“`

6.2 コマンドの組み立てと実行 (eval 関数)

MATLABコマンドをchar型文字列として組み立て、それを実行するためにeval関数が使われることがあります。ただし、evalはコードの可読性を損ない、セキュリティリスクも伴うため、可能な限り代替手段(関数ハンドル、構造体、セル配列など)を使用することが推奨されます。

“`matlab
% 変数を作成
varA = 10;
varB = 20;

% コマンドを文字列として組み立てる
commandString = ‘result = varA + varB;’;

% 組み立てたコマンドを実行
eval(commandString);

% 結果を確認
disp(result);
“`

この例は単純すぎますが、ループ内で異なる変数名や関数名を使って処理を行いたい場合などにevalが使われることがあります。しかし、現代的なMATLABプログラミングでは、多くの場合evalを避けることができます。

6.3 ユーザー入力の処理

input関数を使ってユーザーからテキスト入力を受け取る場合、デフォルトではchar型文字列として入力されます。

“`matlab
% ユーザーに入力を促す (デフォルトは文字列として受け取る)
userName = input(‘Please enter your name: ‘, ‘s’); % ‘s’ オプションで文字列として確実に受け取る

% 受け取った入力を表示
fprintf(‘Hello, %s!\n’, userName);

% 数値入力を促す場合 (デフォルトは数値として受け取る)
userAge = input(‘Please enter your age: ‘); % ‘s’ オプションがない場合は数値として評価しようとする

% 数値として受け取られたか確認
if isnumeric(userAge)
fprintf(‘You entered the age: %d\n’, userAge);
else
fprintf(‘Invalid input for age.\n’);
end
“`

input関数の第2引数に's'を指定すると、入力されたテキストを数値として評価しようとせず、常にchar型文字列として受け取ります。これは、ユーザーが数値以外のものを入力した場合にエラーになるのを避けたい場合に便利です。数値として扱いたい場合は、str2numstr2doubleで変換する必要があります。

6.4 プロットのタイトル、ラベル、凡例への利用

char型文字列は、MATLABのプロット機能でテキスト要素を指定する際によく使用されます。

“`matlab
x = 1:10;
y = x.^2;

figure;
plot(x, y);

% タイトル、ラベル、凡例にchar型文字列を指定
title(‘Plot of y = x^2’);
xlabel(‘X-axis’);
ylabel(‘Y-axis’);

% 凡例も文字列のセル配列またはstring配列で指定
legend({‘Data Points’}, ‘Location’, ‘northwest’); % セル配列の場合
% legend([“Data Points”], ‘Location’, ‘northwest’); % string配列の場合

% テキスト注釈を追加
text(5, 50, ‘Example point (5, 25)’);
“`

多くのプロット関連関数は、char型文字列とstring型文字列のどちらも引数として受け付けます。

6.5 データファイルの読み書き(簡単なケース)

簡単なテキストファイルの場合、char型文字列として読み書きすることも可能です。

“`matlab
% ファイル名
fileName = ‘sample.txt’;

% 書き込むデータ (char型文字列)
dataToWrite = ‘This is the first line.\n’;
dataToWrite = [dataToWrite ‘This is the second line.’]; % 文字列を連結

% ファイルを開く (書き込みモード ‘w’)
fid = fopen(fileName, ‘w’);

% ファイルに書き込む
if fid ~= -1
fprintf(fid, dataToWrite); % fprintf は文字列をファイルに書き込む
fclose(fid);
disp([‘Successfully wrote to ‘ fileName]);
else
disp([‘Error opening file ‘ fileName]);
end

% ファイルを開く (読み込みモード ‘r’)
fid = fopen(fileName, ‘r’);

% ファイルから読み込む (ファイルの最後まで全て読み込む)
if fid ~= -1
dataRead = fread(fid, ‘*char’)’; % fread を使って文字として読み込み、転置して行ベクトルにする
fclose(fid);
disp([‘Successfully read from ‘ fileName ‘:’]);
disp(dataRead);
else
disp([‘Error opening file ‘ fileName]);
end
“`

fread関数はバイナリデータを読み込むためのものですが、'*char'オプションを指定するとchar型として読み込めます。より複雑なテキストファイル(例えばCSVファイルなど)を扱う場合は、textscanreadtableなどの高レベルな関数を使用する方が効率的です。

7. よくある落とし穴とトラブルシューティング

char型を扱う上で遭遇しやすい問題と、その解決策をいくつか紹介します。

7.1 シングルクォートのエスケープ

文字列中にリテラルなシングルクォートを含めたい場合は、2つ連続して記述する必要があります。

“`matlab
% 正しい書き方
text = ‘It”s a sunny day.’;
disp(text);

% 間違い (エラーになる)
% text = ‘It’s a sunny day.’; % Error: Invalid text character.
“`

7.2 char配列の行の長さの不一致

複数行のchar配列を角括弧[]で作成しようとする際に、各行の長さが異なる場合にエラーになります。

“`matlab
% エラーになる例
% list = [‘Short’; ‘Long string’]; % Error: Dimensions of arrays being concatenated are not consistent.

% char関数で自動パディングを使う
list_padded = char(‘Short’, ‘Long string’);
disp(list_padded);
“`

長さが異なる文字列のリストを扱いたい場合は、セル配列 {} やstring配列 "" を使用するのが最も簡単な解決策です。

7.3 char型と数値の区別

MATLABでは、char型の配列とdouble型の配列は異なります。文字 '1' は数値 1 とは全く別のデータです。

“`matlab
charDigit = ‘1’;
numericDigit = 1;

class(charDigit)
class(numericDigit)

% char型の ‘1’ を数値として比較すると、ASCIIコードで比較される
double(‘1’) % 49
charDigit == 1 % ‘1’ (49) == 1 -> false
charDigit == 49 % ‘1’ (49) == 49 -> true

% 文字列として比較するには strcmp を使う
strcmp(charDigit, ‘1’) % true
“`

文字列中の数値を数値として扱いたい場合は、必ずstr2numstr2doubleで変換してください。

7.4 strcmp== の違い

2つのchar型文字列が同じかどうかを比較する場合、strcmp関数を使うのが正しい方法です。==演算子を使うと、char配列をASCIIコードの数値配列として扱い、要素ごとの比較が行われます。

“`matlab
str1 = ‘abc’;
str2 = ‘abc’;
str3 = ‘abd’;

% 文字列比較 (推奨)
strcmp(str1, str2) % 完全に一致 -> true (1)
strcmp(str1, str3) % 一致しない -> false (0)

% == 演算子による比較 (数値配列としての比較)
str1 == str2
% ans =
% 1 1 1 (‘a’==’a’, ‘b’==’b’, ‘c’==’c’ がそれぞれtrue)

str1 == str3
% ans =
% 1 1 0 (‘a’==’a’, ‘b’==’b’, ‘c’==’d’ がそれぞれ true, true, false)
“`

==は同じ長さのchar配列に対して要素ごとのASCIIコード比較を行い、論理値の配列を返します。文字列全体が一致するかどうかを知りたい場合は、必ずstrcmpstrcmpiを使用してください。

7.5 deblankstrtrim の必要性

char関数で作成された複数行のchar配列や、ファイルから固定長レコードとして読み込んだ文字列などには、末尾に不要な空白が含まれていることがあります。これらの空白は、文字列の比較や結合などで予期しない結果を引き起こす可能性があります。

“`matlab
paddedName = ‘Alice ‘; % 末尾にスペースあり
targetName = ‘Alice’;

% 末尾の空白があると strcmp は false になる
strcmp(paddedName, targetName) % false

% deblank または strtrim で空白を取り除いてから比較する
strcmp(deblank(paddedName), targetName) % true
strcmp(strtrim(paddedName), targetName) % true
“`

文字列を処理する前に、必要に応じてdeblankstrtrimで不要な空白を取り除く習慣をつけましょう。

8. まとめ

この記事では、MATLABのchar型(文字配列)について、その基本的な作成方法、サイズと要素へのアクセス、結合、数値との変換から、様々な操作関数(検索、置換、変換、分割)、複数行char配列の扱い、そしてstring型との比較と使い分けまでを詳細に解説しました。

char型はMATLABの長い歴史の中で中心的な役割を果たしてきたデータ型であり、多くの既存コードや低レベルなファイル操作などで依然として不可欠です。特に、シングルクォートの使用、文字配列としての性質、そして専用の操作関数群を理解することが重要です。

MATLAB R2016b以降ではstring型が導入され、より直感的で柔軟な文字列操作が可能になりました。新しいコードを書く場合や、可変長の文字列リストを扱う場合はstring型の使用が推奨されますが、char型の知識はMATLABプログラマとして必ず身につけておくべき基礎です。

char型とstring型の相互変換方法を理解しておけば、両方の型が混在する環境でもスムーズに作業を進めることができます。

char型に関する知識を深めることで、MATLABでの文字列処理の幅が広がり、より複雑なタスクにも自信を持って取り組めるようになるでしょう。この記事が、あなたのMATLABスキル向上の一助となれば幸いです。

コメントする

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

上部へスクロール