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