Arduino - 字符串
字符串用于存储文本。它们可用于在 LCD 或 Arduino IDE 串行监视器窗口中显示文本。字符串还可用于存储用户输入。例如,用户在连接到 Arduino 的键盘上键入的字符。
Arduino 编程中有两种类型的字符串 −
- 字符数组,与 C 编程中使用的字符串相同。
- Arduino 字符串,它允许我们在草图中使用字符串对象。
在本章中,我们将学习字符串、对象以及 Arduino 草图中字符串的使用。在本章结束时,您将了解在草图中使用哪种类型的字符串。
字符串字符数组
我们将学习的第一种字符串类型是一系列 char 类型的字符。在上一章中,我们了解了什么是数组;存储在内存中的一系列连续的相同类型变量。字符串是 char 变量的数组。
字符串是一种特殊数组,在字符串末尾有一个额外的元素,该元素的值始终为 0(零)。这被称为"以空字符结尾的字符串"。
字符串字符数组示例
此示例将展示如何创建字符串并将其打印到串行监视器窗口。
示例
void setup() { char my_str[6]; // 一个足够容纳 5 个字符的字符串的数组 Serial.begin(9600); my_str[0] = 'H'; // 该字符串由 5 个字符组成 my_str[1] = 'e'; my_str[2] = 'l'; my_str[3] = 'l'; my_str[4] = 'o'; my_str[5] = 0; // 第 6 个数组元素是空终止符 Serial.println(my_str); } void loop() { }
以下示例显示了字符串的组成;一个字符数组,其中包含可打印字符,数组的最后一个元素为 0,表示字符串在此处结束。可以使用 Serial.println() 并传递字符串的名称,将字符串打印到 Arduino IDE 串行监视器窗口。
此示例可以更方便地编写,如下所示 −
示例
void setup() { char my_str[] = "Hello"; Serial.begin(9600); Serial.println(my_str); } void loop() { }
在此草图中,编译器计算字符串数组的大小,并自动用零终止字符串。一个长度为六个元素且由五个字符后跟一个零组成的数组的创建方式与上一个草图完全相同。
操作字符串数组
我们可以在草图中更改字符串数组,如以下草图所示。
示例
void setup() { char like[] = "I like coffee and cake"; // 创建字符串 Serial.begin(9600); // (1) 打印字符串 Serial.println(like); // (2) 删除字符串的一部分 like[13] = 0; Serial.println(like); // (3) 将单词替换为字符串 like[13] = ' '; // 用空格替换空终止符 like[18] = 't'; // 插入新单词 like[19] = 'e'; like[20] = 'a'; like[21] = 0; // 终止字符串 Serial.println(like); } void loop() { }
结果
I like coffee and cake I like coffee I like coffee and tea
该草图的工作方式如下。
创建和打印字符串
在上面给出的草图中,创建了一个新字符串,然后将其打印出来以显示在串行监视器窗口中。
缩短字符串
通过将字符串中的第 14 个字符替换为以空字符结尾的零 (2) 来缩短字符串。这是从 0 开始计数的字符串数组中的元素编号 13。
打印字符串时,将打印所有字符,直到新的以空字符结尾的零。其他字符不会消失;它们仍然存在于内存中,并且字符串数组的大小仍然相同。唯一的区别是,任何使用字符串的函数都只能看到第一个空字符结束符之前的字符串。
更改字符串中的单词
最后,该草图将单词"cake"替换为"tea"(3)。它首先必须用空格替换 like[13] 处的空终止符,以便将字符串恢复为最初创建的格式。
新字符用单词"tea"覆盖单词"cake"中的"cak"。这是通过覆盖单个字符来实现的。"cake"中的"e"被替换为新的空终止符。结果是字符串实际上以两个空字符结尾,一个是字符串末尾的原始字符,另一个是替换"cake"中"e"的新字符。这在打印新字符串时没有区别,因为打印字符串的函数在遇到第一个空终止符时会停止打印字符串字符。
操作字符串数组的函数
上一个草图通过访问字符串中的单个字符以手动方式操作字符串。为了更轻松地操作字符串数组,您可以编写自己的函数来执行此操作,或者使用 C 语言库中的某些字符串函数。
S.No. | 函数和描述 |
---|---|
1 |
String() String 类是自版本 0019 起的核心部分,它允许您以比字符数组更复杂的方式使用和操作文本字符串。您可以连接字符串、向其附加内容、搜索和替换子字符串等等。它比简单的字符数组占用更多内存,但也更有用。 作为参考,字符数组被称为带有小写"s"的字符串,String 类的实例被称为带有大写 S 的字符串。请注意,"双引号"中指定的常量字符串被视为字符数组,而不是 String 类的实例 |
2 |
charAt() 访问字符串中的特定字符。 |
3 |
compareTo() 比较两个字符串,测试一个字符串是在另一个字符串之前还是之后,或者它们是否相等。使用字符的 ASCII 值逐个比较字符串。例如,这意味着"a"位于"b"之前但在"A"之后。数字在字母之前。 |
4 |
concat() 将参数附加到字符串。 |
5 |
c_str() 将字符串的内容转换为 C 样式、以空字符结尾的字符串。请注意,这可以直接访问内部字符串缓冲区,应谨慎使用。特别是,您永远不应通过返回的指针修改字符串。当您修改 String 对象或销毁它时,c_str() 先前返回的任何指针都将变为无效,不应再使用。 |
6 |
endsWith() 测试字符串是否以另一个字符串的字符结尾。 |
7 |
equals() 比较两个字符串是否相等。比较区分大小写,这意味着字符串"hello"不等于字符串"HELLO"。 |
8 |
equalsIgnoreCase() 比较两个字符串是否相等。比较不区分大小写,这意味着 String("hello") 等于 String("HELLO")。 |
9 |
getBytes() 将字符串的字符复制到提供的缓冲区。 |
10 |
indexOf() 在另一个字符串中定位字符或字符串。默认情况下,它从字符串的开头搜索,但也可以从给定的索引开始,从而可以找到字符或字符串的所有实例。 |
11 |
lastIndexOf() 在另一个字符串中定位字符或字符串。默认情况下,它从字符串的末尾搜索,但也可以从给定的索引向后搜索,从而可以找到字符或字符串的所有实例。 |
12 |
length() 返回字符串的长度(以字符为单位)。(请注意,这不包括尾随的空字符。) |
13 |
remove() 就地修改字符串,从提供的索引到字符串末尾删除字符,或从提供的索引到索引加计数删除字符。 |
14 |
replace() String replace() 函数允许您用另一个字符替换给定字符的所有实例。您还可以使用 replace 将字符串的子字符串替换为不同的子字符串。 |
15 |
reserve() String reserve() 函数允许您在内存中分配一个缓冲区来处理字符串。 |
16 |
setCharAt() 设置字符串的一个字符。对字符串现有长度之外的索引没有影响。 |
17 |
startsWith() 测试字符串是否以另一个字符串的字符开头。 |
18 |
toCharArray() 将字符串的字符复制到提供的缓冲区。 |
19 |
substring() 获取一个字符串。起始索引是包含的(相应的字符包含在子字符串中),但可选的结束索引是排除的(相应的字符不包含在子字符串中)。如果省略结束索引,子字符串将继续到字符串的末尾。 |
20 |
toInt() 将有效的字符串转换为整数。输入字符串应以整数开头。如果字符串包含非整数,则函数将停止执行转换。 |
21 |
toFloat() 将有效的字符串转换为浮点数。输入字符串应以数字开头。如果字符串包含非数字字符,则函数将停止执行转换。例如,字符串"123.45"、"123"和"123fish"分别转换为 123.45、123.00 和 123.00。请注意,"123.456"近似为 123.46。还请注意,浮点数只有 6-7 位小数,较长的字符串可能会被截断。 |
22 |
toLowerCase() 获取字符串的小写版本。从 1.0 开始,toLowerCase() 会就地修改字符串,而不是返回新的字符串。 |
23 |
toUpperCase() 获取字符串的大写版本。从 1.0 开始,toUpperCase() 会就地修改字符串,而不是返回新的字符串。 |
24 |
trim() 获取字符串的版本,其中删除了所有前导和尾随空格。从 1.0 开始,trim() 会就地修改字符串,而不是返回新的字符串。 |
下一个草图使用了一些 C 字符串函数。
示例
void setup() { char str[] = "This is my string"; // 创建字符串 char out_str[40]; // 此处放置的字符串函数的输出 int num; // 通用整数 Serial.begin(9600); // (1) 打印字符串 Serial.println(str); // (2) 获取字符串的长度(不包括空终止符) num = strlen(str); Serial.print("String length is: "); Serial.println(num); // (3) 获取数组的长度(包括空终止符) num = sizeof(str); // sizeof() 不是 C 字符串函数 Serial.print("Size of the array: "); Serial.println(num); // (4) 复制字符串 strcpy(out_str, str); Serial.println(out_str); // (5) 将字符串添加到字符串末尾(附加) strcat(out_str, " sketch."); Serial.println(out_str); num = strlen(out_str); Serial.print("String length is: "); Serial.println(num); num = sizeof(out_str); Serial.print("Size of the array out_str[]: "); Serial.println(num); } void loop() { }
结果
This is my string String length is: 17 Size of the array: 18 This is my string This is my string sketch. String length is: 25 Size of the array out_str[]: 40
草图的工作方式如下。
打印字符串
新创建的字符串将打印到串行监视器窗口,就像在之前的草图中所做的那样。
获取字符串的长度
strlen() 函数用于获取字符串的长度。字符串的长度仅适用于可打印字符,不包括空终止符。
字符串包含 17 个字符,因此我们在串行监视器窗口中看到打印的 17。
获取数组的长度
运算符 sizeof() 用于获取包含字符串的数组的长度。长度包括空终止符,因此长度比字符串的长度多一个。
sizeof() 看起来像一个函数,但从技术上讲是一个运算符。它不是 C 字符串库的一部分,但在草图中用于显示数组大小和字符串大小(或字符串长度)之间的差异。
复制字符串
strcpy() 函数用于将 str[] 字符串复制到 out_num[] 数组。strcpy() 函数将传递给它的第二个字符串复制到第一个字符串中。该字符串的副本现在存在于 out_num[] 数组中,但仅占用数组的 18 个元素,因此数组中仍有 22 个可用 char 元素。这些可用元素位于内存中的字符串之后。
将字符串复制到数组中,以便我们在数组中有一些额外的空间可用于草图的下一部分,即将字符串添加到字符串的末尾。
将字符串附加到字符串(连接)
草图将一个字符串连接到另一个字符串,这称为连接。这是使用 strcat() 函数完成的。strcat() 函数将传递给它的第二个字符串放在传递给它的第一个字符串的末尾。
连接后,将打印字符串的长度以显示新的字符串长度。然后打印数组的长度以显示我们在 40 个元素长的数组中有一个 25 个字符长的字符串。
请记住,由于以零结尾,25 个字符长的字符串实际上占用了数组的 26 个字符。
数组边界
使用字符串和数组时,在字符串或数组的范围内工作非常重要。在示例草图中,创建了一个长度为 40 个字符的数组,以便分配可用于操作字符串的内存。
如果数组太小,并且我们尝试将大于数组的字符串复制到其中,则该字符串将被复制到数组的末尾。数组末尾以外的内存可能包含草图中使用的其他重要数据,这些数据随后将被我们的字符串覆盖。如果字符串末尾以外的内存超限,则可能导致草图崩溃或导致意外行为。