Arduino - 字符串

字符串用于存储文本。它们可用于在 LCD 或 Arduino IDE 串行监视器窗口中显示文本。字符串对于存储用户输入也很有用。例如,用户在连接到 Arduino 的键盘上键入的字符。

Arduino 编程中有两种类型的字符串 -

  • 字符数组,与 C 编程中使用的字符串相同。
  • Arduino String,它允许我们在草图中使用字符串对象。

在本章中,我们将学习字符串,对象以及 Arduino 草图中字符串的使用。在本章结束时,你将了解在草图中使用哪种类型的字符串。

字符串字符数组

我们将学习的第一种字符串是由 char 类型的一系列字符组成的字符串。在上一章中,我们了解了数组是什么,它是存储在内存中的相同类型变量的连续系列。字符串是 char 类型的数组。

字符串是一个特殊的数组,在字符串的末尾有一个额外的元素,它总是具有 0(零)值。这称为空终止字符串

字符串字符数组示例

此示例将说明如何创建字符串并将其打印到串行监视器窗口。

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 窗口。

同样的例子可以用更简单的方式编写,如下所示 -

void setup() {
   char my_str[] = "Hello";
   Serial.begin(9600);
   Serial.println(my_str);
}

void loop() {

}

在此草图中,编译器计算字符串数组的大小,并且自动用 null 将字符串终止。长度为 6 个元素的数组由 5 个字符后再跟 0 组成。

操作字符串数组

我们可以在草图中更改字符串数组,如下图所示。

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() {

}

结果

I like coffee and cake
I like coffee
I like coffee and tea

草图按下面的方式工作。

创建和打印字符串

在上面给出的草图中,将创建一个新字符串,然后打印该字符串以在“Serial Monitor”窗口中显示。

缩短字符串

通过用空终止符(2)来替换字符串中的第 14 个字符来缩短字符串。它的数组索引为 13。

打印字符串时,所有字符都打印到新的 null 终止符。其他字符不会消失; 它们仍然存在于内存中,字符串数组仍然是相同的大小。唯一的区别是任何使用字符串的函数只能看到第一个空终止符的字符串。

更改字符串中的字符

最后,草图将 cake 改为 tea (3)。它首先必须使用空格替换类似[13]的 null 终止符,以便将字符串恢复为最初创建的格式。

新字符用 tea 一词覆盖 cake 中的 cak。这是通过覆盖单个字符来完成的。 cakee 被替换为新的 null 终止字符。结果是字符串实际上以两个空字符结束,原始字符串在字符串的末尾,而新的 null 字符替换 cake 中的 e。打印新字符串时没有区别,因为打印字符串的函数在遇到第一个空终止符时会停止打印字符串字符。

操作字符串数组的函数

前面的草图通过访问字符串中的单个字符以手动方式操作字符串。为了更容易操作字符串数组,你可以编写自己的函数来执行此操作,或者使用 C 语言库中的某些字符串函数。

下面给出了操作字符串数组的函数列表

S.No. 函数和描述
1

String()

String 类是版本 0019 的核心部分,允许你以比字符数组更复杂的方式使用和操作文本字符串。你可以连接字符串,附加到它们,搜索和替换子字符串等。它比简单的字符数组需要更多的内存,但它也更有用。

For reference, character arrays are referred to as strings with a small ‘s’, and instances of the String class are referred to as Strings with a capital S. Note that constant strings, specified in "double quotes" are treated as char arrays, not instances of the String class

2

`charAt()`

Access a particular character of the String.

3

`compareTo()`

Compares two Strings, testing whether one comes before or after the other, or whether they are equal. The strings are compared character by character, using the ASCII values of the characters. That means, for example, 'a' comes before 'b' but after 'A'. Numbers come before letters.

4

`concat()`

Appends the parameter to a String.

5

`c_str()`

Converts the contents of a string as a C-style, null-terminated string. Note that this gives direct access to the internal String buffer and should be used with care. In particular, you should never modify the string through the pointer returned. When you modify the String object, or when it is destroyed, any pointer previously returned by `c_str()` becomes invalid and should not be used any longer.

6

`endsWith()`

Tests whether or not a String ends with the characters of another String.

7

`equals()`

Compares two strings for equality. The comparison is case-sensitive, meaning the String "hello" is not equal to the String "HELLO".

8

`equalsIgnoreCase()`

Compares two strings for equality. The comparison is not case-sensitive, meaning the String("hello") is equal to the String("HELLO").

9

`getBytes()`

Copies the string's characters to the supplied buffer.

10

`indexOf()`

Locates a character or String within another String. By default, it searches from the beginning of the String, but can also start from a given index, allowing to locate all instances of the character or String.

11

`lastIndexOf()`

Locates a character or String within another String. By default, it searches from the end of the String, but can also work backwards from a given index, allowing to locate all instances of the character or String.

12

`length()`

Returns the length of the String, in characters. (Note that this does not include a trailing null character.)

13

`remove()`

Modify in place, a string removing chars from the provided index to the end of the string or from the provided index to index plus count.

14

`replace()`

The String `replace()` function allows you to replace all instances of a given character with another character. You can also use replace to replace substrings of a string with a different substring.

15

`reserve()`

The String `reserve()` function allows you to allocate a buffer in memory for manipulating strings.

16

`setCharAt()`

Sets a character of the String. Has no effect on indices outside the existing length of the String.

17

`startsWith()`

Tests whether or not a String starts with the characters of another String.

18

`toCharArray()`

Copies the string's characters to the supplied buffer.

19

`substring()`

Get a substring of a String. The starting index is inclusive (the corresponding character is included in the substring), but the optional ending index is exclusive (the corresponding character is not included in the substring). If the ending index is omitted, the substring continues to the end of the String.

20

`toInt()`

Converts a valid String to an integer. The input string should start with an integer number. If the string contains non-integer numbers, the function will stop performing the conversion.

21

`toFloat()`

Converts a valid String to a float. The input string should start with a digit. If the string contains non-digit characters, the function will stop performing the conversion. For example, the strings "123.45", "123", and "123fish" are converted to 123.45, 123.00, and 123.00 respectively. Note that "123.456" is approximated with 123.46. Note too that floats have only 6-7 decimal digits of precision and that longer strings might be truncated.

22

`toLowerCase()`

Get a lower-case version of a String. As of 1.0, `toLowerCase()` modifies the string in place rather than returning a new.

23

`toUpperCase()`

Get an upper-case version of a String. As of 1.0, `toUpperCase()` modifies the string in place rather than returning a new one.

24

`trim()`

Get a version of the String with any leading and trailing whitespace removed. As of 1.0, `trim()` modifies the string in place rather than returning a new one.

下一个草图使用了一些 C 字符串函数。

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() {

}

结果

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

草图以下列方式工作。

打印字符串

新创建的字符串将打印到“Serial Monitor”窗口,如先前草图中所做。

获取字符串的长度

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 个字符的数组,以便分配可用于操作字符串的内存。

如果数组太小并且我们试图将比该数组大的字符串复制到该数组,则该字符串将被复制到数组的末尾。超出数组末尾的内存可能包含草图中使用的其他重要数据,然后我们的字符串将覆盖这些数据。如果超出字符串末尾的内存超出,则可能会使草图崩溃或导致意外行为。