前回の記事作成したスケッチには改良の余地があります。今回はその対応を行います。
改良の余地というより…
前回の記事で「言い訳キーボード」のスケッチを完成させました。これで一通り終わり…といきたいところですが、もう少しお付き合いください。
冒頭で「スケッチには改良の余地があるのでその対応を行う」と説明しましたが、実は本当の目的は別にあります。文字列の扱い方をもう少し深く習得しておこう、ということが本当の目的です。
Arduinoで電子工作を進めていくと「文字列」を扱うことが多くなってきます。例えば、以下のように文字が表示できる「液晶モジュール」という部品が売られています。それほど高価なものではないので(300円〜1000円程度)、何か文字を表示したい時に気軽に使えます。
このような液晶モジュールを使うと、センサで測定した気温や湿度を表示したり、ゲームの得点を表示したりして、作れるものが広がりそうですよね。
この液晶モジュールでは当然ながら文字列を表示するので、スケッチで文字列の処理が必要になります。また言い訳キーボードでも文字列を扱いますので、今回と次回の記事で文字列の扱い方をもう少し深く習得しておこう、というわけです。
C言語の文字列とArduinoの文字列
これから説明する内容は、C言語の文字列ではなく、Arduino専用の文字列の扱い方になります。
すでにご存知の方もいるかもしれませんが、C言語で文字列を扱うにはかなり難しい知識が必要になります。これからC言語の文字列の説明をしようとすると、それだけで1つのシリーズ記事になってしまうほどです。
ところで、Arduinoは簡単に電子工作&プログラミングができるように開発されたシステムです。そのため、文字列も扱いやすいように工夫がされています。
もし、Arduinoでの文字列の扱いがC言語そのままだとすると、例えば文字列を液晶モジュールに表示したいだけでも、C言語の難しい文字列処理のプログラミングが必要となってしまいます。これではとても簡単なシステムとは言えなくなってしまいますよね。
そこで、Arduinoでは文字列を簡単に扱えるようなライブラリが提供されています。このライブラリはシステムにデフォルトで入っていますのですぐに使えます。
今回と次回の記事ではその文字列を扱うライブラリについて習得していきます。
ところで、習得する文字列の処理はArduino専用なので、他のプログラミング言語を習得するときにまた新しいことを覚える必要が出てくるのではないか、と心配になってしまうかもしれません。
でも安心してください。PythonやJavaScriptなどの人気のあるプログラミング言語の文字列の扱い方は、Arduinoの文字列ライブラリにかなり似ています。Arduinoの文字列処理を一度経験したあと、Pythonのプログラムを見ると「あれ?どこかでみたことがある」って感じになると思います。逆にC言語の文字列の扱い方をするプログラミング言語は今や少数派になってきています。
ということで、Arduinoの文字列ライブラリをしっかり習得していきましょう!
Stringライブラリ
Arduinoでは、文字列を扱うために「Stringライブラリ」が用意されています。「String」とは、日本語で「文字列」という意味です。そのものって感じですね。
このライブラリはデフォルトで利用できますので、ヘッダファイルをインクルードする必要はありません。
Stringライブラリの使用方法
Arduinoの文字列処理はライブラリとして用意されていますので、クラスからインスタンスを生成する必要があります。
そこでStringライブラリの前に、以前出てきたSwitchクラスのインスタンス生成について復習しておきましょう。
このように書くと、意味としては「Switchというクラス(型)でhidariSwitchという名前のインスタンスを生成してください。実際のスイッチは23番ピンに接続しています」という意味になりました。
ここで注目していただきたい点があります。それはhidariSwitch
というインスタンスを生成するときに、引数は実際のスイッチが接続されているピン番号であったことです。
これから、Stringクラスのインスタンスを生成する方法を説明しますが、当然ながら引数はSwitchクラスと異なります。この点に注意して読み進めてみてください。
Stringクラスのインスタンスは以下のように生成します。
例えば以下のように使います。
う〜ん、これだけだと何をしたいのかよくわからないですし、何が便利なのかもよくわからないですよね。
それでは、これから具体的に生成したインスタンスの使い方を見ていきましょう。
Stringクラスから生成したインスタンスの基本的な使い方
先ほど、以下のようにStringクラスのインスタンスを生成しました。
String iiwake( "okitara" );
このように生成すると、iiwake
というインスタンスを普通の文字列のように扱うことができます。
例えば、以下のようにシリアルモニタを使用することができます。
String iiwake( "okitara" );
Serial.println( iiwake );
このスケッチを実行すると、シリアルモニタには以下のように「okitara」と表示されます。
okitara
また、クラスから生成したインスタンスですので、メソッドも用意されています。
iiwakeというインスタンスは”okitara”という文字列ですが、この文字列に” atamaga itainode”という文字列を追加したい場合は「concat」というメソッドを使用します。「concat」とは日本語で「連結する」という意味です。
concatメソッドは以下のように使用します。
iiwake.concat( " atamaga itainode" );
それでは、以下のスケッチはどのような結果になるか考えてみてください。
String iiwake( "okitara" );
Serial.println( iiwake );
iiwake.concat( " atamaga itainode" );
Serial.println( iiwake );
このスケッチを実行すると以下のようになります。
okitara
okitara atamaga itainode
スケッチの1行目でStringクラスから「iiwake」というインスタンス名で、「okitara」という文字列のインスタンスを生成します。
3行目でこの「iiwake」インスタンスを引数にSerial.printlnを実行しますので、シリアルモニタには「okitara」が表示されます。
次に、5行目でconcatメソッドを使用して「iiwake」インスタンスに「atamaga itainode」という文字列を追加します。
7行目でその文字列を表示しますので、シリアルモニタには「okitara atamaga itainode」と表示されるわけです。
文字列の「123」と数値の「123」の違い
ところで、Stringクラスのインスタンス生成のところで、引数が数値の場合は、その数値の文字列を生成することになっていました。
文字列の「123」と数値の「123」は何が違うのでしょうか。
以下のスケッチがどうなるか考えてみます。
String moji(123); // 「123」という文字列のインスタンスを生成する
uint16_t suuji = 123; // uint16_t型変数「suuji」に123を代入する
Serial.println( moji );
Serial.println( suuji );
この場合、シリアルモニタには以下のよう表示されます。
123
123
4行目でも5行目でも123を表示するわけです。シリアルモニタ上では、文字列の「123」と数値の「123」は見分けがつきません。
この例を見ると、何が違うのかよくわかりません。でも足し算をすると差がわかります。
String moji_1(123); // 「123」という文字列のインスタンスを生成する
String moji_2(456); // 「456」という文字列のインスタンスを生成する
uint16_t suuji_1 = 123; // uint16_t型変数「suuji_1」に123を代入する
uint16_t suuji_2 = 456; // uint16_t型変数「suuji_2」に456を代入する
Serial.println( moji_1 + moji_2 );
Serial.println( suuji_1 + suuji_2 );
このスケッチを実行すると、シリアルモニタには以下のように表示されます。
123456
579
7行目では、「123」と「456」の文字列を足し算するわけですが、文字列の足し算は単に連結するだけになります。concatメソッドと同じです。
一方8行目では、数値「123」と「456」の足し算になりますので、算術計算となり、結果は 123+456 = 579 という結果になります。
ということで、文字列の「123」と数値の「123」はArduinoは別物として扱いますので意識する必要があります。
Stringクラスの何がいいのか?
ところで、Stringクラスの使い方の概要をいろいろと説明しましたが、何かいいことあるのでしょうか。
だって、やってることは「iiwake」に「okitara」という文字列を設定して使ったり、この文字列に他の文字列を追加したりする程度のことです。大したことしてないですよね。
でも、C言語でこのようなことをすると、ものすごく大変なんです!
例えば、先ほどの例では文字列に文字列を追加しましたが、C言語でこれだけのことをするだけでも大変なんです。C言語では文字列の「+」による足し算(連結)はできません。concatのような命令はありますが、コンピュータ内部のメモリのことを考えてプログラミングする必要があります。間違えるとコンピュータが止まってしまいます。
それでは、次にStringクラスの主要なメソッドを説明します。
Stringクラスの主要メソッド
Stringクラスには多くのメソッドがありますが、以下に主要メソッドをご紹介します。なお、インスタンス名は「moji」としています。
このようなメソッドを使って、液晶モジュールに表示する文字列を簡単に処理できます。
concatメソッド
書き方
moji.concat(文字列);
意味
mojiインスタンスの文字列に、引数「文字列」を追加します。
例
String moji("ABC");
moji.concat("DEF");
Serial.println(moji);
結果
ABCDEF
equalsメソッド
書き方
moji.equals(文字列);
意味
mojiインスタンスの文字列が、引数「文字列」と一致していればtrue、一致していなければfalseを返します。
例
String moji("ABC");
if( moji.equals("ABC") ) {
Serial.println("一致");
} else {
Serial.println("不一致");
}
結果
一致
compareToメソッド
書き方
moji.compareTo(文字列);
意味
mojiインスタンスの文字列を、引数「文字列」と比較して、辞書の順番で「文字列」が前に来る場合は1、後ろに来る場合は-1、一致している場合は0を返します。
例
String moji("ABC");
Serial.println( moji.compareTo("AAA");
Serial.println( moji.compareTo("ABD");
結果
1
-1
lengthメソッド
書き方
moji.length();
意味
mojiインスタンスの文字列の長さを返します。
例
String moji("ABCDEFG");
Serial.println( moji.length() );
結果
7
replaceメソッド
書き方
moji.replace(文字列1, 文字列2);
意味
mojiインスタンスの文字列の中の「文字列1」の部分を「文字列2」に置き換えます。
例
String moji("ABCD");
Serial.println( moji.replace("AB", "ab") );
結果
abCD
substringメソッド
書き方
moji.substring(数値1, 数値2);
意味
mojiインスタンスの文字列の、「数値1」文字目から「数値2」文字目までの文字列を返します。文字列の位置は0から数えます。また、「数値2」が省略された場合は「数値1」文字目から最後までの文字列を返します。
例
String moji("ABCDEFG");
Serial.println( moji.substring(0, 2) );
Serial.println( moji.substring(3) );
結果
ABC
DEFG
trimメソッド
書き方
moji.trim();
意味
mojiインスタンスの文字列の先頭と末尾のスペースを削除します。
例
String moji(" ABC ");
Serial.println( moji.trim() );
結果
ABC
以上が主要メソッドです。
次回の記事ではStringクラスを使って言い訳キーボードのスケッチを見やすくします。
更新履歴
2021.12.18 | 新規投稿 |