🦑
Arduino の String クラスの使い方
Ruby脳のための早見表
Arduino | Ruby | |
---|---|---|
s.length() | s.length | |
s.toInt() | s.to_i | |
s.toFloat() | s.to_f | |
s.toDouble() | s.to_d [1] | |
a + b | a + b | |
a == b | a == b | |
a.equals(b) | a == b | |
! | s += x | s.concat(x) |
! | s.concat(x) | s.concat(x) |
s[i] | s[i].ord | |
! | s[i] = 'x' | s[i] = "x" |
s.charAt(i) | s[i].ord | |
s.startsWith(x) | s.start_with?(x) | |
s.endsWith(x) | s.end_with?(x) | |
s.indexOf(x) | s.index(x) | |
s.lastIndexOf(x) | s.rindex(x) | |
s.substring(a, b) | s[a..b] | |
a.compareTo(b) | a <=> b | |
! | s.remove(i, count) | s[i, count] = "" |
! | s.replace("a", "xxx") | s.gsub(/a/, "xxx") |
! | s.setCharAt(i, 'x') | s[i] = "x" |
! | s.toLowerCase() | s.downcase! |
! | s.toUpperCase() | s.upcase! |
! | s.trim() | s.strip! |
a.equalsIgnoreCase(b) | a.casecmp?(b) | |
△ | s.reserve(n) | new(capacity: n) |
s.c_str() | [s].pack("p") | |
s.getBytes(x, size) | x.replace(s[...size.pred]) |
特徴と注意
- 直感的に書けて便利
- ただし to で始まるメソッドが破壊系だったりする
コンストラクタ
String("foo") // => "foo"
String('a') // => "a"
String(10) // => "10"
String(10, DEC) // => "10"
String(10, HEX) // => "a"
String(10, BIN) // => "1010"
String(0.555, 2) // => "0.56"
String(true) // => "1"
String(false) // => "0"
String(NULL) // => "0"
ここで 10 を a
にしたりする必要ある? って思うのだけど Arduino のライブラリはこのような謎の仕様が多い。
安全なメソッドたち
length
String("foo").length(); // => 3
toInt, toFloat, toDouble
String(" -123.5555 ").toInt(); // => -1234
String(" -123.5555 ").toFloat(); // => -1234.56
String(" -123.5555 ").toDouble(); // => -1234.56
- 内部で trim している
- 小数点以下第3位を勝手に四捨五入している
比較
String("a") == "b" // => false
String("a") != "b" // => true
String("a") < "b" // => true
String("a") > "b" // => false
String("a") <= "b" // => true
String("a") >= "b" // => false
String("2") == 2 // => false
String("2") == "2" // => true
- 右辺は char な文字列か String のインスタンスであること
- 右辺が文字列系以外だった場合にエラーにはならない
charAt, []
String("01")[-1] // => 0
String("01")[0] // => 48
String("01")[1] // => 49
String("01")[2] // => 0
String("01")[3] // => 0
String("01").charAt(0) // => 48
- 領域外は 0
+
String("a") + "b" // => "ab"
String("a") + 1 // => "a1"
- 右辺は自動的に String でラップしたものとして扱ってくれる
- 数字も文字列化される
- とはいえ
String("1") == 1
は真にならない (それでいい)
compareTo
String("s1").compareTo("s3") // => -2
-
左辺の文字コード - 右辺の文字コード
がそのまま返ってくるので -2 になっている - その点で Ruby の
<=>
とは少し違う
c_str
String a = "01";
char *b = a.c_str();
b[0] = '_';
a // => "_1"
同じ参照なので意図しない破壊に注意する。
startsWith, endsWith
String("abcd").startsWith("ab"); // => true
String("abcd").endsWith("cd"); // => true
equals, equalsIgnoreCase
String("foo").equals("foo"); // => true
String("foo").equalsIgnoreCase("FOO"); // => true
indexOf, lastIndexOf
String("abab").indexOf("ab"); // => 0
String("abab").indexOf("ab", 3); // => -1
String("abab").lastIndexOf("ab"); // => 2
String("abab").lastIndexOf("ab", 0); // => 0
substring
String("012345").substring(2, 5); // => "234"
getBytes, toCharArray
char buf[4];
memset(buf, 'x', sizeof(buf));
String("abcd").getBytes(buf, 2);
buf[0] // => 97
buf[1] // => 0
buf[2] // => 120
buf[3] // => 120
char buf[4];
memset(buf, 'x', sizeof(buf));
String("abcd").toCharArray(buf, 2);
buf[0] // => 97
buf[1] // => 0
buf[2] // => 120
buf[3] // => 120
- 違いがわからない
- コピー先には終端の
\0
も含まれる - そのため実際にコピーされるのは
指定の長さ - 1
になる
破壊系メソッド
concat, +=
String s = "a";
s += "b";
s // => "ab"
String s = "a";
s.concat("b");
s // => "ab"
-
+=
は concat のエイリアスでしかない -
+=
ではなく<<
にしてほしかった
remove
String s = "01234567";
s.remove(3, 2);
s // => "012567"
インデックス 3 から 2 文字削除する。
replace
String s = "abcabc";
s.replace("bc", "___");
s // => "a___a___"
元と先のサイズを合わせる必要はない。
setCharAt, []=
String s = "0123";
s.setCharAt(1, '_');
s[2] = '_';
s[4] = '_';
s // => "0__3"
範囲外には書き込めないためバッファオーバーフローの心配がない。
toLowerCase, toUpperCase
String s = "AbCd";
s.toLowerCase();
s // => "abcd"
String s = "AbCd";
s.toUpperCase();
s // => "ABCD"
to で始まるのは Immutable なメソッドという全言語共通の暗黙ルールが破壊された。
trim
String s = " foo ";
s.trim();
s // => "foo"
よくわからないメソッド
reserve
String s = "";
s.reserve(2);
s += "12345";
s // => "12345"
あらかじめ余裕を持って確保しておけば concat 時のバッファの拡張回数が減るってことかな?
参照
-
require "bigdecimal/util" が必要 ↩︎
Discussion